news 2026/9/17 21:07:21

Feast 向量数据库(Alpha):从 Embedding 存储到 OpenAI 兼容检索的完整实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Feast 向量数据库(Alpha):从 Embedding 存储到 OpenAI 兼容检索的完整实践

Feast 向量数据库(Alpha):从 Embedding 存储到 OpenAI 兼容检索的完整实践

【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feast

功能状态说明:向量数据库是 Feast 的一项实验性(Alpha)功能。官方文档声明该功能目前总体稳定,但在使用体验上仍存在一些粗糙之处,欢迎社区贡献改进。本文基于当前仓库的 alpha-vector-database.md 文档及 sdk/python/feast 源码编写,帮助读者掌握如何用 Feast 存储与检索 Embedding,并接入 RAG 与 LLM 应用。

1. 概览:Feast 如何抽象向量检索

向量数据库允许用户存储并检索 Embedding 向量。Feast 提供了通用 API来完成 Embedding 的写入与相似度检索,其核心思路是:把"带向量的 Feature View"物化到支持向量检索的在线存储中,再通过统一的 SDK / HTTP 接口完成 top-k 相似度搜索。

从源码结构看,这一能力由 feature_store.py 中的retrieve_online_documents/retrieve_online_documents_v2两个方法,以及 vector_store.py 中的FeastVectorStore封装类共同承担。其中FeastVectorStore是一个便捷门面,同时支持文本、图像与多模态检索,它会在初始化时自动扫描 Feature View 中带vector_index的字段并读取其vector_search_metric作为默认距离度量(参见 vector_store.py)。

2. 支持的向量数据库与集成矩阵

官方文档给出了当前仓库中已集成的向量数据库及其能力矩阵:

向量数据库检索 (Retrieval)索引 (Indexing)V2 支持*在线读取 (Online Read)
Pgvector✔️
Elasticsearch✔️✔️
Milvus✔️✔️✔️✔️
Faiss
SQLite✔️✔️✔️
Qdrant✔️✔️
ScyllaDB✔️✔️✔️✔️

*V2 支持:指 SDK 支持在向量相似度检索的同时,一并取回标准特征(Feature)与向量 Embedding。

两点补充说明:

  1. SQLite 处于受限访问状态,目前仅在 Python 3.10 上可用,其能力会随 sqlite-vec 项目进展而更新;
  2. 从仓库测试与示例看,Milvus、SQLite、ScyllaDB已在 SDK 层实现了 v2 方法retrieve_online_documents_v2,相关实现在 milvus.py、sqlite.py、scylladb.py 中。

3. API 演进:retrieve_online_documentsretrieve_online_documents_v2

官方文档对两代检索方法给出了明确的演进说明(摘自文档中的 danger 提示):

未来 SDK 将弃用retrieve_online_documents,官方推荐改用retrieve_online_documents_v2。v2 的优势在于:可以直接在 Feature View 上配置向量索引,并且能够在返回向量 Embedding 的同时取回标准特征,便于做更丰富的上下文注入。长远来看,两个方法最终会合并为一个;届时retrieve_online_documentsretrieve_online_documents_v2都会指向get_online_features,以兼容业界标准命名约定。

两代方法在源码中的差异也印证了这一演进方向:

  • retrieve_online_documents(feature_store.py)只接受Embedding 向量作为查询(query: Union[str, List[float]]),若直接传字符串会抛出ValueError,提示需先完成文本 Embedding;且一次只支持单个 Feature View(feature_view_set长度大于 1 即报错)。
  • retrieve_online_documents_v2(feature_store.py)支持query(文本 Embedding)、query_string(混合检索文本)、query_image_bytes(图像相似度检索)三种查询形态,并支持combine_with_text多模态融合(text_weight + image_weight必须等于 1.0,否则报错)、filters元数据过滤,以及可选的include_feature_view_version_metadata版本元数据。

