Article

向量数据库Chroma

更新于:2026-07-16

第一章:Chroma 概述与核心概念

1.1 什么是 Chroma

概念名称说明注意事项
ChromaChroma 是一个开源的向量数据库(Vector Database),专为 AI 应用(如语义搜索、RAG 系统)设计,用于高效存储、索引和检索高维向量数据。Chroma 不仅支持向量,还支持关联的元数据(metadata)和原始文档(documents),便于构建端到端 AI 应用。
向量数据库一种专门用于存储和查询嵌入向量(embedding vectors)的数据库,支持近似最近邻(ANN)搜索。与传统关系型数据库不同,向量数据库优化的是”相似性”而非”精确匹配”。
嵌入(Embedding)将文本、图像等非结构化数据转换为固定维度的数值向量,保留语义信息。Chroma 本身不生成嵌入,但可集成嵌入模型自动完成转换。

1.2 Chroma 的核心特性

特性名称说明注意事项
开源免费Chroma 采用 Apache 2.0 许可证,完全开源,可自由使用和修改。社区版功能已足够强大,企业级功能(如分布式部署)仍在演进中。
内置嵌入支持支持自动调用 Sentence Transformers 等模型生成嵌入,无需手动预处理。首次使用内置嵌入函数时会自动下载模型,需联网且占用磁盘空间(约 500MB+)。
多客户端模式支持内存模式(In-memory)、本地持久化(PersistentClient)和远程 HTTP 客户端(HttpClient)。内存模式适合开发测试;生产环境建议使用持久化或服务化部署。
元数据过滤可在向量检索时结合 JSON 格式的元数据进行条件过滤(如 where={"category": "tech"})。元数据字段需在插入时定义,且过滤性能依赖底层索引实现。
轻量易集成提供简洁 Python API,与 LangChain、LlamaIndex 等主流 LLM 框架深度集成。当前主要语言支持为 Python,JavaScript/TypeScript 支持处于实验阶段。
自动索引管理默认使用 HNSW 算法构建近似最近邻索引,插入数据后自动更新索引。索引参数(如 ef_constructionM)可通过 Collection 配置调整,影响精度与性能。

1.3 Chroma 与其他向量数据库对比

对比维度ChromaPineconeMilvusWeaviate
开源状态✅ 完全开源(Apache 2.0)❌ 闭源(托管服务为主)✅ 开源(Apache 2.0)✅ 开源(BSD-3)
部署复杂度⭐ 极简(单机 Python 包即可运行)⭐⭐⭐ 需注册账号,依赖云服务⭐⭐⭐⭐ 需 Docker/K8s,组件多⭐⭐ 可容器化,配置较复杂
嵌入集成✅ 内置 Sentence Transformers 等❌ 需自行提供向量❌ 需自行提供向量✅ 内置多种嵌入模块
元数据过滤✅ 支持 where 和 where_document✅ 支持 metadata 过滤✅ 强大标量/向量混合查询✅ GraphQL + 语义过滤
适用场景本地开发、原型验证、小型 RAG 应用云端生产级应用大规模、高性能企业级应用语义知识图谱、混合搜索
社区生态快速增长,LangChain 官方推荐商业驱动,文档完善成熟,CNCF 项目活跃,强调语义层

注意事项:

  • Chroma 当前(截至 2026 年)仍以单机架构为主,不原生支持分布式集群,不适合超大规模(亿级向量)场景。
  • 若需横向扩展,可考虑将其作为缓存层,或等待官方 Chroma Cloud / 分布式版本成熟。
  • 对于快速搭建 RAG 原型,Chroma 是目前最轻量、集成最便捷的选择。

第二章:环境准备与快速上手

2.1 安装 Chroma

