Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion infra/scripts/pixi/pixi.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[project]
[workspace]
name = "pixi-feast"
channels = ["conda-forge"]
platforms = ["linux-64", "osx-arm64", "osx-64"]
Expand Down
37 changes: 2 additions & 35 deletions pixi.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ dependencies = [
"psutil",
"bigtree>=0.19.2",
"pyjwt",
"orjson>=3.9.0",
]

[project.optional-dependencies]
Expand Down
40 changes: 34 additions & 6 deletions sdk/python/feast/feature_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
)
from fastapi.concurrency import run_in_threadpool
from fastapi.logger import logger
from fastapi.responses import JSONResponse, ORJSONResponse
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from google.protobuf.json_format import MessageToDict
from pydantic import BaseModel
from pydantic import BaseModel, field_validator

import feast
from feast import metrics as feast_metrics
Expand Down Expand Up @@ -111,6 +111,32 @@ class GetOnlineDocumentsRequest(BaseModel):
api_version: Optional[int] = 1


class FeatureVectorResponse(BaseModel):
values: List[Any] = []
statuses: List[str] = []
event_timestamps: List[str] = []


class OnlineFeaturesMetadataResponse(BaseModel):
feature_names: List[str] = []

@field_validator("feature_names", mode="before")
@classmethod
def _unwrap_feature_list(cls, v: Any) -> Any:
"""Accept both the proto_json-patched flat list and the raw
protobuf ``{"val": [...]}`` dict produced by ``MessageToDict``
when the monkey-patch is absent or ineffective."""
if isinstance(v, dict) and "val" in v:
return v["val"]
return v


class OnlineFeaturesResponse(BaseModel):
metadata: Optional[OnlineFeaturesMetadataResponse] = None
results: List[FeatureVectorResponse] = []
status: Optional[bool] = None


class ChatMessage(BaseModel):
role: str
content: str
Expand Down Expand Up @@ -338,8 +364,9 @@ async def lifespan(app: FastAPI):
@app.post(
"/get-online-features",
dependencies=[Depends(inject_user_details)],
response_model=OnlineFeaturesResponse,
)
async def get_online_features(request: GetOnlineFeaturesRequest) -> ORJSONResponse:
async def get_online_features(request: GetOnlineFeaturesRequest) -> Any:
with feast_metrics.track_request_latency(
"/get-online-features",
) as metrics_ctx:
Expand Down Expand Up @@ -370,15 +397,16 @@ async def get_online_features(request: GetOnlineFeaturesRequest) -> ORJSONRespon
preserving_proto_field_name=True,
float_precision=18,
)
return ORJSONResponse(content=response_dict)
return response_dict

