redis-featureform 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- redis_featureform-3.0.0/PKG-INFO +448 -0
- redis_featureform-3.0.0/README.md +392 -0
- redis_featureform-3.0.0/pyproject.toml +233 -0
- redis_featureform-3.0.0/src/featureform/__init__.py +335 -0
- redis_featureform-3.0.0/src/featureform/_apply_context.py +48 -0
- redis_featureform-3.0.0/src/featureform/_apply_wait.py +183 -0
- redis_featureform-3.0.0/src/featureform/_generated/__init__.py +1 -0
- redis_featureform-3.0.0/src/featureform/_generated/openapi/__init__.py +13 -0
- redis_featureform-3.0.0/src/featureform/_generated/openapi/_internal.py +1631 -0
- redis_featureform-3.0.0/src/featureform/_generated/openapi/github_com_redislabsdev_featureform_internal_rest_types.py +31 -0
- redis_featureform-3.0.0/src/featureform/_generated/openapi/server.py +115 -0
- redis_featureform-3.0.0/src/featureform/_generated/openapi/types.py +365 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/__init__.py +1 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/__init__.py +1 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/__init__.py +1 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/apply_pb2.py +66 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/apply_pb2.pyi +463 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/apply_pb2_grpc.py +147 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/apply_pb2_grpc.pyi +82 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/audit_pb2.py +47 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/audit_pb2.pyi +140 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/audit_pb2_grpc.py +97 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/audit_pb2_grpc.pyi +49 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/catalog_pb2.py +60 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/catalog_pb2.pyi +292 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/catalog_pb2_grpc.py +192 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/catalog_pb2_grpc.pyi +88 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/common_pb2.py +44 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/common_pb2.pyi +128 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/common_pb2_grpc.py +24 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/common_pb2_grpc.pyi +20 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/dataframe_pb2.py +67 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/dataframe_pb2.pyi +342 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/dataframe_pb2_grpc.py +97 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/dataframe_pb2_grpc.pyi +49 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/provider_pb2.py +261 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/provider_pb2.pyi +3013 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/provider_pb2_grpc.py +277 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/provider_pb2_grpc.pyi +106 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/rbac_pb2.py +157 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/rbac_pb2.pyi +1281 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/rbac_pb2_grpc.py +1072 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/rbac_pb2_grpc.pyi +260 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_pb2.py +127 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_pb2.pyi +1529 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_pb2_grpc.py +24 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_pb2_grpc.pyi +20 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_service_pb2.py +215 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_service_pb2.pyi +2295 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_service_pb2_grpc.py +1645 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/resource_service_pb2_grpc.pyi +373 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/secret_provider_pb2.py +83 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/secret_provider_pb2.pyi +607 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/secret_provider_pb2_grpc.py +277 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/secret_provider_pb2_grpc.pyi +106 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/serving_pb2.py +112 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/serving_pb2.pyi +783 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/serving_pb2_grpc.py +146 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/serving_pb2_grpc.pyi +76 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/version_pb2.py +45 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/version_pb2.pyi +127 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/version_pb2_grpc.py +146 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/version_pb2_grpc.pyi +76 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/workspace_pb2.py +65 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/workspace_pb2.pyi +296 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/workspace_pb2_grpc.py +322 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/featureform/v2/workspace_pb2_grpc.pyi +124 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/scheduler/__init__.py +1 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/scheduler/v1/__init__.py +1 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/scheduler/v1/scheduler_pb2.py +180 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/scheduler/v1/scheduler_pb2.pyi +1994 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/scheduler/v1/scheduler_pb2_grpc.py +1145 -0
- redis_featureform-3.0.0/src/featureform/_generated/proto/scheduler/v1/scheduler_pb2_grpc.pyi +301 -0
- redis_featureform-3.0.0/src/featureform/_internal/__init__.py +1 -0
- redis_featureform-3.0.0/src/featureform/_internal/http.py +231 -0
- redis_featureform-3.0.0/src/featureform/_internal/logging.py +299 -0
- redis_featureform-3.0.0/src/featureform/_internal/secret_refs.py +118 -0
- redis_featureform-3.0.0/src/featureform/_internal/telemetry/__init__.py +73 -0
- redis_featureform-3.0.0/src/featureform/_internal/telemetry/base.py +126 -0
- redis_featureform-3.0.0/src/featureform/_internal/telemetry/config.py +71 -0
- redis_featureform-3.0.0/src/featureform/_internal/telemetry/noop.py +89 -0
- redis_featureform-3.0.0/src/featureform/_internal/telemetry/otel.py +152 -0
- redis_featureform-3.0.0/src/featureform/_version.py +39 -0
- redis_featureform-3.0.0/src/featureform/auth/__init__.py +21 -0
- redis_featureform-3.0.0/src/featureform/auth/runtime.py +125 -0
- redis_featureform-3.0.0/src/featureform/auth/token.py +559 -0
- redis_featureform-3.0.0/src/featureform/cli/__init__.py +23 -0
- redis_featureform-3.0.0/src/featureform/cli/admin_client.py +888 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/__init__.py +113 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/clock.py +22 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/discovery.py +240 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/flows.py +130 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/fs.py +14 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/profiles.py +153 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/service.py +575 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/session_store.py +311 -0
- redis_featureform-3.0.0/src/featureform/cli/auth/types.py +80 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/__init__.py +27 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/_common.py +23 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/_provider_config.py +1173 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/apply.py +887 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/audit.py +58 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/auth.py +437 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/catalog.py +116 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/config.py +188 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/dataframe.py +182 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/graph.py +534 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/machine_credential.py +142 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/provider.py +1222 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/rbac.py +445 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/scheduler.py +1101 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/secret_provider.py +405 -0
- redis_featureform-3.0.0/src/featureform/cli/commands/workspace.py +167 -0
- redis_featureform-3.0.0/src/featureform/cli/env.py +69 -0
- redis_featureform-3.0.0/src/featureform/cli/errors.py +155 -0
- redis_featureform-3.0.0/src/featureform/cli/main.py +525 -0
- redis_featureform-3.0.0/src/featureform/cli/output/__init__.py +13 -0
- redis_featureform-3.0.0/src/featureform/cli/output/base.py +49 -0
- redis_featureform-3.0.0/src/featureform/cli/output/json_fmt.py +71 -0
- redis_featureform-3.0.0/src/featureform/cli/output/table.py +163 -0
- redis_featureform-3.0.0/src/featureform/cli/output/yaml_fmt.py +64 -0
- redis_featureform-3.0.0/src/featureform/cli/scheduler_client.py +1281 -0
- redis_featureform-3.0.0/src/featureform/cli/utils/__init__.py +5 -0
- redis_featureform-3.0.0/src/featureform/cli/utils/context.py +252 -0
- redis_featureform-3.0.0/src/featureform/client.py +7961 -0
- redis_featureform-3.0.0/src/featureform/config.py +156 -0
- redis_featureform-3.0.0/src/featureform/dataframe/__init__.py +12 -0
- redis_featureform-3.0.0/src/featureform/dataframe/client.py +787 -0
- redis_featureform-3.0.0/src/featureform/dataframe/result.py +288 -0
- redis_featureform-3.0.0/src/featureform/dataframe/stream.py +146 -0
- redis_featureform-3.0.0/src/featureform/errors.py +867 -0
- redis_featureform-3.0.0/src/featureform/py.typed +0 -0
- redis_featureform-3.0.0/src/featureform/resources/__init__.py +123 -0
- redis_featureform-3.0.0/src/featureform/resources/base.py +256 -0
- redis_featureform-3.0.0/src/featureform/resources/dataset.py +319 -0
- redis_featureform-3.0.0/src/featureform/resources/entity.py +47 -0
- redis_featureform-3.0.0/src/featureform/resources/feature.py +399 -0
- redis_featureform-3.0.0/src/featureform/resources/label.py +250 -0
- redis_featureform-3.0.0/src/featureform/resources/provider.py +729 -0
- redis_featureform-3.0.0/src/featureform/resources/realtime_feature.py +621 -0
- redis_featureform-3.0.0/src/featureform/resources/training.py +333 -0
- redis_featureform-3.0.0/src/featureform/serving/__init__.py +12 -0
- redis_featureform-3.0.0/src/featureform/serving/_decode.py +93 -0
- redis_featureform-3.0.0/src/featureform/serving/_metadata.py +99 -0
- redis_featureform-3.0.0/src/featureform/serving/_realtime.py +253 -0
- redis_featureform-3.0.0/src/featureform/serving/cache.py +190 -0
- redis_featureform-3.0.0/src/featureform/serving/client.py +788 -0
- redis_featureform-3.0.0/src/featureform/serving/types.py +134 -0
- redis_featureform-3.0.0/src/featureform/spark.py +171 -0
- redis_featureform-3.0.0/src/featureform/spark_env.py +31 -0
- redis_featureform-3.0.0/src/featureform/transport/__init__.py +49 -0
- redis_featureform-3.0.0/src/featureform/transport/base.py +42 -0
- redis_featureform-3.0.0/src/featureform/transport/grpc.py +760 -0
- redis_featureform-3.0.0/src/featureform/transport/rest.py +224 -0
- redis_featureform-3.0.0/src/featureform/types/__init__.py +226 -0
- redis_featureform-3.0.0/src/featureform/types/_base.py +24 -0
- redis_featureform-3.0.0/src/featureform/types/catalog.py +62 -0
- redis_featureform-3.0.0/src/featureform/types/entity.py +39 -0
- redis_featureform-3.0.0/src/featureform/types/graph.py +487 -0
- redis_featureform-3.0.0/src/featureform/types/patch.py +14 -0
- redis_featureform-3.0.0/src/featureform/types/provider.py +1098 -0
- redis_featureform-3.0.0/src/featureform/types/resource.py +407 -0
- redis_featureform-3.0.0/src/featureform/types/secret.py +232 -0
- redis_featureform-3.0.0/src/featureform/types/secret_provider.py +206 -0
- redis_featureform-3.0.0/src/featureform/types/workspace.py +54 -0
- redis_featureform-3.0.0/src/featureform/version.py +228 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: redis-featureform
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: Python SDK and ff CLI for Redis Feature Form
|
|
5
|
+
Author: Simba Khadder
|
|
6
|
+
Author-email: Simba Khadder <simba.khadder@redis.com>
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Typing :: Typed
|
|
15
|
+
Requires-Dist: cloudpickle>=3.0.0
|
|
16
|
+
Requires-Dist: httpx>=0.27.0
|
|
17
|
+
Requires-Dist: keyring>=25.0.0
|
|
18
|
+
Requires-Dist: packaging>=24.0
|
|
19
|
+
Requires-Dist: pydantic>=2.0.0
|
|
20
|
+
Requires-Dist: structlog>=24.0.0
|
|
21
|
+
Requires-Dist: typer>=0.12.0
|
|
22
|
+
Requires-Dist: rich>=13.0.0
|
|
23
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
24
|
+
Requires-Dist: grpcio>=1.60.0
|
|
25
|
+
Requires-Dist: grpcio-health-checking>=1.60.0
|
|
26
|
+
Requires-Dist: protobuf>=4.25.0
|
|
27
|
+
Requires-Dist: pyarrow>=17.0.0
|
|
28
|
+
Requires-Dist: pandas>=2.3.3
|
|
29
|
+
Requires-Dist: tomli>=2.0.0 ; python_full_version < '3.11'
|
|
30
|
+
Requires-Dist: pytest>=9.0.3 ; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-cov>=4.1.0 ; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-asyncio>=0.23.0 ; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest-httpx>=0.30.0 ; extra == 'dev'
|
|
34
|
+
Requires-Dist: psycopg[binary]>=3.2.0 ; extra == 'dev'
|
|
35
|
+
Requires-Dist: snowflake-connector-python>=3.12.0 ; extra == 'dev'
|
|
36
|
+
Requires-Dist: requests>=2.33.0 ; extra == 'dev'
|
|
37
|
+
Requires-Dist: redis>=5.0.0 ; extra == 'dev'
|
|
38
|
+
Requires-Dist: schemathesis>=4 ; extra == 'dev'
|
|
39
|
+
Requires-Dist: polars>=1.30.0 ; extra == 'dev'
|
|
40
|
+
Requires-Dist: schemathesis>=4 ; extra == 'dev'
|
|
41
|
+
Requires-Dist: ruff>=0.8.0 ; extra == 'dev'
|
|
42
|
+
Requires-Dist: mypy>=1.8.0 ; extra == 'dev'
|
|
43
|
+
Requires-Dist: pyright>=1.1.350 ; extra == 'dev'
|
|
44
|
+
Requires-Dist: datamodel-code-generator>=0.55.0 ; extra == 'dev'
|
|
45
|
+
Requires-Dist: opentelemetry-api>=1.20.0 ; extra == 'otel'
|
|
46
|
+
Requires-Dist: opentelemetry-sdk>=1.20.0 ; extra == 'otel'
|
|
47
|
+
Requires-Dist: pyspark>=3.5,<5 ; extra == 'pyspark'
|
|
48
|
+
Requires-Python: >=3.10
|
|
49
|
+
Project-URL: Documentation, https://redis.io/docs/latest/develop/ai/featureform/
|
|
50
|
+
Project-URL: Overview, https://redis.io/docs/latest/develop/ai/featureform/overview/
|
|
51
|
+
Project-URL: Quickstart, https://redis.io/docs/latest/develop/ai/featureform/quickstart/
|
|
52
|
+
Provides-Extra: dev
|
|
53
|
+
Provides-Extra: otel
|
|
54
|
+
Provides-Extra: pyspark
|
|
55
|
+
Description-Content-Type: text/markdown
|
|
56
|
+
|
|
57
|
+
# Redis Feature Form Python SDK
|
|
58
|
+
|
|
59
|
+
`redis-featureform` is the Python SDK and `ff` CLI for Redis Feature Form.
|
|
60
|
+
|
|
61
|
+
Redis Feature Form gives data and ML teams a declarative workflow for defining
|
|
62
|
+
providers, datasets, transformations, entities, features, labels, training sets,
|
|
63
|
+
and feature views in Python while keeping existing offline data systems in place.
|
|
64
|
+
Redis is the low-latency online store for feature serving.
|
|
65
|
+
|
|
66
|
+
Install from PyPI as `redis-featureform`, then import it in Python as
|
|
67
|
+
`featureform`.
|
|
68
|
+
|
|
69
|
+
Official Redis Feature Form docs:
|
|
70
|
+
|
|
71
|
+
- Overview: `https://redis.io/docs/latest/develop/ai/featureform/overview/`
|
|
72
|
+
- Quickstart: `https://redis.io/docs/latest/develop/ai/featureform/quickstart/`
|
|
73
|
+
- Documentation hub: `https://redis.io/docs/latest/develop/ai/featureform/`
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install redis-featureform
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Optional extras:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install "redis-featureform[otel]"
|
|
85
|
+
pip install "redis-featureform[pyspark]"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## What Redis Feature Form Does
|
|
89
|
+
|
|
90
|
+
Redis Feature Form helps you:
|
|
91
|
+
|
|
92
|
+
- register offline systems and Redis as providers
|
|
93
|
+
- define feature engineering resources as Python code
|
|
94
|
+
- submit a complete resource graph into a workspace with `ff apply` or `client.apply()`
|
|
95
|
+
- inspect the resulting plan before execution
|
|
96
|
+
- query datasets and training sets over Arrow Flight
|
|
97
|
+
- serve online feature values from Redis-backed feature views
|
|
98
|
+
|
|
99
|
+
## Core Workflow
|
|
100
|
+
|
|
101
|
+
The Redis Feature Form workflow is:
|
|
102
|
+
|
|
103
|
+
1. Create a workspace.
|
|
104
|
+
2. Register providers for offline systems and the Redis online store.
|
|
105
|
+
3. Author resources in Python.
|
|
106
|
+
4. Apply or merge the resource graph into the workspace.
|
|
107
|
+
5. Let Redis Feature Form plan and run the required execution work.
|
|
108
|
+
6. Query offline results for training or fetch online features for inference.
|
|
109
|
+
|
|
110
|
+
## Core Concepts
|
|
111
|
+
|
|
112
|
+
- Workspace: logical boundary for a Redis Feature Form resource graph
|
|
113
|
+
- Provider: connection to an external system such as Postgres, Snowflake, Spark, S3, Iceberg, or Redis
|
|
114
|
+
- Resource: Python declaration of an entity, dataset, transformation, feature, label, training set, or feature view
|
|
115
|
+
- Apply: single-shot workspace update that submits one combined resource set, computes a delta, and optionally runs an apply job
|
|
116
|
+
- Merge: apply strategy that preserves omitted resources already present in the workspace
|
|
117
|
+
- Execution mode: planning mode for runtime work, currently `NORMAL`, `UPDATE`, or `FULL_REMATERIALIZE`
|
|
118
|
+
- Training set: offline, model-ready dataset composed from features and labels
|
|
119
|
+
- Feature view: online-serving surface backed by Redis for inference-time lookup
|
|
120
|
+
|
|
121
|
+
## Connect And Register Providers
|
|
122
|
+
|
|
123
|
+
The CLI is usually the fastest way to bootstrap Redis Feature Form resources:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
ff --server https://api.example.com --transport rest auth login
|
|
127
|
+
|
|
128
|
+
ff --server https://api.example.com --transport rest \
|
|
129
|
+
workspace create fraud-detection
|
|
130
|
+
|
|
131
|
+
ff --server https://api.example.com --transport rest \
|
|
132
|
+
provider register analytics-postgres \
|
|
133
|
+
--workspace fraud-detection \
|
|
134
|
+
--type postgres \
|
|
135
|
+
--pg-host postgres.example.com \
|
|
136
|
+
--pg-port 5432 \
|
|
137
|
+
--pg-database analytics \
|
|
138
|
+
--pg-user ff_user \
|
|
139
|
+
--pg-password-secret env:PG_PASSWORD
|
|
140
|
+
|
|
141
|
+
ff --server https://api.example.com --transport rest \
|
|
142
|
+
provider register online-store \
|
|
143
|
+
--workspace fraud-detection \
|
|
144
|
+
--type redis \
|
|
145
|
+
--redis-host redis.example.com \
|
|
146
|
+
--redis-port 6379
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Providers are registered separately from apply. Resource definitions then refer
|
|
150
|
+
to those provider names when you define datasets, transformations, training sets,
|
|
151
|
+
and Redis-backed feature views.
|
|
152
|
+
|
|
153
|
+
## What `ff apply` Does
|
|
154
|
+
|
|
155
|
+
`ff apply` is the main authoring workflow in Redis Feature Form.
|
|
156
|
+
|
|
157
|
+
At a high level it:
|
|
158
|
+
|
|
159
|
+
1. loads one Python entry file or package directory
|
|
160
|
+
2. collects resources from either an explicit `resources = [...]` list or the global registry
|
|
161
|
+
3. serializes the full resource graph into one request for one workspace
|
|
162
|
+
4. compares the submitted graph with the current workspace graph
|
|
163
|
+
5. returns a dry-run plan or commits the new version and optionally waits for the apply job
|
|
164
|
+
|
|
165
|
+
`ff apply` is graph-wide. It does not patch one object at a time.
|
|
166
|
+
|
|
167
|
+
### Example Apply File
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from datetime import timedelta
|
|
171
|
+
|
|
172
|
+
import featureform as ff
|
|
173
|
+
from featureform.types.resource import FeatureView, MaterializationEngine, TrainingSetType
|
|
174
|
+
|
|
175
|
+
postgres = ff.get_postgres("analytics-postgres")
|
|
176
|
+
|
|
177
|
+
customer = ff.Entity(
|
|
178
|
+
name="customer",
|
|
179
|
+
description="Customer entity for fraud models",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
transactions = postgres.dataset(
|
|
183
|
+
name="transactions",
|
|
184
|
+
schema="public",
|
|
185
|
+
table="transactions",
|
|
186
|
+
timestamp_column="event_ts",
|
|
187
|
+
description="Raw payment events",
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@postgres.sql_transformation(
|
|
192
|
+
name="customer_daily_rollups",
|
|
193
|
+
description="Daily transaction totals per customer",
|
|
194
|
+
inputs=[transactions],
|
|
195
|
+
)
|
|
196
|
+
def customer_daily_rollups() -> str:
|
|
197
|
+
return """
|
|
198
|
+
SELECT
|
|
199
|
+
customer_id,
|
|
200
|
+
date_trunc('day', event_ts) AS event_day,
|
|
201
|
+
SUM(amount) AS total_amount,
|
|
202
|
+
COUNT(*) AS transaction_count
|
|
203
|
+
FROM {{transactions}}
|
|
204
|
+
GROUP BY 1, 2
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
customer_amount_7d = (
|
|
209
|
+
ff.Feature(name="customer_amount_7d")
|
|
210
|
+
.from_dataset(
|
|
211
|
+
customer_daily_rollups,
|
|
212
|
+
entity="customer",
|
|
213
|
+
entity_column="customer_id",
|
|
214
|
+
value="total_amount",
|
|
215
|
+
timestamp="event_day",
|
|
216
|
+
)
|
|
217
|
+
.with_provider("analytics-postgres")
|
|
218
|
+
.aggregate(function=ff.AggregateFunction.SUM, window=timedelta(days=7))
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
fraud_label = (
|
|
222
|
+
ff.Label()
|
|
223
|
+
.from_dataset(transactions)
|
|
224
|
+
.value("is_fraud")
|
|
225
|
+
.timestamp("event_ts")
|
|
226
|
+
.entity("customer", column="customer_id")
|
|
227
|
+
.build()
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
fraud_training = ff.TrainingSet(
|
|
231
|
+
name="fraud_training",
|
|
232
|
+
provider="analytics-postgres",
|
|
233
|
+
features=[customer_amount_7d],
|
|
234
|
+
label=fraud_label,
|
|
235
|
+
type=TrainingSetType.STATIC,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
customer_features = FeatureView(
|
|
239
|
+
name="customer_features",
|
|
240
|
+
entity="customer",
|
|
241
|
+
features=[customer_amount_7d.name],
|
|
242
|
+
inference_store="online-store",
|
|
243
|
+
materialization_engine=MaterializationEngine.K8S,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
resources = [
|
|
247
|
+
customer,
|
|
248
|
+
transactions,
|
|
249
|
+
customer_daily_rollups,
|
|
250
|
+
customer_amount_7d,
|
|
251
|
+
fraud_label,
|
|
252
|
+
fraud_training,
|
|
253
|
+
customer_features,
|
|
254
|
+
]
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Apply Strategies And Execution Modes
|
|
258
|
+
|
|
259
|
+
Redis Feature Form now exposes apply strategy and execution mode as separate axes.
|
|
260
|
+
|
|
261
|
+
Apply strategies:
|
|
262
|
+
|
|
263
|
+
- default apply: submitted resources replace the desired graph for the workspace
|
|
264
|
+
- merge: submitted resources merge into the workspace and omitted resources are retained
|
|
265
|
+
|
|
266
|
+
Execution modes:
|
|
267
|
+
|
|
268
|
+
- `NORMAL`: standard diff-based planning
|
|
269
|
+
- `UPDATE`: revisit the target graph in update mode
|
|
270
|
+
- `FULL_REMATERIALIZE`: revisit the target graph in full-rematerialize mode
|
|
271
|
+
|
|
272
|
+
That means combinations such as these are valid:
|
|
273
|
+
|
|
274
|
+
- apply + normal
|
|
275
|
+
- apply + update
|
|
276
|
+
- apply + full rematerialize
|
|
277
|
+
- merge + normal
|
|
278
|
+
- merge + update
|
|
279
|
+
- merge + full rematerialize
|
|
280
|
+
|
|
281
|
+
### Apply From The CLI
|
|
282
|
+
|
|
283
|
+
Preview the graph delta without changing the workspace:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
ff --server https://api.example.com --transport rest \
|
|
287
|
+
apply -f resources.py --workspace fraud-detection --plan
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Apply the submitted graph and wait for completion:
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
ff --server https://api.example.com --transport rest \
|
|
294
|
+
apply -f resources.py \
|
|
295
|
+
--workspace fraud-detection \
|
|
296
|
+
--message "initial fraud pipeline" \
|
|
297
|
+
--wait --wait-for finished
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Merge into the existing workspace instead of replacing omitted resources:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
ff --server https://api.example.com --transport rest \
|
|
304
|
+
apply -f resources.py \
|
|
305
|
+
--workspace fraud-detection \
|
|
306
|
+
--merge \
|
|
307
|
+
--wait --wait-for finished
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
Run a plan in update mode:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
ff --server https://api.example.com --transport rest \
|
|
314
|
+
apply -f resources.py \
|
|
315
|
+
--workspace fraud-detection \
|
|
316
|
+
--plan \
|
|
317
|
+
--update
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Request a merge with full rematerialization semantics:
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
ff --server https://api.example.com --transport rest \
|
|
324
|
+
apply -f resources.py \
|
|
325
|
+
--workspace fraud-detection \
|
|
326
|
+
--merge \
|
|
327
|
+
--full-rematerialize
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
Useful flags:
|
|
331
|
+
|
|
332
|
+
- `--plan`: show what would change without applying
|
|
333
|
+
- `--merge`: keep omitted resources already present in the workspace
|
|
334
|
+
- `--update`: use update execution mode
|
|
335
|
+
- `--full-rematerialize`: use full rematerialization execution mode
|
|
336
|
+
- `--wait --wait-for finished`: block until the apply job completes and the workspace version is visible
|
|
337
|
+
|
|
338
|
+
### Apply From Python
|
|
339
|
+
|
|
340
|
+
Use `client.apply()` for standard apply semantics:
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
import os
|
|
344
|
+
|
|
345
|
+
import featureform as ff
|
|
346
|
+
import resources
|
|
347
|
+
|
|
348
|
+
client = ff.Client(
|
|
349
|
+
base_url="grpc.example.com:443",
|
|
350
|
+
transport="grpc",
|
|
351
|
+
token=os.environ["FEATUREFORM_TOKEN"],
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
result = client.apply(
|
|
355
|
+
resources=resources.resources,
|
|
356
|
+
workspace="fraud-detection",
|
|
357
|
+
message="initial fraud pipeline",
|
|
358
|
+
wait=True,
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
print(result.version)
|
|
362
|
+
for change in result.changes:
|
|
363
|
+
print(change.resource_type, change.resource_name, change.action)
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Use execution mode directly from Python:
|
|
367
|
+
|
|
368
|
+
```python
|
|
369
|
+
plan = client.apply(
|
|
370
|
+
resources=resources.resources,
|
|
371
|
+
workspace="fraud-detection",
|
|
372
|
+
dry_run=True,
|
|
373
|
+
execution_mode="UPDATE",
|
|
374
|
+
)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Use merge semantics without deleting omitted resources:
|
|
378
|
+
|
|
379
|
+
```python
|
|
380
|
+
result = client.merge(
|
|
381
|
+
resources=resources.resources,
|
|
382
|
+
workspace="fraud-detection",
|
|
383
|
+
execution_mode="FULL_REMATERIALIZE",
|
|
384
|
+
wait=True,
|
|
385
|
+
)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
If `resources` is omitted, `client.apply(...)` and `client.merge(...)` use the
|
|
389
|
+
global resource registry. That works well when definition modules register
|
|
390
|
+
resources during import.
|
|
391
|
+
|
|
392
|
+
## Query Offline Data
|
|
393
|
+
|
|
394
|
+
Use Arrow Flight helpers to pull datasets, training sets, or feature-view
|
|
395
|
+
snapshots into pandas or stream them incrementally.
|
|
396
|
+
|
|
397
|
+
```python
|
|
398
|
+
training = client.query_training_set(
|
|
399
|
+
"fraud_training",
|
|
400
|
+
workspace="fraud-detection",
|
|
401
|
+
flight_server="grpc.example.com:9090",
|
|
402
|
+
).to_pandas()
|
|
403
|
+
|
|
404
|
+
print(training.head())
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
You can also query datasets directly:
|
|
408
|
+
|
|
409
|
+
```python
|
|
410
|
+
transactions = client.query_dataset(
|
|
411
|
+
"transactions",
|
|
412
|
+
workspace="fraud-detection",
|
|
413
|
+
limit=1000,
|
|
414
|
+
).to_pandas()
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## Serve Online Features From Redis
|
|
418
|
+
|
|
419
|
+
Once a feature view is materialized, Redis Feature Form serves online values from
|
|
420
|
+
Redis with `client.serve(...)`.
|
|
421
|
+
|
|
422
|
+
```python
|
|
423
|
+
features = client.serve(
|
|
424
|
+
"customer_features",
|
|
425
|
+
entity="customer_123",
|
|
426
|
+
workspace="fraud-detection",
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
print(features["customer_amount_7d"])
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
Batch serving is supported as well:
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
result = client.serve(
|
|
436
|
+
"customer_features",
|
|
437
|
+
entities=["customer_123", "customer_456"],
|
|
438
|
+
workspace="fraud-detection",
|
|
439
|
+
return_type="pandas",
|
|
440
|
+
)
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Package Surface
|
|
444
|
+
|
|
445
|
+
- `featureform.Client`: client for workspaces, providers, apply and merge, offline queries, and online serving
|
|
446
|
+
- `ff`: CLI for auth, apply, workspace, provider, catalog, graph, scheduler, and RBAC operations
|
|
447
|
+
- `featureform.resources`: typed resource DSL for authoring Redis Feature Form resource graphs
|
|
448
|
+
- `featureform.types`: request and response models used by the client surface
|