1. 什么是向量数据库?
向量数据库是一种专门为存储、索引和检索高维向量数据而设计的数据库。与传统的关系型数据库(存储结构化数据)或文档数据库不同,向量数据库的核心能力是处理由非结构化数据(如文本、图像、音频、视频)通过机器学习模型转换而成的“向量嵌入”。
简单来说,它就像一个为“语义”而非“关键词”设计的搜索引擎。当你搜索“如何养猫”时,它不仅能找到包含“养猫”字样的文章,还能找到关于“猫咪饲养指南”、“宠物猫护理”等内容,因为它们背后的向量在数学上是相似的。
2. Chroma 的核心特性
Chroma 是一个开源的、嵌入原生的向量数据库,以其轻量、易用和开发者友好而著称。以下是其主要特性:
- 轻量且易于上手:几行 Python 代码即可启动和运行,无需复杂的配置。
- 内存与持久化模式:支持纯内存运行(
chromadb.Client())和持久化存储(chromadb.PersistentClient()),满足从原型验证到生产部署的不同需求。 - 多种部署方式:
- Python 客户端:直接在 Python 脚本中嵌入使用。
- Docker 容器:通过 HTTP 客户端(
chromadb.HttpClient())连接,便于微服务架构集成。 - Chroma Cloud:官方托管服务,无需管理基础设施。
- 灵活的嵌入函数:默认使用
all-MiniLM-L6-v2模型,同时支持集成 OpenAI、Cohere、Hugging Face 等多种第三方嵌入模型。 - 强大的查询能力:支持基于向量相似性的语义搜索,并可通过元数据(
where)和文档内容(where_document)进行过滤,实现精准检索。 - 与 AI 开发生态无缝集成:是 LangChain 和 LlamaIndex 等主流 AI 应用框架的原生首选向量存储后端。
3. 核心概念与工作流程
理解 Chroma 的几个核心对象是使用它的关键:
- 客户端 (Client):与数据库交互的入口。根据部署方式选择
Client、PersistentClient或HttpClient。 - 集合 (Collection):类似于传统数据库中的“表”。一个集合包含一组相关的文档、它们的向量嵌入以及可选的元数据。它是进行增删改查操作的主要单元。
- 文档 (Document):你想要存储和检索的原始文本(或其它非结构化数据)。
- 嵌入 (Embedding):文档通过嵌入模型转换成的固定长度的数值向量(一列数字)。Chroma 负责存储这些向量并为其建立高效的索引。
- 元数据 (Metadata):与每个文档关联的键值对信息(如来源、作者、类别、日期等),用于辅助过滤和检索。
- ID:为每个文档分配的唯一标识符。
典型工作流程:
4. 快速入门:Python 代码示例
以下是一个完整的从创建集合到查询的示例。
import chromadb
from chromadb.config import Settings
# 1. 创建客户端(持久化模式,数据保存在 ./chroma_db 目录)
client = chromadb.PersistentClient(path="./chroma_db")
# 2. 创建或获取一个集合
collection = client.get_or_create_collection(name="my_knowledge_base")
# 3. 准备数据
documents = [
"Chroma 是一个开源的向量数据库。",
"它非常适合用于构建 AI 应用,如聊天机器人和语义搜索。",
"你可以用 Python 轻松地与 Chroma 交互。"
]
metadatas = [
{"source": "introduction", "type": "definition"},
{"source": "introduction", "type": "use_case"},
{"source": "introduction", "type": "tutorial"}
]
ids = ["doc1", "doc2", "doc3"]
# 4. 向集合添加数据(Chroma 会自动调用默认模型生成向量)
collection.add(
documents=documents,
metadatas=metadatas,
ids=ids
)
# 5. 进行相似性查询
results = collection.query(
query_texts=["如何用 Python 使用向量数据库?"], # 查询文本
n_results=2 # 返回最相似的2条
)
print("查询结果:")
for i, doc in enumerate(results['documents'][0]):
print(f"{i+1}. {doc}")
print(f" ID: {results['ids'][0][i]}, 元数据: {results['metadatas'][0][i]}")
print(f" 距离: {results['distances'][0][i]:.4f}")
print()
5. 高级功能详解
5.1 使用自定义嵌入模型
你可以轻松集成 OpenAI 等付费模型或 Hugging Face 上的开源模型。
from chromadb.utils import embedding_functions
# 使用 OpenAI 的嵌入模型
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="YOUR_OPENAI_API_KEY",
model_name="text-embedding-3-small"
)
# 创建集合时指定嵌入函数
collection = client.create_collection(
name="openai_collection",
embedding_function=openai_ef # 指定自定义嵌入函数
)
# 后续的 add 和 query 操作都会自动使用此模型
5.2 条件过滤查询
这是 Chroma 的杀手锏之一,让你能结合语义搜索和属性过滤。
# 假设我们有一个产品描述的集合
# ...
# 查询:“寻找一款适合游戏的笔记本电脑”,但只想要品牌是“BrandA”且价格低于1000的产品
results = collection.query(
query_texts=["适合游戏的笔记本电脑"],
n_results=5,
where={
"$and": [
{"brand": {"$eq": "BrandA"}},
{"price": {"$lt": 1000}}
]
},
# 还可以在文档内容中过滤
# where_document={"$contains": "显卡"}
)
print(results)
常用过滤运算符:
$eq(等于),$ne(不等于)$gt(大于),$gte(大于等于)$lt(小于),$lte(小于等于)$in(在列表中),$nin(不在列表中)$contains(文档内容包含,仅用于where_document)
5.3 更新与删除
# 更新文档 (ID 为 doc2 的文档)
collection.update(
ids=["doc2"],
documents=["更新后的文档内容:Chroma 是构建 AI 应用的强大工具。"],
metadatas=[{"source": "updated", "type": "use_case"}]
)
# 删除文档
collection.delete(ids=["doc1"])
# 清空或删除整个集合
client.delete_collection(name="my_knowledge_base")
5.4 Docker 部署与远程连接
对于生产环境,通常将 Chroma 部署为独立服务。
# 拉取并运行 Chroma 容器
docker pull chromadb/chroma
docker run -p 8000:8000 chromadb/chroma
然后在 Python 客户端中连接:
import chromadb
client = chromadb.HttpClient(
host='localhost',
port=8000,
settings=chromadb.Settings(
chroma_client_auth_provider="chromadb.auth.token_authn.TokenAuthClientProvider",
chroma_client_auth_credentials="your-token-here" # 如果设置了认证
)
)
# 后续操作与本地客户端完全一致
collection = client.get_or_create_collection("remote_collection")
6. 在 LangChain 中使用 Chroma
Chroma 与 LangChain 集成得天衣无缝,是构建 RAG(检索增强生成)应用的标准组件。
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader
# 1. 加载并分割文档
loader = TextLoader("./state_of_the_union.txt")
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
texts = text_splitter.split_documents(documents)
# 2. 使用 OpenAI 嵌入函数,并存入 Chroma
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(
documents=texts,
embedding=embeddings,
persist_directory="./chroma_langchain_db"
)
# 3. 将向量库转换为检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 4. 在链中使用
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4")
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever
)
answer = qa_chain.invoke({"query": "总统在国情咨文中提到了哪些关键议题?"})
print(answer["result"])
7. 总结与选型建议
何时选择 Chroma?
- 快速原型验证:你想用最少的时间和代码启动一个向量搜索功能。
- 轻量级应用:数据量在百万级以下,且希望减少运维复杂度。
- AI 应用开发:你正在使用 LangChain/LlamaIndex,需要无缝集成的向量存储。
- 强调开发者体验:你需要清晰的 API、详细的文档和活跃的社区。
与其他向量数据库对比:
- Pinecone / Weaviate (Cloud):更适合大规模、企业级生产环境,提供全托管服务,但通常有成本。
- Qdrant / Milvus:专注于极致性能和可扩展性,适合超大规模向量数据集,但部署和调优相对复杂。
- PGVector (PostgreSQL 扩展):如果你的团队和技术栈重度依赖 PostgreSQL,并且向量搜索是附加需求,PGVector 是一个很好的选择。
核心优势总结:Chroma 在易用性、开发速度和与AI 生态的集成度上做到了极佳的平衡,是大多数 AI 应用项目起步阶段的理想选择。
下一步
尝试修改示例代码,将其接入你自己的知识库或文档集,构建一个简单的问答机器人。探索 Chroma 的 get 方法、元数据过滤的更多组合,以及如何优化检索结果的相关性。
5605



被折叠的 条评论
为什么被折叠?