步骤名称操作细节注意事项
安装核心包在终端执行:pip install chromadb推荐使用 Python 3.8+ 环境;若网络较慢,可使用国内镜像源(如 -i https://pypi.tuna.tsinghua.edu.cn/simple
安装嵌入依赖(可选)若使用内置嵌入模型,首次运行会自动安装 sentence-transformerstorch;也可提前手动安装:pip install sentence-transformers torchtorch 体积较大(约 500MB–1GB),若仅使用 CPU 可安装 torch --extra-index-url https://download.pytorch.org/whl/cpu 减少体积
验证安装在 Python 中执行:import chromadb; print(chromadb.__version__)若报错 No module named 'chromadb',请检查虚拟环境是否激活或 pip 是否指向正确 Python 版本

2.2 创建第一个 Collection

方法名称语法用途代码示例注意事项
chromadb.Client()client = chromadb.Client()创建一个内存模式的 Chroma 客户端实例import chromadb
client = chromadb.Client()
默认为内存模式,程序退出后数据丢失;适用于开发测试
client.create_collection()collection = client.create_collection(name="my_collection")创建一个名为 my_collection 的集合(Collection)collection = client.create_collection(name="docs")集合名必须全局唯一;重复创建同名集合会报错
create_collection() 参数:embedding_functioncreate_collection(name="...", embedding_function=fn)指定自定义或内置嵌入函数from chromadb.utils import embedding_functions
ef = embedding_functions.SentenceTransformerEmbeddingFunction(model_name="all-MiniLM-L6-v2")
collection = client.create_collection(name="docs", embedding_function=ef)
若不指定 embedding_function,则插入数据时必须手动提供 embeddings 参数
create_collection() 参数:metadatacreate_collection(name="...", metadata={"hnsw:space": "cosine"})配置 HNSW 索引的相似度度量方式collection = client.create_collection(name="docs", metadata={"hnsw:space": "l2"})支持 "cosine"(默认)、"l2""ip"(内积);一旦创建不可修改

2.3 插入与查询向量数据

方法名称语法用途代码示例注意事项
collection.add()add(ids, documents=None, embeddings=None, metadatas=None)向集合中添加文档、向量和元数据collection.add(
ids=["id1", "id2"],
documents=["Hello world", "Chroma is great"],
metadatas=[{"source": "user"}, {"source": "doc"}]
)
- ids 必须唯一且非空
- 若未设 embedding_function,则必须提供 embeddings
- documents 和 embeddings 维度需一致
collection.query()query(query_texts=None, query_embeddings=None, n_results=10, where=None, where_document=None)执行相似性搜索results = collection.query(
query_texts=["What is Chroma?"],
n_results=2
)
- 必须提供 query_texts 或 query_embeddings 之一
- 返回结果包含 ids, distances, metadatas, documents
query() 返回结构查询结果字段说明print(results["ids"]) # [['id2', 'id1']]
print(results["documents"]) # [['Chroma is great', 'Hello world']]
结果按相似度降序排列(距离越小越相似);distances 数值含义取决于 hnsw:space 配置
自动嵌入生成示例使用内置函数时无需传 embeddings简化插入流程collection.add(
ids=["1"],
documents=["Machine learning is fun"]
) # 自动调用 embedding_function
首次调用会下载模型(如 all-MiniLM-L6-v2),需联网;后续调用离线可用

注意事项补充:

  • 所有输入(ids, documents, metadatas, embeddings)必须是列表,且长度一致。
  • ids 建议使用字符串类型(如 UUID),避免数字 ID 被误解析。
  • 查询时若同时传 query_textsquery_embeddings,以 query_embeddings 为准。

第三章:Collection 管理

3.1 创建 Collection(含元数据与嵌入函数)

方法名称语法用途代码示例注意事项
create_collection()client.create_collection(name, metadata=None, embedding_function=None)创建新集合,可指定索引参数和嵌入函数collection = client.create_collection(
name="articles",
metadata={"hnsw:space": "cosine"},
embedding_function=ef
)
- name 必须唯一,长度 ≤ 64 字符,仅允许字母、数字、下划线、连字符
- 若已存在同名集合,抛出 ValueError
metadata 参数配置metadata={"hnsw:space": "cosine", "hnsw:M": 16, "hnsw:ef_construction": 100}配置 HNSW 索引的超参数metadata={"hnsw:space": "l2", "hnsw:M": 32}- hnsw:space:相似度度量("cosine""l2""ip"
- hnsw:M:每个节点连接数(默认 16)
- hnsw:ef_construction:建图时候选集大小(默认 100)
⚠️ 一旦创建不可修改
内置嵌入函数embedding_functions.SentenceTransformerEmbeddingFunction(model_name="...")使用 Sentence Transformers 模型自动嵌入from chromadb.utils import embedding_functions
ef = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="all-MiniLM-L6-v2"
)
- 首次使用会自动下载模型(约 80MB)
- 支持 Hugging Face 上任意兼容模型
自定义嵌入函数传入可调用对象(Callable)集成私有或第三方嵌入模型def my_embed(texts):
return [[0.1, 0.9] for _ in texts] # 示例
collection = client.create_collection("test", embedding_function=my_embed)
- 函数必须接受 List[str],返回 List[List[float]]
- 向量维度需一致且匹配模型输出

3.2 获取与列出 Collection

方法名称语法用途代码示例注意事项
get_collection()client.get_collection(name, embedding_function=None)获取已存在的集合实例coll = client.get_collection("articles")- 若集合不存在,抛出 ValueError
- 可重新指定 embedding_function(仅用于后续 add/query,不影响已有数据)
list_collections()client.list_collections()列出所有集合的简要信息collections = client.list_collections()
for c in collections:
print(c.name, c.metadata)
返回 List[CollectionMetadata],包含 name 和 metadata 字段
不包含数据内容,仅元信息
get_or_create_collection()client.get_or_create_collection(name, ...)若存在则获取,否则创建coll = client.get_or_create_collection("logs")避免重复创建错误;常用于初始化逻辑
若已存在,忽略 metadata 和 embedding_function 参数

3.3 修改与删除 Collection

方法名称语法用途代码示例注意事项
modify()collection.modify(name=new_name, metadata=new_metadata)修改集合名称或元数据collection.modify(name="new_articles")- 仅支持修改 name 和 metadata
- metadata 不能修改 hnsw:space 等索引参数(会报错)
- 修改后原变量仍有效,但建议重新获取
delete_collection()client.delete_collection(name)永久删除整个集合及其所有数据client.delete_collection("temp_data")⚠️ 不可逆操作!删除后无法恢复
若集合不存在,抛出 ValueError
清空集合内容(变通方法)通过 delete(ids=...) 删除所有 ID实现”清空”效果all_ids = collection.get()["ids"]
if all_ids:
collection.delete(ids=all_ids)
Chroma 无原生 clear() 方法
需先 get() 获取全部 ID 再批量删除

补充说明:

  • Collection 是 Chroma 中的顶层容器,类似传统数据库中的”表”。
  • 所有数据操作(add/query/update/delete)都必须通过 Collection 实例进行。
  • 修改集合名称后,旧名称不可再用,需使用新名称重新获取实例。

第四章:数据操作(CRUD)

4.1 添加文档与向量(add)

方法名称语法用途代码示例注意事项
collection.add()add(ids, embeddings=None, documents=None, metadatas=None)向集合中插入新数据项collection.add(
ids=["doc1", "doc2"],
documents=["AI is powerful", "Chroma stores vectors"],
metadatas=[{"type": "intro"}, {"type": "db"}]
)
- ids 必须为非空字符串列表,且全局唯一
- 若未配置 embedding_function,必须提供 embeddings
- 所有参数(除 ids)均可为 None,但至少需提供 documents 或 embeddings 之一
提供显式嵌入向量add(ids, embeddings=[[0.1,0.9], [0.8,0.2]], ...)手动传入预计算的向量collection.add(
ids=["v1"],
embeddings=[[0.5, -0.3, 0.7]],
documents=["Custom vector"]
)
- 向量维度必须一致(如均为 384 维)
- 维度必须与集合已有数据或嵌入函数输出一致,否则报错
批量插入优化单次调用插入多条(推荐 ≤ 10,000 条)提高写入效率ids = [f"id_{i}" for i in range(1000)]
docs = [f"Document {i}" for i in range(1000)]
collection.add(ids=ids, documents=docs)
- 避免在循环中逐条调用 add()
- 超大批次可能导致内存溢出,建议分批(如每批 5k)

4.2 查询相似内容(query)

方法名称语法用途代码示例注意事项
collection.query()query(query_texts=None, query_embeddings=None, n_results=10, where=None, where_document=None)基于语义相似性检索最相近的文档results = collection.query(
query_texts=["What can Chroma do?"],
n_results=3,
where={"type": "db"}
)
- 必须提供 query_texts 或 query_embeddings 之一
- 返回字典包含:ids, distances, metadatas, documents
- 结果按相似度排序(距离越小越相关)
使用嵌入向量查询query(query_embeddings=[[0.6, 0.4, ...]])用预计算向量进行检索emb = model.encode(["My query"])
results = collection.query(query_embeddings=emb.tolist())
向量维度必须与集合一致;适用于已在外部分词/嵌入的场景
元数据过滤where={"category": "tech", "year": {"$gte": 2023}}限制结果范围collection.query(
query_texts=["AI trends"],
where={"domain": "artificial_intelligence"}
)
支持 $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin 等操作符
不支持复杂嵌套逻辑(如 AND/OR 混合)
文档内容过滤where_document={"$contains": "vector"}根据原始文档文本过滤collection.query(
query_texts=["database"],
where_document={"$contains": "Chroma"}
)
仅支持 $contains 操作符(子串匹配)
大小写敏感,不支持正则

4.3 更新已有数据(update)

方法名称语法用途代码示例注意事项
collection.update()update(ids, embeddings=None, documents=None, metadatas=None)修改指定 ID 的字段值collection.update(
ids=["doc1"],
metadatas=[{"type": "updated_intro"}]
)
- 仅更新非 None 的字段
- 若提供 documents,会重新生成嵌入向量(若配置了 embedding_function)
- 不支持部分字段更新(如只改 metadata 中一个 key),需传入完整新值
更新文档触发重嵌入提供新 documents自动更新向量表示collection.update(
ids=["doc1"],
documents=["AI is transformative"]
)
⚠️ 嵌入会变化,影响后续查询结果
若手动提供 embeddings,则跳过自动嵌入
批量更新一次更新多个 ID提高效率collection.update(
ids=["id1", "id2"],
metadatas=[{"status": "active"}, {"status": "archived"}]
)
所有参数列表长度必须与 ids 一致
缺失字段保持原值不变

4.4 删除数据(delete)

方法名称语法用途代码示例注意事项
collection.delete()delete(ids=None, where=None, where_document=None)删除满足条件的数据项collection.delete(ids=["doc1", "doc2"])- 至少提供 ids、where、where_document 之一
- 多条件组合时为 AND 关系
按元数据删除delete(where={"status": "deprecated"})批量清理特定类型数据collection.delete(where={"source": "temp"})支持与 query() 相同的 where 语法
慎用无条件删除(如 where={} 会删全部)
按文档内容删除delete(where_document={"$contains": "test"})清理含特定关键词的文档collection.delete(where_document={"$contains": "DRAFT"})仅支持 $contains
删除后无法恢复
获取后再删除(安全模式)先 get() 确认再 delete()避免误删to_delete = collection.get(where={"flag": "delete_me"})["ids"]
if to_delete:
collection.delete(ids=to_delete)
推荐在生产环境中使用此模式
可打印 to_delete 进行人工确认

通用注意事项:

  • 所有 CRUD 操作均为同步阻塞,大数据量时可能耗时较长。
  • Chroma 不支持事务,操作不可回滚。
  • 删除或更新后,HNSW 索引不会立即重建,但查询结果会正确反映变更(通过内部标记机制)。

第五章:嵌入(Embedding)与自定义模型

5.1 使用内置嵌入函数(如 Sentence Transformers)

方法名称语法用途代码示例注意事项
SentenceTransformerEmbeddingFunctionembedding_functions.SentenceTransformerEmbeddingFunction(model_name="...")使用 Hugging Face 上的 Sentence Transformers 模型自动嵌入文本from chromadb.utils import embedding_functions
ef = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="all-MiniLM-L6-v2"
)
collection = client.create_collection("docs", embedding_function=ef)
- 首次调用会自动下载模型(约 80–500MB)
- 需联网;可提前下载至本地并指定路径
- 默认使用 CPU 推理
支持的常用模型"all-MiniLM-L6-v2", "multi-qa-MiniLM-L6-cos-v1", "paraphrase-multilingual-MiniLM-L12-v2"轻量级、多语言、问答优化等场景ef = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="paraphrase-multilingual-MiniLM-L12-v2"
)
- 模型维度需一致(如 L6-v2 为 384 维)
- 多语言模型适合非英文文本
- 可在 Hugging Face Sentence Transformers 查看完整列表
OpenAI 嵌入函数(实验性)embedding_functions.OpenAIEmbeddingFunction(api_key="...", model_name="text-embedding-ada-002")使用 OpenAI API 生成嵌入ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="sk-...",
model_name="text-embedding-3-small"
)
- 需安装 openai 包:pip install openai
- 产生 API 调用费用
- 需设置环境变量或显式传入 api_key

