LlamaIndex 集成 Bagel 向量数据库:BagelVectorStore 实战指南
【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index
导读
本文围绕 LlamaIndex 官方集成包llama-index-vector-stores-bagel中的核心类BagelVectorStore,系统讲解如何在 LlamaIndex 检索管线中接入 Bagel 向量数据库:从安装配置、客户端与 Cluster 的创建,到节点写入、元数据过滤、相似度查询与删除的完整链路,并深入源码剖析其与 LlamaIndex 核心抽象(BasePydanticVectorStore、VectorStoreQuery)的对接原理。读完本文,你将能够独立完成 Bagel 后端与 LlamaIndex 的端到端接入,并理解其查询结果相似度换算与元数据序列化的底层实现。
一、集成包概览
BagelVectorStore是 LlamaIndex 针对 Bagel 向量数据库实现的官方适配器,代码位于 llama-index-integrations/vector_stores/llama-index-vector-stores-bagel/llama_index/vector_stores/bagel/base.py,并通过init.py 对外导出。本文所对应的 API 参考文档为 docs/api_reference/api_reference/storage/vector_store/bagel.md,其内容由 mkdocstrings 依据源码 docstring 自动生成。
从包元数据(pyproject.toml)可以确认该集成包的关键约束:
- 包名:
llama-index-vector-stores-bagel(当前版本 0.5.0); - 依赖:
llama-index-core>=0.13.0,<0.15,因此与 LlamaIndex 0.13.x 系列核心库配套使用; - Python 版本要求:
>=3.10,<4.0。
BagelVectorStore继承自 LlamaIndex 核心层的BasePydanticVectorStore(定义于 llama-index-core/llama_index/core/vector_stores/types.py),这意味着它天然兼容VectorStoreIndex、StorageContext等 LlamaIndex 上层组件,可作为标准向量存储后端直接参与索引构建与查询。
二、安装与依赖
安装该集成包使用 pip 即可:
pip install llama-index-vector-stores-bagel注意:运行环境还需要额外安装 Bagel 官方 Python 客户端库
bagel。源码中 base.py 在初始化时会尝试from bagel.api.Cluster import Cluster,若导入失败会抛出ImportError("Bagel is not installed. Please install bagel."),所以务必确保 Bagel 客户端已安装。
三、快速开始:创建客户端与 Cluster
Bagel 的命名体系与其他向量数据库略有差异:它使用Cluster(集群)的概念来承载集合数据。官方 docstring 给出了最小可运行示例:
from llama_index.core import VectorStoreIndex, StorageContext from llama_index.vector_stores.bagel import BagelVectorStore import bagel from bagel import Settings # 配置 Bagel 服务端参数:走 REST 协议,指向云端服务 server_settings = Settings( bagel_api_impl="rest", bagel_server_host="api.bageldb.ai" ) client = bagel.Client(server_settings) # 获取或创建名为 testing_embeddings 的 Cluster collection = client.get_or_create_cluster("testing_embeddings") # 用该 Cluster 构建 LlamaIndex 向量存储 vector_store = BagelVectorStore(collection=collection)关键点拆解:
| 步骤 | 说明 |
|---|---|
Settings(bagel_api_impl="rest", ...) | 指定 Bagel 客户端使用 REST 实现连接服务端;如需自建服务,可将bagel_server_host改为自建地址 |
bagel.Client(server_settings) | 基于配置创建 Bagel 客户端 |
client.get_or_create_cluster(name) | 幂等获取 Cluster;不存在则自动创建 |
BagelVectorStore(collection=...) | 将 Cluster 包装为 LlamaIndex 向量存储实例 |
在 base.py 的构造函数中,collection参数会被严格校验:必须传入bagel.api.Cluster.Cluster实例,否则抛出ValueError("Collection must be a bagel Cluster.")。因此你不能直接传普通 dict 或字符串,必须使用 Bagel 客户端获取到的 Cluster 对象。
接入索引的标准姿势
获得BagelVectorStore后,可以像使用其他向量存储一样将其挂载到StorageContext并构建索引:
from llama_index.core import VectorStoreIndex, StorageContext storage_context = StorageContext.from_defaults(vector_store=vector_store) # 方式一:已有文档节点,直接构建索引并持久化到 Bagel index = VectorStoreIndex.from_documents( documents, storage_context=storage_context ) # 方式二:后续查询时复用已有 Bagel 存储 index = VectorStoreIndex.from_vector_store(vector_store)四、核心 API 详解
BagelVectorStore的完整实现集中在 base.py(约 217 行),下面逐一剖析其公开能力。
4.1 类级配置项
stores_text: bool = True flat_metadata: bool = Truestores_text:声明该存储会保存节点文本,便于 LlamaIndex 上层判断是否需要额外保留文本;flat_metadata:控制写入元数据时是否扁平化。为True时调用node_to_metadata_dict(..., flat_metadata=True)生成扁平结构的 metadata dict,兼容 Bagel 的存储格式。
4.2 add:写入节点
def add(self, nodes: List[BaseNode], **add_kwargs: Any) -> List[str]:add接收带 embedding 的BaseNode列表,逐节点提取:
ids:取node.node_id;embeddings:取node.get_embedding();metadatas:通过node_to_metadata_dict(node, remove_text=True, flat_metadata=self.flat_metadata)序列化(移除文本字段以避免冗余,扁平化后写入);documents:取node.get_content(metadata_mode=MetadataMode.NONE),即纯文本内容。
随后一次性调用self._collection.add(ids=ids, embeddings=embeddings, metadatas=metadatas, documents=documents)批量写入,并返回全部node_id列表。若_collection未设置,会抛出ValueError("collection not set")。
4.3 delete:按文档删除
def delete(self, ref_doc_id: str, **kwargs: Any) -> None:delete首先以where={"doc_id": ref_doc_id}在 Cluster 中检索与该文档关联的所有记录,拿到ids后调用self._collection.delete(ids=...)完成删除。这意味着删除的粒度是"按源文档(ref_doc_id)",而非单个节点——符合 LlamaIndex 中删除整篇文档的语义约定。
4.4 client:访问底层 Cluster
@property def client(self) -> Any: return self._collectionclient属性直接暴露内部的 Bagel Cluster 对象,便于需要绕过封装、直接执行原生操作的场景。
4.5 query:相似度查询
def query(self, query: VectorStoreQuery, **kwargs: Any) -> VectorStoreQueryResult:query是检索的核心入口,其内部逻辑为:
- 过滤条件解析:若
query.filters非空,则调用模块级函数_to_bagel_filter将 LlamaIndex 标准的MetadataFilters转换为 Bagel 的wheredict;若同时通过kwargs传入了where,会抛出ValueError("Cannot specify both filters and where")以避免冲突;若没有 filters,则回退使用kwargs.get("where", {})。 - 执行检索:调用
self._collection.find(query_embeddings=query.query_embedding, where=where, n_results=query.similarity_top_k, **kwargs)。 - 结果重建:遍历返回的
ids、documents、metadatas、distances,优先通过metadata_dict_to_node(metadata)反序列化节点并set_content(text);若失败(为兼容历史遗留格式),回退到legacy_metadata_dict_to_node并手动构造TextNode。 - 相似度换算:Bagel 返回的是距离值
distance,代码用1.0 - math.exp(-distance)将其映射为相似度分数(距离为 0 时相似度趋近 1,距离越大相似度越小)。
最终返回VectorStoreQueryResult(nodes=nodes, similarities=similarities, ids=ids),与 LlamaIndex 核心查询引擎无缝衔接。
4.6 元数据过滤的底层转换
模块级辅助函数_to_bagel_filter负责两种过滤语法的桥接:
def _to_bagel_filter(standard_filters: MetadataFilters) -> dict: filters = {} for filter in standard_filters.legacy_filters(): filters[filter.key] = filter.value return filters它遍历MetadataFilters.legacy_filters()(该方法定义于 llama-index-core/llama_index/core/vector_stores/types.py),提取每个过滤项的key与value,组成{key: value}形式的 where 条件交给 Bagel 执行。从源码结构看,当前实现采用精确匹配(Equality)语义,适合按字段等值过滤的场景。
五、查询参数:VectorStoreQuery 语义
BagelVectorStore.query接收的是 LlamaIndex 核心定义的VectorStoreQuery(见 llama-index-core/llama_index/core/vector_stores/types.py),其中与 Bagel 集成直接相关的字段包括:
| 字段 | 默认值 | 在 Bagel 集成中的作用 |
|---|---|---|
query_embedding | None | 查询向量,作为find的query_embeddings参数 |
similarity_top_k | 1 | 返回 Top-K 结果,作为find的n_results参数 |
filters | None | 元数据过滤条件,经_to_bagel_filter转为 Bagelwhere |
也就是说,LlamaIndex 的VectorIndexRetriever等组件在构建查询时设置的similarity_top_k与过滤条件,会被原样传递给 Bagel 的find调用,无需额外适配。
六、与核心抽象的关系:测试验证
集成包的测试位于 tests/test_vector_stores_bagel.py,虽然仅有一个用例,但它精确验证了架构契约:
def test_class(): names_of_base_classes = [b.__name__ for b in BagelVectorStore.__mro__] assert BasePydanticVectorStore.__name__ in names_of_base_classes该测试断言BagelVectorStore的 MRO(方法解析顺序)中包含BasePydanticVectorStore,从测试层面固化了"Bagel 集成属于 LlamaIndex 标准向量存储家族"这一事实。因此:
- 它可以被
StorageContext.from_defaults(vector_store=...)直接接收; - 它可以作为
VectorStoreIndex的持久化后端; - 它遵循统一的
add / delete / query / client接口约定,便于在多种向量存储之间切换。
七、实战注意事项
- Cluster 而非 Collection:Bagel 使用 Cluster 组织数据,
get_or_create_cluster是幂等操作,重复调用不会报错,适合长期复用同一存储。 - 相似度方向:Bagel 返回距离,集成层使用
1.0 - math.exp(-distance)换算相似度,属于非线性映射。若直接使用client属性读取原始结果,拿到的是距离值而非相似度。 - 过滤与
where互斥:当VectorStoreQuery.filters已设置时,不能再通过kwargs传where,否则会抛出异常;建议统一走MetadataFilters标准通道。 - 元数据扁平化:
flat_metadata=True是默认行为,嵌套结构的元数据在写入前会被扁平化处理,设计数据结构时应注意这一点。 - 文本存储:
stores_text=True表示 Bagel 后端保存了节点原文,查询时metadata_dict_to_node反序列化后可立即set_content(text),无需额外的文档存储兜底。
结语
BagelVectorStore是一个轻量而完整的向量存储适配器:它以约两百行代码实现了 LlamaIndex 标准接口与 Bagel 原生命令的桥接,覆盖写入、按文档删除、带过滤的 Top-K 查询、相似度换算与元数据序列化等全部关键路径。无论是接入云端 Bagel 服务还是自建部署,按照本文的安装、初始化和集成步骤,你都能在数分钟内将 Bagel 作为 LlamaIndex 的检索后端投入使用;如需深入,可直接阅读 base.py 与核心抽象 types.py 的完整实现。
【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考