|
1 | 1 | from datetime import timedelta
|
2 | 2 |
|
3 | 3 | import pandas as pd
|
| 4 | +import numpy as np |
4 | 5 |
|
5 | 6 | from feast import Entity, FeatureService, FeatureView, Field, FileSource
|
6 | 7 | from feast.data_source import RequestSource
|
7 | 8 | from feast.on_demand_feature_view import on_demand_feature_view
|
8 |
| -from feast.types import Bool, Int64, String |
| 9 | +from feast.permissions.action import AuthzedAction, READ |
| 10 | +from feast.permissions.permission import Permission |
| 11 | +from feast.permissions.policy import RoleBasedPolicy |
| 12 | +from feast.types import Bool, Int64, String, Float32, Array |
9 | 13 |
|
10 | 14 | zipcode = Entity(
|
11 | 15 | name="zipcode",
|
@@ -199,3 +203,153 @@ def transaction_gt_last_credit_card_due(inputs: pd.DataFrame) -> pd.DataFrame:
|
199 | 203 | tags={ "owner": "[email protected]", "stage": "dev"},
|
200 | 204 | description="Location model",
|
201 | 205 | )
|
| 206 | + |
| 207 | +zipcode_features_permission = Permission( |
| 208 | + name="zipcode-features-reader", |
| 209 | + types=[FeatureView], |
| 210 | + name_patterns=["zipcode_features"], |
| 211 | + policy=RoleBasedPolicy(roles=["analyst", "data_scientist"]), |
| 212 | + actions=[AuthzedAction.DESCRIBE, *READ], |
| 213 | +) |
| 214 | + |
| 215 | +zipcode_source_permission = Permission( |
| 216 | + name="zipcode-source-writer", |
| 217 | + types=[FileSource], |
| 218 | + name_patterns=["zipcode"], |
| 219 | + policy=RoleBasedPolicy(roles=["admin", "data_engineer"]), |
| 220 | + actions=[AuthzedAction.CREATE, AuthzedAction.UPDATE, AuthzedAction.WRITE_OFFLINE], |
| 221 | +) |
| 222 | + |
| 223 | +model_v1_permission = Permission( |
| 224 | + name="credit-score-v1-reader", |
| 225 | + types=[FeatureService], |
| 226 | + name_patterns=["credit_score_v1"], |
| 227 | + policy=RoleBasedPolicy(roles=["model_user", "data_scientist"]), |
| 228 | + actions=[AuthzedAction.DESCRIBE, AuthzedAction.READ_ONLINE], |
| 229 | +) |
| 230 | + |
| 231 | +risky_features_permission = Permission( |
| 232 | + name="risky-features-reader", |
| 233 | + types=[FeatureView, FeatureService], |
| 234 | + required_tags={"stage": "prod"}, |
| 235 | + policy=RoleBasedPolicy(roles=["trusted_analyst"]), |
| 236 | + actions=[AuthzedAction.READ_OFFLINE], |
| 237 | +) |
| 238 | + |
| 239 | +document = Entity( |
| 240 | + name="document_id", |
| 241 | + description="Document identifier for RAG system", |
| 242 | + tags={ |
| 243 | + |
| 244 | + "team": "rag", |
| 245 | + }, |
| 246 | +) |
| 247 | + |
| 248 | +document_source = FileSource( |
| 249 | + name="document_embeddings", |
| 250 | + path="data/document_embeddings.parquet", |
| 251 | + timestamp_field="event_timestamp", |
| 252 | + created_timestamp_column="created_timestamp", |
| 253 | +) |
| 254 | + |
| 255 | +document_metadata_source = FileSource( |
| 256 | + name="document_metadata", |
| 257 | + path="data/document_metadata.parquet", |
| 258 | + timestamp_field="event_timestamp", |
| 259 | + created_timestamp_column="created_timestamp", |
| 260 | +) |
| 261 | + |
| 262 | +document_embeddings_view = FeatureView( |
| 263 | + name="document_embeddings", |
| 264 | + entities=[document], |
| 265 | + ttl=timedelta(days=365), |
| 266 | + schema=[ |
| 267 | + Field(name="embedding", dtype=Array(Float32, 768)), |
| 268 | + Field(name="document_id", dtype=String), |
| 269 | + ], |
| 270 | + source=document_source, |
| 271 | + tags={ |
| 272 | + "date_added": "2025-05-04", |
| 273 | + "model": "sentence-transformer", |
| 274 | + "access_group": "[email protected]", |
| 275 | + "stage": "prod", |
| 276 | + }, |
| 277 | + online=True, |
| 278 | +) |
| 279 | + |
| 280 | +document_metadata_view = FeatureView( |
| 281 | + name="document_metadata", |
| 282 | + entities=[document], |
| 283 | + ttl=timedelta(days=365), |
| 284 | + schema=[ |
| 285 | + Field(name="title", dtype=String), |
| 286 | + Field(name="content", dtype=String), |
| 287 | + Field(name="source", dtype=String), |
| 288 | + Field(name="author", dtype=String), |
| 289 | + Field(name="publish_date", dtype=String), |
| 290 | + Field(name="document_id", dtype=String), |
| 291 | + ], |
| 292 | + source=document_metadata_source, |
| 293 | + tags={ |
| 294 | + "date_added": "2025-05-04", |
| 295 | + "access_group": "[email protected]", |
| 296 | + "stage": "prod", |
| 297 | + }, |
| 298 | + online=True, |
| 299 | +) |
| 300 | + |
| 301 | +# Define a request data source for query embeddings |
| 302 | +query_request = RequestSource( |
| 303 | + name="query", |
| 304 | + schema=[ |
| 305 | + Field(name="query_embedding", dtype=Array(Float32, 768)), |
| 306 | + ], |
| 307 | +) |
| 308 | + |
| 309 | +# Define an on-demand feature view for similarity calculation |
| 310 | +@on_demand_feature_view( |
| 311 | + sources=[document_embeddings_view, query_request], |
| 312 | + schema=[ |
| 313 | + Field(name="similarity_score", dtype=Float32), |
| 314 | + ], |
| 315 | +) |
| 316 | +def document_similarity(inputs: pd.DataFrame) -> pd.DataFrame: |
| 317 | + """Calculate cosine similarity between query and document embeddings.""" |
| 318 | + df = pd.DataFrame() |
| 319 | + df["similarity_score"] = 0.95 # Placeholder value |
| 320 | + return df |
| 321 | + |
| 322 | +rag_model = FeatureService( |
| 323 | + name="rag_retriever", |
| 324 | + features=[ |
| 325 | + document_embeddings_view, |
| 326 | + document_metadata_view, |
| 327 | + document_similarity, |
| 328 | + ], |
| 329 | + tags={ "owner": "[email protected]", "stage": "prod"}, |
| 330 | + description="Retrieval Augmented Generation model", |
| 331 | +) |
| 332 | + |
| 333 | +document_embeddings_permission = Permission( |
| 334 | + name="document-embeddings-reader", |
| 335 | + types=[FeatureView], |
| 336 | + name_patterns=["document_embeddings"], |
| 337 | + policy=RoleBasedPolicy(roles=["ml_engineer", "data_scientist"]), |
| 338 | + actions=[AuthzedAction.DESCRIBE, *READ], |
| 339 | +) |
| 340 | + |
| 341 | +document_metadata_permission = Permission( |
| 342 | + name="document-metadata-reader", |
| 343 | + types=[FeatureView], |
| 344 | + name_patterns=["document_metadata"], |
| 345 | + policy=RoleBasedPolicy(roles=["ml_engineer", "content_manager"]), |
| 346 | + actions=[AuthzedAction.DESCRIBE, *READ], |
| 347 | +) |
| 348 | + |
| 349 | +rag_model_permission = Permission( |
| 350 | + name="rag-model-user", |
| 351 | + types=[FeatureService], |
| 352 | + name_patterns=["rag_retriever"], |
| 353 | + policy=RoleBasedPolicy(roles=["ml_engineer", "app_developer"]), |
| 354 | + actions=[AuthzedAction.DESCRIBE, AuthzedAction.READ_ONLINE], |
| 355 | +) |
0 commit comments