向量存储(Vector Stores) #
向量存储是 RAG 应用的核心组件,负责存储文档的向量表示并支持高效的相似度检索。LangChain 支持多种向量数据库,满足不同场景的需求。
向量存储概述 #
text
┌─────────────────────────────────────────────────────────────┐
│ 向量存储的作用 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 存储: │
│ 文档 ───> 向量化 ───> 存储到向量数据库 │
│ │
│ 检索: │
│ 查询 ───> 向量化 ───> 相似度搜索 ───> 返回相关文档 │
│ │
│ 核心功能: │
│ ✅ 高效存储大量向量 │
│ ✅ 快速相似度搜索 │
│ ✅ 支持元数据过滤 │
│ ✅ 支持增删改查 │
│ │
└─────────────────────────────────────────────────────────────┘
基本使用 #
创建向量存储 #
python
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
# 创建嵌入模型
embeddings = OpenAIEmbeddings()
# 方式一:从文档列表创建
documents = [
Document(page_content="机器学习是AI的一个分支", metadata={"source": "doc1"}),
Document(page_content="深度学习使用神经网络", metadata={"source": "doc2"}),
]
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory="./chroma_db"
)
# 方式二:从文本列表创建
texts = ["机器学习是AI的一个分支", "深度学习使用神经网络"]
metadatas = [{"source": "doc1"}, {"source": "doc2"}]
vectorstore = Chroma.from_texts(
texts=texts,
embedding=embeddings,
metadatas=metadatas,
persist_directory="./chroma_db"
)
相似度搜索 #
python
# 基础搜索
results = vectorstore.similarity_search(
query="什么是AI技术",
k=4 # 返回最相似的 4 个文档
)
for doc in results:
print(doc.page_content)
print(doc.metadata)
print("-" * 50)
# 带分数的搜索
results_with_scores = vectorstore.similarity_search_with_score(
query="什么是AI技术",
k=4
)
for doc, score in results_with_scores:
print(f"Score: {score:.4f}")
print(doc.page_content)
print("-" * 50)
添加和删除文档 #
python
# 添加文档
vectorstore.add_documents([
Document(page_content="新文档内容", metadata={"source": "new"})
])
# 添加文本
vectorstore.add_texts(
texts=["另一个新文档"],
metadatas=[{"source": "another"}]
)
# 删除文档
vectorstore.delete(ids=["doc-id-1", "doc-id-2"])
常用向量数据库 #
FAISS(本地) #
Facebook 开源的高效向量搜索库:
python
from langchain_community.vectorstores import FAISS
# 创建
vectorstore = FAISS.from_documents(
documents=documents,
embedding=embeddings
)
# 保存到本地
vectorstore.save_local("./faiss_index")
# 从本地加载
vectorstore = FAISS.load_local(
"./faiss_index",
embeddings=embeddings,
allow_dangerous_deserialization=True
)
# 合并多个索引
vectorstore1.merge_from(vectorstore2)
Chroma(本地) #
功能丰富的本地向量数据库:
python
from langchain_community.vectorstores import Chroma
# 创建(持久化)
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embeddings,
persist_directory="./chroma_db",
collection_name="my_collection"
)
# 加载已有数据库
vectorstore = Chroma(
persist_directory="./chroma_db",
embedding_function=embeddings,
collection_name="my_collection"
)
# 内存模式
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embeddings
)
Pinecone(云端) #
托管式向量数据库:
python
from langchain_community.vectorstores import Pinecone
import pinecone
# 初始化 Pinecone
pinecone.init(
api_key="your-api-key",
environment="your-environment"
)
# 创建索引
index_name = "my-index"
if index_name not in pinecone.list_indexes():
pinecone.create_index(
name=index_name,
dimension=1536,
metric="cosine"
)
# 创建向量存储
vectorstore = Pinecone.from_documents(
documents=documents,
embedding=embeddings,
index_name=index_name
)
# 连接已有索引
vectorstore = Pinecone.from_existing_index(
index_name=index_name,
embedding=embeddings
)
Weaviate #
开源向量搜索引擎:
python
from langchain_community.vectorstores import Weaviate
import weaviate
# 连接 Weaviate
client = weaviate.Client("http://localhost:8080")
# 创建向量存储
vectorstore = Weaviate.from_documents(
documents=documents,
embedding=embeddings,
client=client,
index_name="MyCollection"
)
# 连接已有集合
vectorstore = Weaviate(
client=client,
index_name="MyCollection",
text_key="text",
embedding=embeddings
)
Milvus #
高性能分布式向量数据库:
python
from langchain_community.vectorstores import Milvus
# 创建向量存储
vectorstore = Milvus.from_documents(
documents=documents,
embedding=embeddings,
connection_args={
"host": "localhost",
"port": "19530"
},
collection_name="my_collection"
)
Qdrant #
高性能向量数据库:
python
from langchain_community.vectorstores import Qdrant
from qdrant_client import QdrantClient
# 创建客户端
client = QdrantClient(url="http://localhost:6333")
# 创建向量存储
vectorstore = Qdrant.from_documents(
documents=documents,
embedding=embeddings,
url="http://localhost:6333",
collection_name="my_collection"
)
text
┌─────────────────────────────────────────────────────────────┐
│ 向量数据库对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 数据库 │ 类型 │ 特点 │ 适用场景 │
│ ───────────────────────────────────────────────────────── │
│ FAISS │ 本地 │ 快速、轻量 │ 开发测试、小规模 │
│ Chroma │ 本地 │ 功能丰富 │ 本地应用、开发 │
│ Pinecone │ 云端 │ 托管、易用 │ 生产环境、无运维 │
│ Weaviate │ 开源 │ 功能全面 │ 自托管、企业级 │
│ Milvus │ 开源 │ 高性能、分布式 │ 大规模、高并发 │
│ Qdrant │ 开源 │ 高效、Rust │ 高性能需求 │
│ │
└─────────────────────────────────────────────────────────────┘
高级功能 #
元数据过滤 #
python
# Chroma 元数据过滤
results = vectorstore.similarity_search(
query="机器学习",
k=4,
filter={
"source": "doc1"
}
)
# 复杂过滤
results = vectorstore.similarity_search(
query="机器学习",
k=4,
filter={
"$and": [
{"source": {"$eq": "doc1"}},
{"year": {"$gte": 2023}}
]
}
)
# Pinecone 元数据过滤
results = vectorstore.similarity_search(
query="机器学习",
k=4,
filter={
"category": "tech",
"year": {"$gte": 2023}
}
)
MMR 搜索 #
最大边际相关性搜索,提高结果多样性:
python
# MMR 搜索
results = vectorstore.max_marginal_relevance_search(
query="机器学习",
k=4, # 返回结果数
fetch_k=20, # 候选结果数
lambda_mult=0.5 # 多样性权重
)
# 带分数的 MMR 搜索
results = vectorstore.max_marginal_relevance_search_with_score(
query="机器学习",
k=4,
fetch_k=20
)
text
┌─────────────────────────────────────────────────────────────┐
│ MMR vs 普通搜索 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 普通相似度搜索: │
│ 查询: "机器学习" │
│ 结果: │
│ 1. 机器学习是AI分支 (0.95) │
│ 2. 机器学习算法介绍 (0.94) ← 内容相似 │
│ 3. 机器学习应用场景 (0.93) ← 内容相似 │
│ │
│ MMR 搜索: │
│ 查询: "机器学习" │
│ 结果: │
│ 1. 机器学习是AI分支 (0.95) │
│ 2. 深度学习神经网络 (0.82) ← 内容多样 │
│ 3. 自然语言处理技术 (0.78) ← 内容多样 │
│ │
│ MMR 在保持相关性的同时增加结果多样性 │
│ │
└─────────────────────────────────────────────────────────────┘
创建检索器 #
python
# 基础检索器
retriever = vectorstore.as_retriever(
search_type="similarity",
search_kwargs={"k": 4}
)
# MMR 检索器
retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={"k": 4, "fetch_k": 20}
)
# 分数阈值检索器
retriever = vectorstore.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={"score_threshold": 0.8, "k": 4}
)
# 使用检索器
docs = retriever.invoke("什么是机器学习?")
管理操作 #
查看存储信息 #
python
# Chroma
collection = vectorstore._collection
print(f"文档数量: {collection.count()}")
# FAISS
print(f"索引大小: {vectorstore.index.ntotal}")
# Pinecone
index = pinecone.Index("my-index")
stats = index.describe_index_stats()
print(f"向量数量: {stats.total_vector_count}")
批量操作 #
python
# 批量添加
batch_documents = [
Document(page_content=f"文档 {i}", metadata={"id": i})
for i in range(1000)
]
vectorstore.add_documents(batch_documents)
# 分批处理大数据集
def batch_add_documents(documents, batch_size=100):
for i in range(0, len(documents), batch_size):
batch = documents[i:i + batch_size]
vectorstore.add_documents(batch)
更新文档 #
python
# 删除旧文档
vectorstore.delete(ids=["old-doc-id"])
# 添加新文档
vectorstore.add_documents([
Document(
page_content="更新后的内容",
metadata={"id": "new-doc-id"}
)
])
完整示例 #
文档知识库 #
python
from langchain_community.document_loaders import DirectoryLoader, PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
class KnowledgeBase:
"""文档知识库"""
def __init__(self, persist_directory: str):
self.embeddings = OpenAIEmbeddings()
self.vectorstore = Chroma(
persist_directory=persist_directory,
embedding_function=self.embeddings
)
def add_documents(self, documents: list):
"""添加文档"""
# 分割文档
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
splits = text_splitter.split_documents(documents)
# 添加到向量存储
self.vectorstore.add_documents(splits)
def search(self, query: str, k: int = 4) -> list:
"""搜索文档"""
return self.vectorstore.similarity_search(query, k=k)
def search_with_scores(self, query: str, k: int = 4) -> list:
"""带分数的搜索"""
return self.vectorstore.similarity_search_with_score(query, k=k)
def as_retriever(self, **kwargs):
"""获取检索器"""
return self.vectorstore.as_retriever(**kwargs)
# 使用
kb = KnowledgeBase("./knowledge_base")
# 添加文档
loader = DirectoryLoader("./documents", glob="**/*.pdf", loader_cls=PyPDFLoader)
documents = loader.load()
kb.add_documents(documents)
# 搜索
results = kb.search("什么是机器学习?")
for doc in results:
print(doc.page_content[:100])
print("-" * 50)
性能优化 #
1. 选择合适的索引 #
python
# FAISS - 选择索引类型
import faiss
# 平面索引(精确搜索,适合小数据集)
index = faiss.IndexFlatL2(1536)
# IVF 索引(近似搜索,适合大数据集)
nlist = 100 # 聚类中心数
quantizer = faiss.IndexFlatL2(1536)
index = faiss.IndexIVFFlat(quantizer, 1536, nlist)
2. 批量处理 #
python
# 批量添加文档
def batch_add(vectorstore, documents, batch_size=100):
for i in range(0, len(documents), batch_size):
batch = documents[i:i + batch_size]
vectorstore.add_documents(batch)
3. 缓存嵌入 #
python
from langchain.embeddings import CacheBackedEmbeddings
from langchain_community.storage import LocalFileStore
# 使用缓存的嵌入
store = LocalFileStore("./embedding_cache")
cached_embeddings = CacheBackedEmbeddings.from_bytes_store(
OpenAIEmbeddings(),
store
)
vectorstore = Chroma.from_documents(
documents=documents,
embedding=cached_embeddings
)
最佳实践 #
1. 选择合适的向量数据库 #
python
# 开发阶段 - 使用本地数据库
vectorstore = Chroma.from_documents(documents, embeddings)
# 生产环境 - 使用云端或分布式数据库
vectorstore = Pinecone.from_documents(documents, embeddings)
2. 合理设置参数 #
python
# 分割参数
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 根据模型上下文调整
chunk_overlap=50 # 适当的重叠
)
# 检索参数
retriever = vectorstore.as_retriever(
search_kwargs={"k": 4} # 根据需求调整
)
3. 持久化存储 #
python
# 定期持久化
vectorstore.persist()
# 备份向量数据库
import shutil
shutil.copytree("./chroma_db", "./chroma_db_backup")
下一步 #
最后更新:2026-03-30