此外,v2 还内置了对 On-Demand Feature View 的支持(会从available_odfv_views中解析),使检索链路可以衔接在线变换。

4. Feature Server 检索端点总览

官方文档给出了 Feature Server 对外暴露的检索端点速查表:

端点适用场景
POST /search你已持有 Embedding 向量(或使用api_version: 2query_string),希望获得 Feast 原生的在线特征响应格式
GET /v1/vector_stores发现可用的向量存储及其vs_{hash}ID(OpenAI 兼容)
GET /v1/vector_stores/{id}获取某个具体向量存储的元数据(OpenAI 兼容)
POST /v1/vector_stores/{id}/search使用纯文本查询 + 服务端 Embedding,返回 OpenAI 兼容响应

POST /retrieve-online-documents已弃用,请改用POST /search这一点在 feature_server.py 中也有体现:/retrieve-online-documents路由会先返回弃用提示,再转发到与/search相同的处理逻辑。

5. [Alpha] OpenAI 兼容向量存储 API

Alpha 特性警告:该 API 面已可运行且经过测试,但可能在后续版本中调整,欢迎反馈与贡献。

Feast 暴露了一组OpenAI 兼容的向量存储端点,让客户端可以用纯文本查询 + 服务端 Embedding来发现、查看与检索向量存储。这意味着AI Agent、LLM 工具调用框架以及任何 OpenAI 兼容客户端都可以直接对接,调用方无需自行产出原始 Embedding 向量。

5.1 向量存储 ID 的生成规则

每个包含至少一个vector_index=True字段的 Feature View,都会被自动分配一个确定性标识符,形如vs_{hash},其中{hash}SHA-256(project + ":" + feature_view_name)的前 24 个字符。该 ID 在服务重启与 Registry 刷新后保持稳定。

例如,项目my_project下的 Feature Viewproduct_catalog总是映射到同一个vs_...标识。列出端点会返回这些 ID,客户端可以在运行时发现存储。

这一规则在 vector_store_utils.py 中有精确实现:

def feature_view_to_vs_id(project: str, feature_view_name: str) -> str: digest = hashlib.sha256(f"{project}:{feature_view_name}".encode()).hexdigest()[:24] return f"vs_{digest}"

5.2 端点与权限

方法路径所需权限说明
GET/v1/vector_storesDESCRIBE列出调用方有权限访问的全部向量存储
GET/v1/vector_stores/{vector_store_id}DESCRIBE获取单个向量存储的元数据
POST/v1/vector_stores/{vector_store_id}/searchREAD_ONLINE用纯文本查询检索向量存储

配置了认证后,以上所有端点都会强制RBAC校验;列出端点会自动过滤掉调用方无权DESCRIBE的存储。这些路由定义于 feature_server.py,服务端通过store.openai_search(...)处理POST .../search请求。

5.3 启用前置条件

要使用该 API,需要满足以下三点:

① 配置 Embedding 模型—— 在feature_store.yaml中增加embedding_model段。默认使用Sentence Transformers做本地 Embedding,无需外部 API Key(安装pip install sentence-transformers即可):

embedding_model: provider: sentence_transformers # 默认值,可省略 model: all-MiniLM-L6-v2

② 定义带向量索引的 Feature View—— 至少有一个 Feature View 在向量字段上设置了vector_index=True,并且物化到支持向量检索的在线存储中。

③ (可选)数值过滤支持—— 若元数据过滤涉及数值或布尔比较,需要在在线存储配置中开启enable_openai_compatible_store: true,然后执行feast apply以在数据库中新增value_num列。

5.4 自定义 Embedding Provider

内置的 Sentence Transformers Provider 适用于大多数场景。若想接入其他 Embedding 后端(OpenAI、Cohere 或自研模型),可以实现EmbeddingProvider协议并将实例传给FeatureStore