5.2 集成自定义嵌入模型

方法名称语法用途代码示例注意事项
自定义 Callable 函数定义接受 List[str] 返回 List[List[float]] 的函数集成私有模型、ONNX 模型、API 服务等def my_embed(texts: list[str]) -> list[list[float]]:
# 示例:调用本地 ONNX 模型
return [[0.1 * len(t)] * 384 for t in texts]

collection = client.create_collection("custom", embedding_function=my_embed)
- 必须严格匹配输入输出类型
- 向量维度必须固定(如 384、768)
- 函数需处理批量输入(非单条)
集成 transformers 管道使用 Hugging Face transformers 库使用 BERT、RoBERTa 等模型生成嵌入from transformers import AutoTokenizer, AutoModel
import torch

tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")

def bert_embed(texts):
inputs = tokenizer(texts, return_tensors="pt", padding=True, truncation=True)
with torch.no_grad():
outputs = model(**inputs)
embeddings = outputs.last_hidden_state.mean(dim=1).numpy()
return embeddings.tolist()

collection = client.create_collection("bert_docs", embedding_function=bert_embed)
- 需安装 transformers 和 torch
- 注意内存和 GPU 显存占用
- 建议添加 truncation=True 防止超长文本报错
封装为类(推荐)实现 __call__ 方法的类更灵活地管理模型状态(如加载、缓存)class MyEmbedder:
def __init__(self, model_path):
self.model = load_my_model(model_path)
def __call__(self, texts):
return self.model.encode(texts)

