LlamaIndex ChromaReader 实战指南:从持久化 Chroma 集合加载文档到 LlamaIndex
【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index
本文是一篇围绕 LlamaIndex 官方集成包llama-index-readers-chroma中ChromaReader类的技术指南。ChromaReader是 LlamaIndex 读取器(Reader)家族的一员,专门用于从已持久化的 Chroma 集合中检索文档,并将其转换为 LlamaIndex 的Document对象,从而无缝接入索引构建、检索与问答流水线。读完本文,你将掌握ChromaReader的安装方式、全部构造参数与load_data查询参数的语义、底层实现原理,并能直接用示例代码从本地磁盘或远程 Chroma 服务中批量加载数据。
ChromaReader 是什么
Chroma 是一个面向文档集合及其向量嵌入管理的高效框架,而ChromaReader的作用正是充当 LlamaIndex 与 Chroma 之间的桥梁。它在 llama-index-integrations/readers/llama-index-readers-chroma/llama_index/readers/chroma/base.py 中实现,官方描述为:
Retrieve documents from existing persisted Chroma collections.
即:从已经存在(且已持久化)的 Chroma 集合中检索文档。它不负责写入或创建集合,而是专注于读取——这也意味着在使用它之前,目标集合必须已经通过其他方式(例如chromadb客户端或 LlamaIndex 的 Chroma Vector Store)创建并写入数据。
从源码结构看,ChromaReader继承自 BaseReader,因此天然具备 LlamaIndex 读取器的统一行为:load_data返回List[Document],同时通过基类获得lazy_load_data、aload_data、load_langchain_documents等派生能力。包入口init.py 仅导出ChromaReader一个类。
安装
ChromaReader作为独立集成包发布,可通过 pip 直接安装:
pip install llama-index-readers-chroma从 pyproject.toml 可以看到其运行时依赖:
chromadb>=0.4.22,<0.5:Chroma 官方客户端库;llama-index-core>=0.13.0,<0.15:LlamaIndex 核心包,提供Document、BaseReader等基础组件。
如果你的环境尚未安装chromadb,ChromaReader会在初始化时抛出提示信息:
`chromadb` package not found, please run `pip install chromadb`初始化参数详解
ChromaReader的构造函数定义如下(源码见 base.py):
def __init__( self, collection_name: str, persist_directory: Optional[str] = None, chroma_api_impl: str = "rest", chroma_db_impl: Optional[str] = None, host: str = "localhost", port: int = 8000, ) -> None:各参数含义与底层行为:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
collection_name | str | 必填 | 要读取的持久化集合名称,None时会抛出ValueError(源码中显式校验 "Please provide a collection name.") |
persist_directory | Optional[str] | None | 集合持久化所在目录。提供后走本地持久化模式,实际路径缺省为./chroma |
chroma_api_impl | str | "rest" | Chroma API 实现方式,默认为 REST |
chroma_db_impl | Optional[str] | None | Chroma DB 实现(当前版本源码中为预留参数,不影响客户端选择逻辑) |
host | str | "localhost" | 远程 Chroma 服务主机名,用于 HTTP 客户端模式 |
port | int | 8000 | 远程 Chroma 服务端口,默认 8000 |
客户端选择逻辑:本地 vs 远程
构造函数中有一个关键分支(base.py#L43-L51):
- 当
persist_directory非空时,创建chromadb.PersistentClient(path=persist_directory),读取本地磁盘上持久化的集合; - 否则(
host或port非空,而二者均有默认值,因此通常总会进入该分支),创建chromadb.HttpClient(host=host, port=port),连接远程 Chroma 服务。
最后统一通过self._client.get_collection(collection_name)获取目标集合。需要特别注意的是:这里的get_collection要求集合已存在,如果集合不存在会报错,这与"从已有持久化集合检索"的定位一致。
load_data:文本查询与向量查询
load_data是读取器的核心入口,签名如下(base.py#L83-L125):
def load_data( self, query_embedding: Optional[List[float]] = None, limit: int = 10, where: Optional[dict] = None, where_document: Optional[dict] = None, query: Optional[Union[str, List[str]]] = None, ) -> Any:参数语义:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
query_embedding | Optional[List[float]] | None | 查询向量。提供后走向量相似度检索路径(collection.search) |
query | Optional[Union[str, List[str]]] | None | 查询文本或文本列表。提供后走文本查询路径(collection.query) |
limit | int | 10 | 返回结果数量上限,即n_results |
where | Optional[dict] | {} | 按元数据过滤,例如{"metadata_field": "is_equal_to_this"} |
where_document | Optional[dict] | {} | 按文档内容过滤,例如{"$contains": "search_string"} |
两条查询路径
源码中load_data严格按照以下优先级分派:
- 向量检索路径:
query_embedding非空时调用collection.search(query_embedding=..., n_results=limit, where=..., where_document=..., include=["metadatas", "documents", "distances", "embeddings"])。此时需要调用方自行准备查询向量(例如用 Embedding 模型对查询文本编码),适合"以向量搜向量"的语义检索场景。 - 文本查询路径:
query_embedding为空但query非空时,先将query规范化为列表(query if isinstance(query, list) else [query]),再调用collection.query(query_texts=query, ...)。此时由 Chroma 内部完成文本到向量的转换(依赖集合创建时配置的 embedding 函数),适合直接以自然语言查询。 - 异常兜底:两者都为空时抛出
ValueError("Please provide either query embedding or query."),防止无意义的空查询。
两条路径都显式传入include=["metadatas", "documents", "distances", "embeddings"],即结果中同时携带元数据、文档文本、距离分数与向量。
create_documents:结果到 LlamaIndex Document 的映射
无论走哪条查询路径,最终都会调用create_documents(results)把 Chroma 的查询结果转换为List[Document](base.py#L55-L81)。
其核心逻辑是用zip并行遍历结果的四个字段,并逐条构造Document:
documents = [] for result in zip( results["ids"][0], results["documents"][0], results["embeddings"][0], results["metadatas"][0], ): document = Document( id_=result[0], # Chroma 中的文档 ID text=result[1], # 文档文本 embedding=result[2],# 文档向量 metadata=result[3], # 文档元数据 ) documents.append(document)这里展示了几个值得注意的实现细节:
- 字段索引
[0]:Chroma 的查询结果按查询条件分组,对于单查询(一个 embedding 或一个文本),取第一个查询对应的结果列表,即results["ids"][0]等; id_直接使用 Chroma 的文档 ID:这保证了读取后的Document.node_id与 Chroma 中的原始 ID 一致,便于后续追踪与去重;- 向量被完整保留:
embedding字段被写入Document,因此读取出的文档可以直接用于构建 LlamaIndex 向量索引,无需重新计算嵌入。
与 BaseReader 的关系及异步能力
ChromaReader继承自 LlamaIndex 核心的 BaseReader(抽象基类),并直接覆写了load_data。通过基类,ChromaReader实例还自动获得以下能力:
lazy_load_data:惰性加载接口,默认抛NotImplementedError,提示子类未实现;aload_data:通过asyncio.to_thread将同步load_data包装为异步调用,可在异步代码中直接使用;load_langchain_documents:将加载结果转换为 LangChain 文档格式(d.to_langchain_format()),便于与 LangChain 生态互操作。
仓库中的单元测试 tests/test_readers_chroma.py 验证了类的继承关系:
def test_class(): names_of_base_classes = [b.__name__ for b in ChromaReader.__mro__] assert BaseReader.__name__ in names_of_base_classes该测试通过检查__mro__(方法解析顺序)确认ChromaReader确实是BaseReader的子类,从测试层面锁定了读取器体系的一致性。
完整实战示例
结合 README.md 与源码行为,一个完整的读取流程如下:
from llama_index.core.schema import Document from llama_index.readers.chroma import ChromaReader # 1. 初始化:指向已持久化的集合 reader = ChromaReader( collection_name="<Your Collection Name>", persist_directory="<Directory Path>", # 本地持久化目录 chroma_api_impl="rest", # Chroma API 实现(默认 "rest") chroma_db_impl=None, # Chroma DB 实现(默认 None) host="localhost", # 远程服务主机(默认 "localhost") port=8000, # 远程服务端口(默认 8000) ) # 2. 方式一:按文本查询(字符串或字符串列表均可) documents = reader.load_data( query_embedding=None, # 文本查询时置空 limit=10, # 返回条数 where=None, # 元数据过滤,如 {"category": "tech"} where_document=None, # 文档内容过滤,如 {"$contains": "llama"} query=["search term"], # 查询文本 ) # 3. 方式二:按向量查询(需自行提供查询向量) documents = reader.load_data( query_embedding=[0.1, 0.2, ...], # 查询向量 limit=10, ) # 4. 使用结果:构建 LlamaIndex 索引 from llama_index.core import VectorStoreIndex index = VectorStoreIndex.from_documents(documents)远程模式示例
当集合存放在远程 Chroma 服务时,不传persist_directory,改为指定host与port:
reader = ChromaReader( collection_name="my_prod_collection", host="chroma.internal.example", # 远程服务地址 port=8000, ) documents = reader.load_data(query="年度技术报告")过滤条件示例
where与where_document是 Chroma 原生的过滤能力,ChromaReader将其原样透传给底层search/query调用:
# 只检索 author 字段为 "Alice" 的文档 documents = reader.load_data( query="分布式系统", where={"author": "Alice"}, ) # 只检索正文包含 "LlamaIndex" 的文档 documents = reader.load_data( query="最佳实践", where_document={"$contains": "LlamaIndex"}, )使用注意事项
- 集合必须预先存在:
ChromaReader通过get_collection获取集合,若集合不存在会直接报错。请先用 Chroma 客户端或 LlamaIndex 的 Chroma Vector Store 写入数据并持久化。 - 本地路径缺省值:当
persist_directory非空时,源码中实际路径缺省为./chroma(persist_directory if persist_directory else "./chroma"),但该分支只有在传入非空值时才会进入。 query_embedding优先级高于query:两者同时提供时,load_data只走向量检索路径(先判断query_embedding),query会被忽略。limit默认 10:需要更多结果时显式调大,否则只会返回前 10 条。- 异步与 LangChain 互操作:如需在异步环境或 LangChain 流水线中使用,可借助基类提供的
aload_data与load_langchain_documents。 - 版本约束:本集成依赖
chromadb>=0.4.22,<0.5与llama-index-core>=0.13.0,<0.15(见 pyproject.toml),安装时请确保版本兼容。
小结
ChromaReader是 LlamaIndex 与 Chroma 生态对接的最小而完整的读取组件:构造阶段根据persist_directory/host/port自动选择本地持久化客户端或 HTTP 客户端,查询阶段支持向量检索与文本查询两条路径,并通过create_documents将 Chroma 结果无损映射为携带id_、text、embedding、metadata的 LlamaIndexDocument。无论你是想把已有 Chroma 集合中的数据直接灌入索引,还是作为检索工具嵌入 Agent 流水线,都可以基于本文给出的参数表与示例快速落地。
【免费下载链接】llama_indexLlamaIndex is the leading document agent and OCR platform项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考