语义搜索实战:用 ChromaDB 构建向量检索系统
语义搜索实战:用 ChromaDB 构建向量检索系统
搜索这件事,关键词匹配能做,但做不好。你搜「高效训练」,传统搜索只会找包含这四个字的文档,语义搜索却能找到讨论「加速模型收敛」的段落。这就是向量检索的价值。
索引:把文档变成向量
语义搜索的前置步骤是索引,分四步走:读文档、切片、向量化、存进向量库。
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# 读 PDF
loader = PyPDFLoader("data/paper.pdf")
documents = loader.load()
# 切片
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, chunk_overlap=200
)
all_splits = text_splitter.split_documents(documents)
# 向量化并存储
embedding_model = OpenAIEmbeddings(model="text-embedding-3-small")
vector_store = Chroma(
collection_name="demo",
embedding_function=embedding_model,
persist_directory="./chroma_db",
)
vector_store.add_documents(all_splits)
chunk_size=1000 是每个文本块的字符上限,chunk_overlap=200 让相邻块有重叠,避免语义在切割处断裂。
查询:多种检索方式
存好之后,查询就很直观了:
# 基本相似度搜索
results = vector_store.similarity_search("如何实现高效推理?")
# 带分数的搜索
results = vector_store.similarity_search_with_score(
"如何实现高效推理?", k=3
)
for doc, score in results:
print(f"分数: {score}, 内容: {doc.page_content[:100]}")
你也可以把查询封装成 LangChain 的 chain,方便后续和 Agent 串联:
from langchain_core.runnables import chain
@chain
def retriever(query: str):
return vector_store.similarity_search(query, k=1)
result = retriever.invoke("高效推理的方法")
评分方式的选择
ChromaDB 支持多种距离计算方式:L2(欧氏距离)、余弦相似度、内积。默认用 L2。
vector_store = Chroma(
collection_name="cosine_demo",
embedding_function=embedding_model,
collection_metadata={"hnsw:space": "cosine"},
)
不同场景适合不同度量。文本语义搜索一般用余弦相似度效果最好,因为它只关注方向不关注长度。L2 对向量的绝对大小敏感,内积则介于两者之间。
ChromaDB 的管理
实际开发中你会需要查看和清理向量库:
import chromadb
client = chromadb.PersistentClient(path="./chroma_db")
collections = client.list_collections()
for col in collections:
print(f"{col.name}: {col.count()} 条记录")
小结
语义搜索的核心流程就是:文档切片、向量化、存储、查询。ChromaDB 轻量好用,本地开发首选。理解了这套流程,后面做 RAG 就有了基础。