@app.post(
"/retrieve-online-documents",
dependencies=[Depends(inject_user_details)],
response_model=OnlineFeaturesResponse,
)
async def retrieve_online_documents(
request: GetOnlineDocumentsRequest,
) -> ORJSONResponse:
) -> Any:
with feast_metrics.track_request_latency("/retrieve-online-documents"):
logger.warning(
"This endpoint is in alpha and will be moved to /get-online-features when stable."
Expand Down Expand Up @@ -406,7 +434,7 @@ async def retrieve_online_documents(
preserving_proto_field_name=True,
float_precision=18,
)
return ORJSONResponse(content=response_dict)
return response_dict

@app.post("/push", dependencies=[Depends(inject_user_details)])
async def push(request: PushFeaturesRequest) -> Response:
Expand Down
367 changes: 196 additions & 171 deletions sdk/python/requirements/py3.10-ci-requirements.txt

Large diffs are not rendered by default.

140 changes: 32 additions & 108 deletions sdk/python/requirements/py3.10-minimal-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,9 @@ atpublic==7.0.0 \
--hash=sha256:466ef10d0c8bbd14fd02a5fbd5a8b6af6a846373d91106d3a07c16d72d96b63e \
--hash=sha256:6702bd9e7245eb4e8220a3e222afcef7f87412154732271ee7deee4433b72b4b
# via ibis-framework
attrs==25.4.0 \
--hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \
--hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373
attrs==26.1.0 \
--hash=sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309 \
--hash=sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32
# via
# aiohttp
# jsonschema
Expand Down Expand Up @@ -497,9 +497,9 @@ cryptography==46.0.5 \
# pyjwt
# pyopenssl
# snowflake-connector-python
dask[dataframe]==2026.1.2 \
--hash=sha256:1136683de2750d98ea792670f7434e6c1cfce90cab2cc2f2495a9e60fd25a4fc \
--hash=sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91
dask[dataframe]==2026.3.0 \
--hash=sha256:be614b9242b0b38288060fb2d7696125946469c98a1c30e174883fd199e0428d \
--hash=sha256:f7d96c8274e8a900d217c1ff6ea8d1bbf0b4c2c21e74a409644498d925eb8f85
# via feast (pyproject.toml)
db-dtypes==1.5.0 \
--hash=sha256:abdbb2e4eb965800ed6f98af0c5c1cafff9063ace09114be2d26a7f046be2c8a \
Expand Down Expand Up @@ -1087,9 +1087,9 @@ idna==3.11 \
# requests
# snowflake-connector-python
# yarl
importlib-metadata==8.7.1 \
--hash=sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb \
--hash=sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151
importlib-metadata==9.0.0 \
--hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \
--hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc
# via dask
jinja2==3.1.6 \
--hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
Expand Down Expand Up @@ -1694,82 +1694,6 @@ oauthlib==3.3.1 \
--hash=sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9 \
--hash=sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1
# via requests-oauthlib
orjson==3.11.7 \
--hash=sha256:043d3006b7d32c7e233b8cfb1f01c651013ea079e08dcef7189a29abd8befe11 \
--hash=sha256:0527a4510c300e3b406591b0ba69b5dc50031895b0a93743526a3fc45f59d26e \
--hash=sha256:0724e265bc548af1dedebd9cb3d24b4e1c1e685a343be43e87ba922a5c5fff2f \
--hash=sha256:136dcd6a2e796dfd9ffca9fc027d778567b0b7c9968d092842d3c323cef88aa8 \
--hash=sha256:14f440c7268c8f8633d1b3d443a434bd70cb15686117ea6beff8fdc8f5917a1e \
--hash=sha256:1d98b30cc1313d52d4af17d9c3d307b08389752ec5f2e5febdfada70b0f8c733 \
--hash=sha256:1eb80451a9c351a71dfaf5b7ccc13ad065405217726b59fdbeadbcc544f9d223 \
--hash=sha256:1ee5cc7160a821dfe14f130bc8e63e7611051f964b463d9e2a3a573204446a4d \
--hash=sha256:23d6c20517a97a9daf1d48b580fcdc6f0516c6f4b5038823426033690b4d2650 \
--hash=sha256:26c3b9132f783b7d7903bf1efb095fed8d4a3a85ec0d334ee8beff3d7a4749d5 \
--hash=sha256:31c80ce534ac4ea3739c5ee751270646cbc46e45aea7576a38ffec040b4029a1 \
--hash=sha256:3726be79e36e526e3d9c1aceaadbfb4a04ee80a72ab47b3f3c17fefb9812e7b8 \
--hash=sha256:390a1dce0c055ddf8adb6aa94a73b45a4a7d7177b5c584b8d1c1947f2ba60fb3 \
--hash=sha256:3a2479753bbb95b0ebcf7969f562cdb9668e6d12416a35b0dda79febf89cdea2 \
--hash=sha256:3c4bc6c6ac52cdaa267552544c73e486fecbd710b7ac09bc024d5a78555a22f6 \
--hash=sha256:411ebaf34d735e25e358a6d9e7978954a9c9d58cfb47bc6683cdc3964cd2f910 \
--hash=sha256:4682d1db3bcebd2b64757e0ddf9e87ae5f00d29d16c5cdf3a62f561d08cc3dd2 \
--hash=sha256:4a2e9c5be347b937a2e0203866f12bba36082e89b402ddb9e927d5822e43088d \
--hash=sha256:57036b27ac8a25d81112eb0cc9835cd4833c5b16e1467816adc0015f59e870dc \
--hash=sha256:5ede977b5fe5ac91b1dffc0a517ca4542d2ec8a6a4ff7b2652d94f640796342a \
--hash=sha256:5fdfad2093bdd08245f2e204d977facd5f871c88c4a71230d5bcbd0e43bf6222 \
--hash=sha256:623ad1b9548ef63886319c16fa317848e465a21513b31a6ad7b57443c3e0dcf5 \
--hash=sha256:652c6c3af76716f4a9c290371ba2e390ede06f6603edb277b481daf37f6f464e \
--hash=sha256:6543001328aa857187f905308a028935864aefe9968af3848401b6fe80dbb471 \
--hash=sha256:6e776b998ac37c0396093d10290e60283f59cfe0fc3fccbd0ccc4bd04dd19892 \
--hash=sha256:71924496986275a737f38e3f22b4e0878882b3f7a310d2ff4dc96e812789120c \
--hash=sha256:733ae23ada68b804b222c44affed76b39e30806d38660bf1eb200520d259cc16 \
--hash=sha256:7477aa6a6ec6139c5cb1cc7b214643592169a5494d200397c7fc95d740d5fcf3 \
--hash=sha256:79cacb0b52f6004caf92405a7e1f11e6e2de8bdf9019e4f76b44ba045125cd6b \
--hash=sha256:7ba61079379b0ae29e117db13bda5f28d939766e410d321ec1624afc6a0b0504 \
--hash=sha256:800988273a014a0541483dc81021247d7eacb0c845a9d1a34a422bc718f41539 \
--hash=sha256:814be4b49b228cfc0b3c565acf642dd7d13538f966e3ccde61f4f55be3e20785 \
--hash=sha256:845c3e0d8ded9c9271cd79596b9b552448b885b97110f628fb687aee2eed11c1 \
--hash=sha256:849e38203e5be40b776ed2718e587faf204d184fc9a008ae441f9442320c0cab \
--hash=sha256:89e13dd3f89f1c38a9c9eba5fbf7cdc2d1feca82f5f290864b4b7a6aac704576 \
--hash=sha256:89e440ebc74ce8ab5c7bc4ce6757b4a6b1041becb127df818f6997b5c71aa60b \
--hash=sha256:8ff206156006da5b847c9304b6308a01e8cdbc8cce824e2779a5ba71c3def141 \
--hash=sha256:91c81ef070c8f3220054115e1ef468b1c9ce8497b4e526cb9f68ab4dc0a7ac62 \
--hash=sha256:9487abc2c2086e7c8eb9a211d2ce8855bae0e92586279d0d27b341d5ad76c85c \
--hash=sha256:962d046ee1765f74a1da723f4b33e3b228fe3a48bd307acce5021dfefe0e29b2 \
--hash=sha256:996b65230271f1a97026fd0e6a753f51fbc0c335d2ad0c6201f711b0da32693b \
--hash=sha256:9b1a67243945819ce55d24a30b59d6a168e86220452d2c96f4d1f093e71c0c49 \
--hash=sha256:9c0b51672e466fd7e56230ffbae7f1639e18d0ce023351fb75da21b71bc2c960 \
--hash=sha256:9e54f3808e2b6b945078c41aa8d9b5834b28c50843846e97807e5adb75fa9705 \
--hash=sha256:a02c833f38f36546ba65a452127633afce4cf0dd7296b753d3bb54e55e5c0174 \
--hash=sha256:a12b80df61aab7b98b490fe9e4879925ba666fccdfcd175252ce4d9035865ace \
--hash=sha256:a16bcd08ab0bcdfc7e8801d9c4a9cc17e58418e4d48ddc6ded4e9e4b1a94062b \
--hash=sha256:a56df3239294ea5964adf074c54bcc4f0ccd21636049a2cf3ca9cf03b5d03cf1 \
--hash=sha256:a709e881723c9b18acddcfb8ba357322491ad553e277cf467e1e7e20e2d90561 \
--hash=sha256:ab49d4b2a6a1d415ddb9f37a21e02e0d5dbfe10b7870b21bf779fc21e9156157 \
--hash=sha256:ae9e0b37a834cef7ce8f99de6498f8fad4a2c0bf6bfc3d02abd8ed56aa15b2de \
--hash=sha256:b4a9eefdc70bf8bf9857f0290f973dec534ac84c35cd6a7f4083be43e7170a8f \
--hash=sha256:b63c6e6738d7c3470ad01601e23376aa511e50e1f3931395b9f9c722406d1a67 \
--hash=sha256:b7b1dae39230a393df353827c855a5f176271c23434cfd2db74e0e424e693e10 \
--hash=sha256:b8d14b71c0b12963fe8a62aac87119f1afdf4cb88a400f61ca5ae581449efcb5 \
--hash=sha256:b9f95dcdea9d4f805daa9ddf02617a89e484c6985fa03055459f90e87d7a0757 \
--hash=sha256:b9fc4d0f81f394689e0814617aadc4f2ea0e8025f38c226cbf22d3b5ddbf025d \
--hash=sha256:bd03ea7606833655048dab1a00734a2875e3e86c276e1d772b2a02556f0d895f \
--hash=sha256:bd0d68edd7dfca1b2eca9361a44ac9f24b078de3481003159929a0573f21a6bf \
--hash=sha256:bda117c4148e81f746655d5a3239ae9bd00cb7bc3ca178b5fc5a5997e9744183 \
--hash=sha256:bf742e149121dc5648ba0a08ea0871e87b660467ef168a3a5e53bc1fbd64bb74 \
--hash=sha256:c2428d358d85e8da9d37cba18b8c4047c55222007a84f97156a5b22028dfbfc0 \
--hash=sha256:c2e85fe4698b6a56d5e2ebf7ae87544d668eb6bde1ad1226c13f44663f20ec9e \
--hash=sha256:c43b8b5bab288b6b90dac410cca7e986a4fa747a2e8f94615aea407da706980d \
--hash=sha256:cededd6738e1c153530793998e31c05086582b08315db48ab66649768f326baa \
--hash=sha256:d06e5c5fed5caedd2e540d62e5b1c25e8c82431b9e577c33537e5fa4aa909539 \
--hash=sha256:d772afdb22555f0c58cfc741bdae44180122b3616faa1ecadb595cd526e4c993 \
--hash=sha256:d897e81f8d0cbd2abb82226d1860ad2e1ab3ff16d7b08c96ca00df9d45409ef4 \
--hash=sha256:de0a37f21d0d364954ad5de1970491d7fbd0fb1ef7417d4d56a36dc01ba0c0a0 \
--hash=sha256:e7745312efa9e11c17fbd3cb3097262d079da26930ae9ae7ba28fb738367cbad \
--hash=sha256:ed46f17096e28fb28d2975834836a639af7278aa87c84f68ab08fbe5b8bd75fa \
--hash=sha256:f4f7c956b5215d949a1f65334cf9d7612dde38f20a95f2315deef167def91a6f \
--hash=sha256:f50979824bde13d32b4320eedd513431c921102796d86be3eee0b58e58a3ecd1 \
--hash=sha256:f904c24bdeabd4298f7a977ef14ca2a022ca921ed670b92ecd16ab6f3d01f867
# via feast (pyproject.toml)
packaging==26.0 \
--hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \
--hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529
Expand Down Expand Up @@ -2004,17 +1928,17 @@ proto-plus==1.27.1 \
# google-cloud-bigquery-storage
# google-cloud-bigtable
# google-cloud-datastore
protobuf==6.33.5 \
--hash=sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c \
--hash=sha256:69915a973dd0f60f31a08b8318b73eab2bd6a392c79184b3612226b0a3f8ec02 \
--hash=sha256:6ddcac2a081f8b7b9642c09406bc6a4290128fce5f471cddd165960bb9119e5c \
--hash=sha256:8afa18e1d6d20af15b417e728e9f60f3aa108ee76f23c3b2c07a2c3b546d3afd \
--hash=sha256:8f04fa32763dcdb4973d537d6b54e615cc61108c7cb38fe59310c3192d29510a \
--hash=sha256:9b71e0281f36f179d00cbcb119cb19dec4d14a81393e5ea220f64b286173e190 \
--hash=sha256:a3157e62729aafb8df6da2c03aa5c0937c7266c626ce11a278b6eb7963c4e37c \
--hash=sha256:a5cb85982d95d906df1e2210e58f8e4f1e3cdc088e52c921a041f9c9a0386de5 \
--hash=sha256:cbf16ba3350fb7b889fca858fb215967792dc125b35c7976ca4818bee3521cf0 \
--hash=sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b
protobuf==6.33.6 \
--hash=sha256:0cd27b587afca21b7cfa59a74dcbd48a50f0a6400cfb59391340ad729d91d326 \
--hash=sha256:77179e006c476e69bf8e8ce866640091ec42e1beb80b213c3900006ecfba6901 \
--hash=sha256:7d29d9b65f8afef196f8334e80d6bc1d5d4adedb449971fefd3723824e6e77d3 \
--hash=sha256:9720e6961b251bde64edfdab7d500725a2af5280f3f4c87e57c0208376aa8c3a \
--hash=sha256:a6768d25248312c297558af96a9f9c929e8c4cee0659cb07e780731095f38135 \
--hash=sha256:bd56799fb262994b2c2faa1799693c95cc2e22c62f56fb43af311cae45d26f0e \
--hash=sha256:c96c37eec15086b79762ed265d59ab204dabc53056e3443e702d2681f4b39ce3 \
--hash=sha256:e2afbae9b8e1825e3529f88d514754e094278bb95eadc0e199751cdd9a2e82a2 \
--hash=sha256:e9db7e292e0ab79dd108d7f1a94fe31601ce1ee3f7b79e0692043423020b0593 \
--hash=sha256:f443a394af5ed23672bc6c486be138628fbe5c651ccbc536873d7da23d1868cf
# via
# feast (pyproject.toml)
# google-api-core
Expand Down Expand Up @@ -2127,9 +2051,9 @@ pyarrow-hotfix==0.7 \
--hash=sha256:3236f3b5f1260f0e2ac070a55c1a7b339c4bb7267839bd2015e283234e758100 \
--hash=sha256:59399cd58bdd978b2e42816a4183a55c6472d4e33d183351b6069f11ed42661d
# via ibis-framework
pyasn1==0.6.2 \
--hash=sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf \
--hash=sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b
pyasn1==0.6.3 \
--hash=sha256:697a8ecd6d98891189184ca1fa05d1bb00e2f84b5977c481452050549c8a72cf \
--hash=sha256:a80184d120f0864a52a073acc6fc642847d0be408e7c7252f31390c0f4eadcde
# via pyasn1-modules
pyasn1-modules==0.4.2 \
--hash=sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a \
Expand Down Expand Up @@ -2685,17 +2609,17 @@ sqlalchemy[mypy]==2.0.48 \
--hash=sha256:fac0fa4e4f55f118fd87177dacb1c6522fe39c28d498d259014020fec9164c29 \
--hash=sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb
# via feast (pyproject.toml)
sqlglot==29.0.1 \
--hash=sha256:0010b4f77fb996c8d25dd4b16f3654e6da163ff1866ceabc70b24e791c203048 \
--hash=sha256:06a473ea6c2b3632ac67bd38e687a6860265bf4156e66b54adeda15d07f00c65
sqlglot==30.0.3 \
--hash=sha256:35ba7514c132b54f87fd1732a65a73615efa9fd83f6e1eed0a315bc9ee3e1027 \
--hash=sha256:5489cc98b5666f1fafc21e0304ca286e513e142aa054ee5760806a2139d07a05
# via ibis-framework
sse-starlette==3.3.2 \
--hash=sha256:5c3ea3dad425c601236726af2f27689b74494643f57017cafcb6f8c9acfbb862 \
--hash=sha256:678fca55a1945c734d8472a6cad186a55ab02840b4f6786f5ee8770970579dcd
sse-starlette==3.3.3 \
--hash=sha256:72a95d7575fd5129bd0ae15275ac6432bb35ac542fdebb82889c24bb9f3f4049 \
--hash=sha256:c5abb5082a1cc1c6294d89c5290c46b5f67808cfdb612b7ec27e8ba061c22e8d
# via mcp
starlette==0.52.1 \
--hash=sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74 \
--hash=sha256:834edd1b0a23167694292e94f597773bc3f89f362be6effee198165a35d62933
starlette==1.0.0 \
--hash=sha256:6a4beaf1f81bb472fd19ea9b918b50dc3a77a6f2e190a12954b25e6ed5eea149 \
--hash=sha256:d3ec55e0bb321692d275455ddfd3df75fff145d009685eb40dc91fc66b03d38b
# via
# fastapi
# mcp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,6 @@ maturin==1.12.6 \
--hash=sha256:fa84b7493a2e80759cacc2e668fa5b444d55b9994e90707c42904f55d6322c1e
# via
# cryptography
# orjson
# pydantic-core
# rpds-py
# watchfiles
Expand Down Expand Up @@ -814,9 +813,9 @@ typing-extensions==4.15.0 \
# mypy
# scikit-build-core
# setuptools-scm
uv-dynamic-versioning==0.13.0 \
--hash=sha256:3220cbf10987d862d78e9931957782a274fa438d33efb1fa26b8155353749e06 \
--hash=sha256:86d37b89fa2b6836a515301f74ea2d56a1bc59a46a74d66a24c869d1fc8f7585
uv-dynamic-versioning==0.14.0 \
--hash=sha256:574fbc07e87ace45c01d55967ad3b864871257b98ff5b8ac87c261227ac8db5b \
--hash=sha256:e087c346a786e98d41292ac2315180fb700cedfb30565fc973d64ce11a112387
# via mcp
versioneer==0.29 \
--hash=sha256:0f1a137bb5d6811e96a79bb0486798aeae9b9c6efc24b389659cebb0ee396cb9 \
Expand Down
Loading
Loading