纲要
- 向量数据库基础
- 在 RAG 系统中的核心位置
- 与传统关系型数据库的本质区别
- LangChain 向量数据库接口
- 统一方法:
add_documents、delete、similarity_search - 常用向量数据库概览:Chroma、FAISS、Pinecone、Milvus 等
- 统一方法:
- 基本操作实战
- 文档添加(支持自定义 ID)
- 文档删除(按 ID)
- 文本相似性搜索与向量搜索
- 高级检索技巧
- 最大边际相关性(MMR)搜索
- 混合搜索(关键词 + 向量)
- 完整可运行代码:使用
FakeEmbeddings与内存向量库模拟增删查与 MMR
引言
在 RAG(检索增强生成)系统中,经过加载、切片和向量化的文档最终需要一个高效的存储和检索容器------这就是向量数据库。它不仅仅是一个存放向量的仓库,更承担着语义搜索的核心任务:根据查询向量快速找到最相似的文档片段。LangChain 通过统一的接口封装了各类向量数据库,让开发者可以像操作普通数据一样进行增删查,同时提供了 MMR、混合搜索等高级功能。本文将通过可运行的代码,手把手带你掌握向量数据库的关键操作。
向量数据库基础
向量数据库与传统的关系型数据库(如 MySQL)有着本质不同:
| 维度 | 关系型数据库 | 向量数据库 |
|---|---|---|
| 存储内容 | 结构化数据(表格、字段) | 高维向量数组(浮点数序列) |
| 查询方式 | 精确匹配(SQL where、join) | 相似度搜索(余弦距离、欧氏距离) |
| 典型场景 | 交易处理、用户管理 | 语义检索、图像搜索、推荐系统 |
| 数据模式 | 固定 Schema | 灵活,无需预定义结构 |
在 RAG 系统中,向量数据库负责存储所有外部知识片段的向量表示,当用户查询到来时,同样经过嵌入模型转为向量,然后在库中通过相似度算法检索出最相关的 Top‑K 个文档片段。
#mermaid-svg-FOb9r9vKTlMXroJv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FOb9r9vKTlMXroJv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FOb9r9vKTlMXroJv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FOb9r9vKTlMXroJv .error-icon{fill:#552222;}#mermaid-svg-FOb9r9vKTlMXroJv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FOb9r9vKTlMXroJv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FOb9r9vKTlMXroJv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FOb9r9vKTlMXroJv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FOb9r9vKTlMXroJv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FOb9r9vKTlMXroJv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FOb9r9vKTlMXroJv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FOb9r9vKTlMXroJv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FOb9r9vKTlMXroJv .marker.cross{stroke:#333333;}#mermaid-svg-FOb9r9vKTlMXroJv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FOb9r9vKTlMXroJv p{margin:0;}#mermaid-svg-FOb9r9vKTlMXroJv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FOb9r9vKTlMXroJv .cluster-label text{fill:#333;}#mermaid-svg-FOb9r9vKTlMXroJv .cluster-label span{color:#333;}#mermaid-svg-FOb9r9vKTlMXroJv .cluster-label span p{background-color:transparent;}#mermaid-svg-FOb9r9vKTlMXroJv .label text,#mermaid-svg-FOb9r9vKTlMXroJv span{fill:#333;color:#333;}#mermaid-svg-FOb9r9vKTlMXroJv .node rect,#mermaid-svg-FOb9r9vKTlMXroJv .node circle,#mermaid-svg-FOb9r9vKTlMXroJv .node ellipse,#mermaid-svg-FOb9r9vKTlMXroJv .node polygon,#mermaid-svg-FOb9r9vKTlMXroJv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FOb9r9vKTlMXroJv .rough-node .label text,#mermaid-svg-FOb9r9vKTlMXroJv .node .label text,#mermaid-svg-FOb9r9vKTlMXroJv .image-shape .label,#mermaid-svg-FOb9r9vKTlMXroJv .icon-shape .label{text-anchor:middle;}#mermaid-svg-FOb9r9vKTlMXroJv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FOb9r9vKTlMXroJv .rough-node .label,#mermaid-svg-FOb9r9vKTlMXroJv .node .label,#mermaid-svg-FOb9r9vKTlMXroJv .image-shape .label,#mermaid-svg-FOb9r9vKTlMXroJv .icon-shape .label{text-align:center;}#mermaid-svg-FOb9r9vKTlMXroJv .node.clickable{cursor:pointer;}#mermaid-svg-FOb9r9vKTlMXroJv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FOb9r9vKTlMXroJv .arrowheadPath{fill:#333333;}#mermaid-svg-FOb9r9vKTlMXroJv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FOb9r9vKTlMXroJv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FOb9r9vKTlMXroJv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FOb9r9vKTlMXroJv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FOb9r9vKTlMXroJv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FOb9r9vKTlMXroJv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FOb9r9vKTlMXroJv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FOb9r9vKTlMXroJv .cluster text{fill:#333;}#mermaid-svg-FOb9r9vKTlMXroJv .cluster span{color:#333;}#mermaid-svg-FOb9r9vKTlMXroJv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FOb9r9vKTlMXroJv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FOb9r9vKTlMXroJv rect.text{fill:none;stroke-width:0;}#mermaid-svg-FOb9r9vKTlMXroJv .icon-shape,#mermaid-svg-FOb9r9vKTlMXroJv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FOb9r9vKTlMXroJv .icon-shape p,#mermaid-svg-FOb9r9vKTlMXroJv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FOb9r9vKTlMXroJv .icon-shape .label rect,#mermaid-svg-FOb9r9vKTlMXroJv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FOb9r9vKTlMXroJv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FOb9r9vKTlMXroJv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FOb9r9vKTlMXroJv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 文档切片
嵌入模型向量化
存入向量数据库
用户查询
查询向量化
相似度搜索
返回相关片段
LangChain 向量数据库接口
LangChain 为向量数据库抽象出了统一的接口,所有实现该接口的数据库都支持以下方法:
add_documents(documents):批量添加文档(含向量)。delete(ids):按 ID 删除文档。similarity_search(query, k):纯文本查询,返回最相似的 k 个文档。similarity_search_by_vector(vector, k):直接传入向量进行查询。- 部分数据库还支持
max_marginal_relevance_search(MMR)和混合检索。
常见向量数据库有 Chroma、FAISS、Pinecone、Milvus、Weaviate 等,其中 Chroma 和 FAISS 适合本地轻量级使用,Pinecone 和 Milvus 面向生产环境。
向量库基本操作:增、删、查
下面使用 FakeEmbeddings 模拟向量嵌入,搭配 Chroma 内存向量库,演示完整的增删查流程。无需任何外部 API。
安装依赖:
bash
pip install langchain langchain-core langchain-community chromadb
文档添加
python
from langchain_community.embeddings.fake import FakeEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
# 模拟嵌入模型(维度 128)
embeddings = FakeEmbeddings(size=128)
# 准备文档
docs = [
Document(page_content="智能温控水杯支持手机 App 远程控温。", metadata={"source": "product"}),
Document(page_content="产品续航 48 小时,采用 316 不锈钢内胆。", metadata={"source": "product"}),
Document(page_content="充电时请使用 5V/2A 适配器。", metadata={"source": "product"}),
]
# 创建内存向量库并添加文档(可指定 ID)
vectorstore = Chroma(embedding_function=embeddings, collection_name="demo")
ids = ["doc_1", "doc_2", "doc_3"]
vectorstore.add_documents(docs, ids=ids)
print("已添加文档数:", vectorstore._collection.count())
删除文档
按 ID 删除某条记录:
python
vectorstore.delete(ids=["doc_2"])
print("删除后文档数:", vectorstore._collection.count()) # 输出 2
相似性搜索
使用纯文本查询:
python
results = vectorstore.similarity_search("怎么充电?", k=1)
for doc in results:
print(doc.page_content) # 应返回充电相关文档
也可以先将查询向量化再搜索:
python
query_vector = embeddings.embed_query("怎么充电?")
results = vectorstore.similarity_search_by_vector(query_vector, k=1)
print(results[0].page_content)
高级检索:MMR 搜索
最大边际相关性(MMR)算法在保持结果与查询相关的同时,尽量增加结果之间的多样性,避免返回过于相似的内容。Chroma 支持 max_marginal_relevance_search。
python
# 添加一些内容相近的文档以便观察 MMR 效果
additional_docs = [
Document(page_content="水杯过热保护功能详解", metadata={"source": "manual"}),
Document(page_content="如何正确清洗保温杯内胆", metadata={"source": "manual"}),
Document(page_content="电池续航测试及充电注意事项", metadata={"source": "manual"}),
]
vectorstore.add_documents(additional_docs)
# MMR 搜索:取 3 条结果,多样性参数 lambda_mult=0.5(值越小越注重多样性)
mmr_results = vectorstore.max_marginal_relevance_search("充电", k=3, lambda_mult=0.5)
for doc in mmr_results:
print(doc.page_content)
MMR 会尽量避免只返回三篇全都是充电的文章,而是可能混入一篇关于清洗或过热保护的文档,提供更丰富的上下文。
混合搜索简介
一些高级向量数据库(如 Pinecone)支持混合搜索,先通过关键词(如 BM25 算法)过滤候选文档,再在缩小后的集合中进行向量相似度匹配。这种方式能结合关键词的精确性和语义的泛化性,显著提升检索质量。LangChain 提供了相应的 Retrieval 封装,如 Pinecone 的 HybridSearchRetriever。因需要外部服务,本文不展开运行,但其理念与 MMR 相似:用更智能的算法提升召回率和答案质量。
完整可运行代码整合
以下代码将增、删、查、MMR 整合于一个脚本,使用内存向量库,无需任何 API Key。
python
from langchain_community.embeddings.fake import FakeEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
embeddings = FakeEmbeddings(size=128)
# 初始文档
docs = [
Document(page_content="智能温控水杯支持手机 App 远程控温。", metadata={"type": "feature"}),
Document(page_content="产品续航 48 小时,采用 316 不锈钢内胆。", metadata={"type": "feature"}),
Document(page_content="充电时请使用 5V/2A 适配器。", metadata={"type": "caution"}),
Document(page_content="请勿将杯体浸入水中清洗。", metadata={"type": "caution"}),
Document(page_content="可通过 App 调节温度范围 40~100°C。", metadata={"type": "feature"}),
]
vectorstore = Chroma(embedding_function=embeddings, collection_name="cup")
ids = ["d1", "d2", "d3", "d4", "d5"]
vectorstore.add_documents(docs, ids=ids)
# 删除一条
vectorstore.delete(ids=["d4"])
print("剩余文档数:", vectorstore._collection.count())
# 文本搜索
print("\n--- 相似性搜索:充电 ---")
for doc in vectorstore.similarity_search("如何充电?", k=2):
print(doc.page_content)
# MMR 搜索
print("\n--- MMR 搜索:充电(多样性优先) ---")
for doc in vectorstore.max_marginal_relevance_search("充电", k=2, lambda_mult=0.3):
print(doc.page_content)
总结
向量数据库是 RAG 应用的数据心脏,LangChain 通过统一接口让开发者无需关心底层差异即可完成增删查。掌握基本的 add_documents、delete、similarity_search 后,根据场景选用 MMR 或混合搜索,能显著提升检索质量和最终回答的准确度。
从本地 Chroma/FAISS 到云端 Pinecone/Milvus,LangChain 都能丝滑切换,为你的 AI 应用提供强大的知识检索基座。