from feast.embedder import EmbeddingProvider class MyEmbeddingProvider: def embed(self, texts: list[str]) -> list[list[float]]: # 在此调用你的 Embedding API return my_model.encode(texts) async def aembed(self, texts: list[str]) -> list[list[float]]: return await my_model.aencode(texts) store = FeatureStore( repo_path=".", embedding_provider=MyEmbeddingProvider(), )

从源码看,该协议定义于 embedder.py,内置的SentenceTransformersEmbeddingProvider(embedder.py)通过from_config工厂构造,模型加载采用惰性初始化——只有真正调用embed/aembed时才导入 sentence-transformers,避免启动开销。get_embedding_provider工厂会按config.provider分发(默认sentence_transformers),未知 Provider 名称会抛出ValueError

5.5 数值存储:enable_openai_compatible_store

默认情况下,特征值在在线存储中以文本形式保存,因此字符串排序规则生效(例如'9' > '100'true)。当在线存储配置中开启enable_openai_compatible_store: true后,Feast 会新增一个value_num列,用原生类型存储intfloatdoublebool值,从而保证数值过滤结果正确:

online_store: type: postgres # 或 sqlite # ... 连接配置 ... enable_openai_compatible_store: true

修改该配置后,需运行feast apply更新数据库表结构。

5.6 端点使用示例

以下请求默认 Feature Server 运行在localhost:6566feast serve启动)。

列出向量存储:

curl http://localhost:6566/v1/vector_stores
{ "object": "list", "data": [ { "id": "vs_a1b2c3d4e5f6a1b2c3d4e5f6", "object": "vector_store", "name": "product_catalog", "status": "completed", "created_at": 1717200000 } ] }

获取单个向量存储:

curl http://localhost:6566/v1/vector_stores/vs_a1b2c3d4e5f6a1b2c3d4e5f6

返回对象形状与列表响应中的单个条目一致;若 ID 不匹配任何带向量索引的 Feature View,返回404

执行检索:

curl -X POST http://localhost:6566/v1/vector_stores/vs_a1b2c3d4e5f6a1b2c3d4e5f6/search \ -H "Content-Type: application/json" \ -d '{ "query": "wireless noise-cancelling headphones", "max_num_results": 5 }'

5.7 请求字段说明

字段类型默认值说明
querystringlist[string]必填纯文本检索查询。列表会在 Embedding 前用空格拼接
max_num_resultsint10返回结果的最大条数
filtersobjectnullOpenAI 风格过滤器(见下文)
ranking_optionsobjectnull为向前兼容而接受,但当前被忽略;在其中设置score_thresholdranker将返回 422 错误
rewrite_queryboolnull接受false(默认/无操作);true尚未支持,将返回 422 错误
metadataobjectnull可选;metadata.features_to_retrieve用于挑选特定特征

5.8 元数据过滤器(OpenAI 风格)

端点支持在向量相似度之外,用 OpenAI 风格过滤器进一步收窄结果。

比较运算符eqnegtgteltlteinnin

{"type": "eq", "key": "category", "value": "Electronics"}

复合运算符andor(可任意深度嵌套)

{ "type": "and", "filters": [ {"type": "eq", "key": "category", "value": "Electronics"}, {"type": "gte", "key": "rating", "value": 4.5} ] }

使用限制:

  • 对于Postgres 与 SQLite后端,所有过滤(包括字符串相等比较)都要求在线存储开启enable_openai_compatible_store: true;开启后执行feast apply更新表结构;
  • ScyllaDB支持通过retrieve_online_documents_v2进行向量检索,但OpenAI 风格元数据过滤尚未实现——传入filters会抛出NotImplementedError

5.9 响应格式与分数转换

响应遵循 OpenAIvector_store.search_results.page模式:

{ "object": "vector_store.search_results.page", "search_query": ["wireless noise-cancelling headphones"], "data": [ { "file_id": "vs_a1b2c3d4e5f6a1b2c3d4e5f6_42", "filename": "vs_a1b2c3d4e5f6a1b2c3d4e5f6", "score": 0.92, "attributes": {"name": "...", "category": "..."}, "content": [ {"type": "text", "text": "..."} ] } ], "has_more": false, "next_page": null }

要点解读:

  • file_idfilename字段使用vs_{hash}标识符,而非原始 Feature View 名称;
  • score越高越好的相关性分数,由原始向量距离按度量类型换算而来:
距离度量换算公式取值范围
L2(默认)1 / (1 + distance)(0, 1]
Cosine1 - distance[0, 1]
内积 / 点积-distance不定
  • 度量由 Feature View 向量字段上的vector_search_metric决定,不由 API 参数指定。该换算逻辑在 utils.py 的_distance_to_score中实现;
  • 省略features_to_retrieve时,默认返回全部非向量特征(向量 Embedding 列会被排除);
  • 分页尚未实现,has_more恒为false

从 feature_store.py 的openai_search实现可以看到完整的响应组装链路:先经embedding_provider.aembed对查询文本做 Embedding,再调用retrieve_online_documents_v2获取结果,最后逐行将distance换算为score、把字符串特征组装进content、并用排序后的实体键拼接file_id(无实体时回退为下标)。

5.10 通过 Python SDK 直接调用

OpenAI 兼容检索也可直接通过 Python SDK 使用(注意openai_search异步方法):

import asyncio from feast import FeatureStore store = FeatureStore(repo_path=".") result = asyncio.run(store.openai_search( vector_store_id="product_catalog", query="wireless noise-cancelling headphones", max_num_results=5, filters={"type": "eq", "key": "category", "value": "Electronics"}, )) for item in result["data"]: print(f"{item['score']:.3f} {item['attributes']}")

SDK 参数与 HTTP 端点一一对应:vector_store_id对应 Feature View 名称(内部映射为vs_{hash}),filters既支持字典也支持ComparisonFilter/CompoundFilter类型对象。

5.11 各在线存储的 OpenAI 兼容支持情况

官方文档确认已为下列在线存储实现了 OpenAI 兼容过滤:

在线存储向量检索元数据过滤备注
Milvus✔️✔️布尔表达式
Elasticsearch✔️✔️Query DSL 子句
Postgres(pgvector)✔️✔️enable_openai_compatible_store: true
SQLite(sqlite-vec)✔️✔️enable_openai_compatible_store: true
MongoDB✔️✔️聚合管道
ScyllaDB✔️仅向量检索;元数据过滤暂未支持

6. 端到端示例:Milvus 上的 RAG 检索

官方文档给出了一条完整的 RAG 链路(v1 路线,基于retrieve_online_documents_v2),完整可运行示例见仓库中的 examples/rag/milvus-quickstart.ipynb(配套的 Feature Repo 位于 examples/rag/feature_repo)。v0 路线的retrieve_online_documents用法见 Rag Demo 的 module_4_rag(官方已计划迁移与弃用)。

6.1 准备离线 Embedding 数据集

运行以下命令生成 Embedding 数据集:

python pull_states.py python batch_score_documents.py

输出将存储在data/city_wikipedia_summaries.csv中。

6.2 初始化 Feature Store 并物化到在线存储

使用下面的feature_store.yaml初始化特征仓库:数据源使用本地文件作为离线存储,Milvus 作为在线存储

project: local_rag provider: local registry: data/registry.db online_store: type: milvus path: data/online_store.db vector_enabled: true embedding_dim: 384 index_type: "IVF_FLAT" offline_store: type: file entity_key_serialization_version: 3 # 默认 no_auth;其他可选值:kubernetes、oidc,详见相关文档 auth: type: no_auth

然后在终端执行:

feast apply

执行feast apply时,会注册下面这个后续用于检索的 Feature View:

document_embeddings = FeatureView( name="embedded_documents", entities=[item, author], schema=[ Field( name="vector", dtype=Array(Float32), # 看,开启 RAG 就是这么简单! vector_index=True, vector_search_metric="COSINE", ), Field(name="item_id", dtype=Int64), Field(name="author_id", dtype=String), Field(name="created_timestamp", dtype=UnixTimestamp), Field(name="sentence_chunks", dtype=String), Field(name="event_timestamp", dtype=UnixTimestamp), ], source=rag_documents_source, ttl=timedelta(hours=24), )

随后用 SDK 把包含 Embedding 的 DataFrame 写入在线存储:

store.write_to_online_store(feature_view_name='city_embeddings', df=df)

6.3 生成查询 Embedding

推理阶段(例如用户提交聊天消息时)需要对输入文本做 Embedding。这可以看作对输入数据的一次特征变换。示例中使用 Hugging Face 的小型 Sentence Transformer 完成:

import torch import torch.nn.functional as F from feast import FeatureStore from pymilvus import MilvusClient, DataType, FieldSchema from transformers import AutoTokenizer, AutoModel from example_repo import city_embeddings_feature_view, item TOKENIZER = "sentence-transformers/all-MiniLM-L6-v2" MODEL = "sentence-transformers/all-MiniLM-L6-v2" def mean_pooling(model_output, attention_mask): token_embeddings = model_output[ 0 ] # model_output 的第一个元素包含所有 token 的 Embedding input_mask_expanded = ( attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float() ) return torch.sum(token_embeddings * input_mask_expanded, 1) / torch.clamp( input_mask_expanded.sum(1), min=1e-9 ) def run_model(sentences, tokenizer, model): encoded_input = tokenizer( sentences, padding=True, truncation=True, return_tensors="pt" ) # 计算 token Embedding with torch.no_grad(): model_output = model(**encoded_input) sentence_embeddings = mean_pooling(model_output, encoded_input["attention_mask"]) sentence_embeddings = F.normalize(sentence_embeddings, p=2, dim=1) return sentence_embeddings question = "Which city has the largest population in New York?" tokenizer = AutoTokenizer.from_pretrained(TOKENIZER) model = AutoModel.from_pretrained(MODEL) query_embedding = run_model(question, tokenizer, model).detach().cpu().numpy().tolist()[0]

6.4 检索 top-K 相似文档

创建 Feature Store 实例,调用retrieve_online_documents_v2检索与查询最相似的 3 条文档:

context_data = store.retrieve_online_documents_v2( features=[ "city_embeddings:vector", "city_embeddings:item_id", "city_embeddings:state", "city_embeddings:sentence_chunks", "city_embeddings:wiki_summary", ], query=query_embedding, top_k=3, distance_metric='COSINE', ).to_df()

注意这里featuresfeature_view:feature形式引用多个特征,一次调用即可同时取回向量相似度结果与文档相关的标准特征,这正是 v2 方法的核心价值。

6.5 用 LLM 生成最终回答

假设已有基础提示词BASE_PROMPT和格式化检索结果的函数format_documents,可以将检索到的上下文拼入提示词后调用 OpenAI 的 Chat Completion API:

FULL_PROMPT = format_documents(rag_context_data, BASE_PROMPT) from openai import OpenAI client = OpenAI( api_key=os.environ.get("OPENAI_API_KEY"), ) response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": FULL_PROMPT}, {"role": "user", "content": question} ], ) # 输出回答内容。端到端示例见 examples/rag/milvus-quickstart.ipynb print('\n'.join([c.message.content for c in response.choices]))

至此,"文档入库 → 向量检索 → 上下文注入 → LLM 生成"的完整 RAG 闭环就打通了。

7. 配置与安装

Feast 为向量数据库场景提供以下在线存储选项:Milvus、PGVector、SQLite(sqlite-vec)、Elasticsearch、Qdrant。其中 Milvus 提供了便捷的本地实现用于向量相似度检索。

按需选择对应的安装方式:

# Milvus pip install feast[milvus] # Elasticsearch pip install feast[elasticsearch] # Qdrant pip install feast[qdrant]

SQLite 特殊说明:若使用pyenv管理 Python 版本,需要先安装带可加载扩展支持的 Python 3.10:

PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" \ LDFLAGS="-L/opt/homebrew/opt/sqlite/lib" \ CPPFLAGS="-I/opt/homebrew/opt/sqlite/include" \ pyenv install 3.10.14

然后安装 Feast 的 SQLite 向量扩展包:

pip install feast[sqlite_vec]

8. 小结与建议

  • 新项目直接使用 v2 路线retrieve_online_documents_v2支持在 Feature View 上直接声明向量索引(vector_index=True+vector_search_metric),并能在检索向量的同时取回标准特征,是官方推荐的长期方案;
  • AI Agent 集成首选 OpenAI 兼容 API/v1/vector_stores/*系列端点支持纯文本查询与服务端 Embedding,配合 embedder.py 的EmbeddingProvider协议可以无缝替换任意 Embedding 后端,无需调用方关心向量细节;
  • 数值过滤需显式开启:Postgres / SQLite 上若元数据过滤涉及数值或布尔比较,务必开启enable_openai_compatible_store: true并重新执行feast apply
  • 关注功能演进:该 API 处于 Alpha 阶段,retrieve_online_documents已进入弃用计划,ranking_optionsrewrite_query等参数尚未实现,使用时建议以当前仓库文档与源码为准。

【免费下载链接】feastThe Open Source Feature Store for AI/ML项目地址: https://gitcode.com/GitHub_Trending/fe/feast

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 21:04:05

Pdman数据库建模工具实战:从表结构设计到SQL生成与逆向工程

做数据库设计这行,最烦的就是改来改去。表结构改了一版又一版,同事那边用的还是旧脚本,建表语句在不同的库里面跑出好几个版本——这个场景我太熟了。后来我把建模工作切到Pdman数据库建模工具上,才慢慢把这一摊事理顺。Pdman是一…

作者头像 李华
网站建设 2026/9/17 21:03:31

DRBFM 宣讲稿结构化:python-pptx 提取变化点与评审闭环

简介:面向制造业品质管理、设计与工艺工程师的DRBFM宣讲培训课件,围绕事前预防(Prevention Method)展开,帮助团队理解如何在问题发生前识别并控制风险。课件从品质意识切入,剖析大企业病、品质文化、顾客选…

作者头像 李华
网站建设 2026/9/17 21:00:33

用Multisim仿真设计5W音频功放:从电路搭建到演示视频全流程

1. 为什么先用Multisim把音频功放跑通我在电子爱好者的群里看了太多次类似的求助了:照着网上的音频功率放大器原理图画PCB,结果焊好一上电,要么没声音,要么管子烫得能煎鸡蛋。Multisim这个软件在国内电子类专业几乎人手一份&#…

作者头像 李华
网站建设 2026/9/17 20:58:51

PHP与Go框架性能对比:真实业务场景下的选型指南

1. 这不是“谁更快”的口水战,而是选型现场的实时决策推演你刚接到一个新项目需求:日均活跃用户50万,核心是高频图片上传、实时缩略图生成与多端内容分发。技术选型会上,后端组有人拍桌:“PHP生态成熟,Lara…

作者头像 李华
网站建设 2026/9/17 20:58:12

STM32CubeMX安装实战:AI嵌入式编程工作流的地基

我一直觉得嵌入式开发里最容易被低估的工具,就是 STM32CubeMX。尤其在最近把 AI 编程引入日常工作流之后,我反而更觉得这工具是绕不开的地基。很多人以为 AI 编程就是跟 Claude 说一句话,然后直接拿代码去烧录,真这么干十有八九会…

作者头像 李华