在 RAG 系统中,向量库负责存储和检索文档片段的嵌入向量,是连接用户问题与知识库内容的桥梁。对于个人开发者或小型项目,使用轻量级本地向量库可以避开云端服务的复杂配置和网络延迟,在几分钟内即可跑通完整的“入库-检索”流程。本节以最常用的开源向量库 Chroma 为例,演示从零搭建到可用的完整步骤。
1. 环境准备
确保已安装 Python 3.8+,然后使用 pip 安装 Chroma 及其依赖的嵌入模型库:
pip install chromadb sentence-transformers
sentence-transformers 提供了免费的本地嵌入模型,无需调用外部 API,完全离线运行。
2. 启动向量库并创建集合
Chroma 支持两种模式:内存模式(数据仅存于当前进程,适合实验)和持久化模式(数据写入本地磁盘,重启后不丢失)。实际使用中推荐持久化模式。
import chromadb
from chromadb.config import Settings
# 创建客户端,指定数据存储路径(当前目录下的 chroma_data 文件夹)
client = chromadb.PersistentClient(path="./chroma_data")
# 创建或获取一个集合(collection),类似关系数据库的“表”
collection = client.get_or_create_collection(name="my_docs")
集合是文档片段的容器,一个项目中可以按知识域建立多个集合,例如 hr_policies、product_manuals,便于管理和隔离。
3. 定义嵌入函数
Chroma 默认使用内置的 all-MiniLM-L6-v2 模型,但为更灵活地控制嵌入维度与性能,通常显式传入自定义的嵌入函数。这里使用 sentence-transformers 的一个轻量模型:
from chromadb.utils import embedding_functions
# 使用本地多语言模型(支持中英文)
embedding_func = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="paraphrase-multilingual-MiniLM-L12-v2"
)
若只需处理英文,可将模型名换为 all-MiniLM-L6-v2,速度更快。上述多语言模型对中文检索也有良好效果。
4. 加载文档并入库
实际文档可能来自 TXT、PDF 或数据库,这里以几个示例段落模拟。核心步骤是将文本切分为适当大小的片段(chunk),并生成向量一次性写入。
documents = [
"RAG 是一种将检索与生成相结合的技术框架。",
"员工每年享有 15 天带薪年假,入职满一年后生效。",
"出差住宿标准:一线城市 500 元/晚,其他城市 350 元/晚。",
"项目申报截止日期为 2025 年 12 月 31 日,逾期不再受理。"
]
# 为每个文档生成唯一 ID
ids = [f"doc_{i}" for i in range(len(documents))]
# 添加文档到集合
collection.add(
documents=documents,
ids=ids,
embedding_function=embedding_func
)
print(f"已入库 {collection.count()} 条文档片段")
实际项目中,文档在入库前通常经过清洗(去除空行、特殊字符)并按语义分块,以保证检索精度。但在此快速启动阶段,简易分块已足够验证流程。
5. 执行检索
用户提问后,将问题转换为向量,在集合中查找最相似的文档片段。
query = "年假有多少天?"
results = collection.query(
query_texts=[query],
n_results=2, # 返回最相似的 2 个结果
embedding_function=embedding_func
)
# 解析并展示结果
for i, doc in enumerate(results['documents'][0]):
score = results['distances'][0][i]
print(f"排名 {i+1}(距离 {score:.4f}): {doc}")
输出示例:
排名 1(距离 0.3456): 员工每年享有 15 天带薪年假,入职满一年后生效。
排名 2(距离 0.7890): 出差住宿标准:一线城市 500 元/晚,其他城市 350 元/晚。
距离值越小代表语义越相关(此处使用默认的余弦距离)。第一个结果完全匹配问题意图,可直接送入大模型生成最终答案。
6. 持久化与后续使用
数据已自动写入启动时指定的 ./chroma_data 目录。下次启动时,只需重新创建客户端并获取同名集合,所有文档即可直接使用,无需再次入库。
# 重启后恢复使用
client = chromadb.PersistentClient(path="./chroma_data")
collection = client.get_collection(name="my_docs", embedding_function=embedding_func)
# 此时可以直接进行查询
7. 常见问题与调优提示
- 查询速度慢:检查嵌入模型是否过大,英文场景可切换至轻量模型;文档量超过 10 万条时可考虑启用索引(Chroma 默认使用 HNSW,通常已足够快)。
- 检索相关性差:尝试调整 chunk 大小,一般 200~500 字符较均衡;也可换用更强的嵌入模型(如
intfloat/multilingual-e5-base)。 - 内存占用高:嵌入维度与模型大小直接相关,按需选择;若只需简单中文匹配,可考虑使用
shibing624/text2vec-base-chinese。 - 生产环境部署:Chroma 支持客户端-服务器模式,你可以将向量库单独部署为一台服务,多应用共享。
通过上述步骤,你可以在五分钟内拥有一个完全本地化、可投入测试的向量检索后端。这一基础设施是后续搭建完整 RAG 问答流程的基础,接下来只需将检索到的片段填入提示词并调用大模型,即可得到一个具备私有知识能力的智能问答应用。