embedder = MyEmbedder("my_model.onnx")
collection = client.create_collection("onnx_docs", embedding_function=embedder)
- 类实例可携带模型、tokenizer 等状态
- 适用于复杂预处理/后处理逻辑

5.3 手动提供嵌入向量

方法名称语法用途代码示例注意事项
collection.add(embeddings=...)add(ids, embeddings=[[...], [...]], documents=None, metadatas=None)插入时直接传入预计算的向量collection.add(
ids=["m1"],
embeddings=[[0.2, -0.5, 0.9]],
documents=["Manual vector example"]
)
- 向量必须为 List[List[float]]
- 维度必须与集合中其他数据一致(若已有数据)
- 若集合无数据,则以此维度为准
collection.update(embeddings=...)update(ids, embeddings=[[...]])更新现有记录的向量表示collection.update(
ids=["m1"],
embeddings=[[0.3, -0.4, 0.8]]
)
- 不触发自动嵌入(即使配置了 embedding_function)
- 可用于修正错误嵌入或迁移向量
查询时手动提供查询向量query(query_embeddings=[[...]])使用外部系统生成的查询向量query_vec = external_model.encode("What is AI?")
results = collection.query(query_embeddings=[query_vec])
- 适用于跨系统语义对齐场景
- 查询向量维度必须与集合嵌入维度一致,否则报错
维度一致性校验确保所有向量维度统一# 首次插入决定维度
collection.add(ids=["init"], embeddings=[[0]*384])
# 后续必须为 384 维
⚠️ Chroma 不支持混合维度
若尝试插入不同维度向量,将抛出 InvalidDimensionException

通用建议:

  • 开发阶段推荐使用内置 SentenceTransformerEmbeddingFunction,快速验证流程。
  • 生产环境中若需高性能或私有化部署,建议使用 ONNX 或 TensorRT 优化的自定义模型。
  • 手动提供向量适用于已有嵌入流水线(如 Spark + FAISS 预计算)的迁移场景。

第六章:元数据过滤与高级查询

6.1 使用 where 过滤元数据

操作名称语法用途代码示例注意事项
等值过滤where={"key": "value"}筛选元数据中某字段等于指定值的记录collection.query(
query_texts=["AI"],
where={"category": "technology"}
)
- 仅支持顶层字段(不支持嵌套 JSON)
- 值类型需匹配(字符串、数字、布尔)
数值范围过滤where={"year": {"$gt": 2020}}筛选数值型字段满足不等式的记录collection.query(
query_texts=["models"],
where={"year": {"$gte": 2022, "$lt": 2025}}
)
支持操作符:
$gt(大于)、$gte(大于等于)、
$lt(小于)、$lte(小于等于)
多值匹配where={"tag": {"$in": ["nlp", "cv"]}}字段值在给定列表中的记录collection.query(
query_texts=["deep learning"],
where={"domain": {"$in": ["vision", "speech"]}}
)
$in$nin(不在)仅适用于数组或标量
若字段为字符串,$in 要求完全匹配
不等于过滤where={"status": {"$ne": "archived"}}排除特定值的记录collection.query(
query_texts=["active projects"],
where={"status": {"$ne": "deprecated"}}
)
$ne 可用于任何类型字段
布尔值过滤where={"is_public": True}筛选布尔字段collection.query(
query_texts=["open research"],
where={"is_public": True}
)
Python 中使用 True/False,非字符串 “true”

限制说明:

  • 不支持正则表达式、模糊匹配、全文搜索等复杂文本操作。
  • 所有 where 条件作用于元数据(metadatas),而非文档内容或向量本身。

6.2 使用 where_document 过滤文档内容

操作名称语法用途代码示例注意事项
子串包含过滤where_document={"$contains": "keyword"}筛选原始文档中包含指定子串的记录collection.query(
query_texts=["vector DB"],
where_document={"$contains": "Chroma"}
)
- 仅支持 $contains 操作符
- 区分大小写(“chroma” ≠ “Chroma”)
- 不支持通配符或正则
与 where 联用同时使用 where 和 where_document多维度联合过滤collection.query(
query_texts=["database"],
where={"type": "tool"},
where_document={"$contains": "open source"}
)
两个条件为 AND 关系
即:元数据匹配 且 文档包含关键词
性能影响文档过滤需扫描原始文本- 大集合中频繁使用 where_document 可能变慢Chroma 对 documents 未建索引
建议仅在小规模数据或必要时使用

重要提醒:

  • where_document 仅作用于插入时提供的 documents 字段。
  • 若未提供 documents(仅存向量和元数据),此过滤无效。

6.3 多条件组合查询

操作名称语法用途代码示例注意事项
单层 AND 组合where={"field1": "A", "field2": {"$gt": 10}}多个元数据条件同时满足collection.query(
query_texts=["recent AI paper"],
where={
"category": "AI",
"year": {"$gte": 2023},
"peer_reviewed": True
}
)
所有键值对自动按 AND 逻辑组合
不支持显式的 $and 语法
不支持 OR 逻辑无法直接表达”或”关系- 不支持 $or$and 显式逻辑操作符Chroma 当前不支持 $or
变通方案:分别查询后合并结果(需去重)
嵌套条件限制元数据必须为扁平结构- 无效:metadatas=[{"author": {"name": "Alice"}}]
- 有效:metadatas=[{"author_name": "Alice"}]
不支持嵌套对象(如 {"a": {"b": 1}}
建议将嵌套结构拍平为 a_b 形式
查询 + 过滤完整示例综合使用所有参数构建精准语义检索results = collection.query(
query_texts=["How to use vector DB?"],
n_results=5,
where={
"language": "en",
"relevance_score": {"$gte": 0.8}
},
where_document={"$contains": "example"}
)
返回结果同时满足:
1. 语义最相似
2. 英文文档
3. 相关性评分 ≥ 0.8
4. 文档含 “example”

最佳实践建议:

  • 将高频过滤字段放入 metadatas(可高效过滤),而非依赖 where_document。
  • 避免在 metadatas 中存储大文本;应仅存分类、标签、时间戳等结构化信息。
  • 若业务强依赖 $or 逻辑,可考虑在应用层合并多次查询结果,或评估 Milvus/Weaviate 等支持更复杂过滤的数据库。

第七章:持久化与客户端模式

7.1 内存模式 vs 持久化模式

概念名称说明注意事项
内存模式(In-Memory)使用 chromadb.Client() 创建的默认客户端,所有数据存储在 Python 进程内存中- 程序退出后数据完全丢失
- 适合快速原型开发、单元测试
- 无法跨进程共享数据
持久化模式(Persistent)使用 chromadb.PersistentClient(path=...) 将数据写入本地磁盘(SQLite + Parquet)- 数据在程序重启后自动恢复
- 默认存储路径为 ./chroma.sqlite3./chroma_data/
- 单机单写,不支持并发写入
存储结构持久化模式使用 SQLite 存元数据,Parquet 文件存向量和文档- 向量数据以列式格式高效存储
- 可直接查看 chroma_data/ 目录下的 Parquet 文件(需工具解析)
性能对比内存模式读写最快;持久化模式首次加载稍慢(需读磁盘)- 持久化模式插入速度略低于内存模式
- 查询性能几乎一致(索引仍加载到内存)
适用阶段内存:开发/调试;持久化:本地演示、小型应用- 生产环境若需高可用,应使用 HTTP Client + Chroma Server(见 7.3)

7.2 使用 PersistentClient 实现本地存储

方法名称语法用途代码示例注意事项
PersistentClient 初始化client = chromadb.PersistentClient(path="./my_db")创建指向指定目录的持久化客户端import chromadb
client = chromadb.PersistentClient(path="/data/chroma_db")
- path 必须为绝对路径或相对于当前工作目录
- 首次运行会自动创建目录和文件
创建集合(持久化)client.create_collection("my_coll")在持久化存储中创建集合coll = client.create_collection("articles")
coll.add(ids=["1"], documents=["Persisted doc"])
- 集合元数据和数据均写入磁盘
- 重启后通过相同 path 可恢复
重启后恢复数据重新初始化 PersistentClient 并 get_collection()验证数据持久性# 重启脚本后
client = chromadb.PersistentClient(path="./my_db")
coll = client.get_collection("articles")
print(coll.peek())
- 无需重新插入数据
- 集合名称、嵌入函数、元数据均保留
多进程限制同一持久化目录不允许多个写入进程- SQLite 不支持并发写
- 两个 Python 脚本同时写入 ./my_db 危险
可能导致数据库锁或损坏
建议单写多读,或使用服务模式

目录结构示例(持久化后):

./my_db/
├── chroma.sqlite3          # 元数据(集合名、ID 映射等)
└── chroma_data/
    └── <collection_id>/
        ├── embeddings.parquet
        ├── documents.parquet
        ├── metadatas.parquet
        └── ...

7.3 使用 HTTP Client 连接远程服务

方法名称语法用途代码示例注意事项
启动 Chroma Server命令行:chroma run --host 0.0.0.0 --port 8000启动独立的 Chroma 服务进程# 安装 server 组件
pip install chromadb[server]
# 启动服务
chroma run --host 0.0.0.0 --port 8000
- 需额外安装 [server] 依赖
- 默认使用内存存储(可配置持久化)
- 服务端不自动保存数据(除非启用持久化)
HttpClient 初始化client = chromadb.HttpClient(host="localhost", port=8000)从 Python 客户端连接远程 Chroma 服务import chromadb
client = chromadb.HttpClient(host="192.168.1.10", port=8000)
- 客户端不加载模型,仅转发请求
- 所有嵌入计算在服务端完成(若配置了 embedding_function)
创建远程集合client.create_collection(...)操作由服务端执行coll = client.create_collection("remote_docs")
coll.add(ids=["r1"], documents=["From client"])
- 客户端代码与本地模式完全一致
- 网络延迟会影响性能
服务端持久化配置启动时指定 --persist-directory使远程服务具备持久能力chroma run \
--host 0.0.0.0 \
--port 8000 \
--persist-directory /mnt/chroma_data
- 重启服务后数据可恢复
- 多客户端可共享同一服务端数据
安全与生产部署当前无认证/加密机制⚠️ 不要暴露 8000 端口到公网- 官方暂未提供 TLS、API Key 等安全功能
- 建议配合 Nginx/API 网关做鉴权
- 生产环境需自行封装或等待企业版

典型架构:

[Python App] --(HTTP)--> [Chroma Server (with persistent storage)]

[LangChain / FastAPI / Streamlit]

第八章:性能调优与最佳实践

8.1 批量插入优化

操作名称操作细节注意事项
单次批量插入(推荐)将多条数据一次性传入 add(),而非循环逐条插入- 单次建议 ≤ 10,000 条(视内存而定)
- 过大批次可能导致 OOM(Out of Memory)
- 示例:ids = [f"id_{i}" for i in range(5000)]
docs = [f"Document {i}" for i in range(5000)]
collection.add(ids=ids, documents=docs)
分批插入策略对超大数据集(>10万条)分块处理batch_size = 2000
for i in range(0, len(all_docs), batch_size):
batch_ids = all_ids[i:i+batch_size]
batch_docs = all_docs[i:i+batch_size]
collection.add(ids=batch_ids, documents=batch_docs)
预分配 ID 与避免重复使用 UUID 或确定性 ID 防止冲突import uuid
ids = [str(uuid.uuid4()) for _ in docs]
禁用自动嵌入(如已预计算)插入时直接提供 embeddings,跳过模型调用collection.add(ids=ids, embeddings=precomputed_embs, documents=docs)

8.2 索引类型与 HNSW 参数配置

参数名称说明推荐值注意事项
hnsw:space相似度度量方式"cosine"(文本常用)、"l2"(欧氏距离)、"ip"(内积)- 必须在 create_collection() 时指定
- 一旦创建不可更改
- 与嵌入模型训练目标一致(如 Sentence Transformers 多用 cosine)
hnsw:MHNSW 图中每个节点的连接数默认 16;高精度场景用 32~64- 值越大,索引越大,查询越准,构建越慢
- 内存占用 ≈ M × 向量数 × 向量维度 × 4 字节
hnsw:ef_construction构建索引时的候选集大小默认 100;高召回用 200~500- 影响索引构建质量和速度
- 对查询性能无直接影响
hnsw:ef(查询时)查询时的候选集大小(动态参数)通过 query() 的 include 无法设置;需修改底层(暂不开放)⚠️ Chroma 当前不支持运行时调整 ef
查询精度由索引构建质量决定
索引重建限制不支持- Chroma 无法重建或重配已有集合的 HNSW 索引
- 若需调整参数,必须创建新集合并迁移数据

HNSW 参数影响总结:

目标调整方向
更高召回率↑ M,↑ ef_construction
更快插入速度↓ M,↓ ef_construction
更低内存占用↓ M
更快查询速度↑ M(但收益递减),需权衡

8.3 内存与磁盘使用建议

场景建议措施注意事项
控制内存峰值使用持久化模式 + 分批插入- 内存模式下,所有向量常驻 RAM
- 100 万条 384 维 float32 向量 ≈ 1.5 GB 内存
- 持久化模式可显著降低常驻内存
磁盘空间管理定期清理无用集合client.delete_collection("temp_data")
嵌入模型缓存预下载模型至固定路径from sentence_transformers import SentenceTransformer
SentenceTransformer("all-MiniLM-L6-v2", cache_folder="/models")
避免冗余文档存储仅存必要字段到 documents- 若原始文本已存于其他系统(如 S3、PostgreSQL),documents 可存摘要或空字符串
- 减少 Parquet 文件体积
监控资源使用使用系统工具(htop, du -sh)- 持久化目录增长 = 数据量增长
- 内存泄漏通常源于客户端未释放(罕见)

容量估算参考(384 维 float32 向量):

数据量向量内存磁盘占用(持久化)
10,000 条~15 MB~20 MB
100,000 条~150 MB~200 MB
1,000,000 条~1.5 GB~2 GB

重要提醒:

  • Chroma 不是为十亿级向量设计,单机建议上限为 500 万~1000 万条。
  • 超出此规模应考虑 Milvus、Qdrant 或 Pinecone 等分布式向量数据库。

第九章:应用场景与集成示例

9.1 RAG(检索增强生成)集成

集成步骤操作细节注意事项
构建知识库将文档分块后存入 Chroma 集合from langchain.text_splitter import RecursiveCharacterTextSplitter
texts = text_splitter.split_documents(raw_docs)
collection.add(
ids=[f"doc_{i}" for i in range(len(texts))],
documents=[t.page_content for t in texts],
metadatas=[t.metadata for t in texts]
)
检索相关上下文用户提问 → Chroma 查询 → 返回 top-k 文档results = collection.query(
query_texts=["How does Chroma work?"],
n_results=3
)
context = "\n".join(results["documents"][0])
注入 LLM Prompt将检索结果拼接到提示词中prompt = f"""Use the following context to answer the question:
{context}

Question: How does Chroma work?"""
response = llm(prompt)
端到端流程封装使用 LangChain 的 RetrievalQA 链from langchain.chains import RetrievalQA
qa = RetrievalQA.from_chain_type(
llm=llm,
retriever=chroma.as_retriever(),
chain_type="stuff"
)
qa.run("What is Chroma?")

RAG 性能关键点:

  • 嵌入模型应与 LLM 语义空间对齐(如都使用英文模型)
  • 避免在 documents 中存储冗余或噪声文本

9.2 与 LangChain / LlamaIndex 集成

LangChain 集成

方法名称语法用途代码示例注意事项
Chroma.from_documents()Chroma.from_documents(docs, embedding, persist_directory=...)从 LangChain Document 列表创建 Chroma 集合from langchain_community.vectorstores import Chroma
db = Chroma.from_documents(
documents=texts,
embedding=embedding_func,
persist_directory="./rag_db"
)
- 自动处理 ID 生成、分块嵌入
- 支持持久化路径
as_retriever()retriever = db.as_retriever(search_kwargs={"k": 4})获取检索器用于 RAG 链retriever = db.as_retriever(
search_type="similarity",
search_kwargs={"k": 3, "filter": {"source": "manual"}}
)
- search_kwargs 支持 k, filter(即 where)
- 不支持 where_document
直接查询db.similarity_search("query", k=2)快速语义搜索docs = db.similarity_search("vector DB", k=2)返回 LangChain Document 对象列表
包含 page_content 和 metadata

LlamaIndex 集成

方法名称语法用途代码示例注意事项
ChromaVectorStorevector_store = ChromaVectorStore(chroma_collection=collection)将 Chroma 集合作为 LlamaIndex 后端from llama_index.vector_stores.chroma import ChromaVectorStore
vector_store = ChromaVectorStore(collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex(nodes, storage_context=storage_context)
- 需先通过原生 Chroma 创建 collection
- 支持增量索引更新
查询引擎query_engine = index.as_query_engine()构建问答接口response = query_engine.query("Explain Chroma")
print(response.response)
- 自动完成检索 + LLM 生成
- 可配置响应模式(如 streaming)

集成选择建议:

  • LangChain:适合快速搭建 RAG pipeline,生态丰富
  • LlamaIndex:更适合复杂索引结构(如层次化、图索引)和高级查询策略

9.3 构建语义搜索应用

应用组件实现方式代码示例注意事项
Web API 层使用 FastAPI 提供 REST 接口from fastapi import FastAPI
app = FastAPI()

@app.post("/search")
def search(q: str):
results = collection.query(query_texts=[q], n_results=5)
return {"results": results["documents"][0]}
- 启动命令:uvicorn main:app --reload
- 可添加 CORS、限流等中间件
前端调用JavaScript fetch 调用后端const res = await fetch("/search", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({q: "What is vector search?"})
});
const data = await res.json();
- 前端不直接连 Chroma(无 JS 官方 SDK)
- 所有逻辑由后端封装
元数据展示返回结果包含来源、时间等return {
"matches": [
{
"text": doc,
"source": meta["source"],
"score": 1 - dist # 转为相似度
}
for doc, meta, dist in zip(docs, metas, dists)
]
}
- distances 是 HNSW 距离,可转为 0~1 相似度
- 建议过滤低分结果(如 score < 0.3)
本地演示应用Streamlit 快速构建 UIimport streamlit as st
query = st.text_input("Ask anything")
if query:
res = collection.query(query_texts=[query], n_results=3)
for doc in res["documents"][0]:
st.write(doc)
- 适合内部 demo 或 MVP
- 单文件即可运行:streamlit run app.py

部署建议:

  • 开发阶段:内存模式 + Streamlit
  • 生产阶段:PersistentClient 或 HTTP Client + FastAPI + Docker
  • 高并发场景:前端加缓存(如 Redis 缓存热门查询结果)