跳到主要内容

向量数据库

向量数据库是 RAG 系统的核心组件,用于存储和检索文档的向量表示。本章将介绍常用的向量数据库及其使用方法。

什么是向量数据库?

向量数据库 专门用于存储高维向量(嵌入),并支持高效的相似度搜索。在 RAG 系统中,它存储文档块的嵌入向量,根据用户查询检索最相关的文档。

为什么需要向量数据库?

  • 高效相似度搜索:传统数据库无法高效计算向量相似度
  • 语义检索:基于语义而非关键词匹配
  • 大规模数据:支持数十亿级向量的快速检索

常用向量数据库

1. Chroma

轻量级、易用的本地向量数据库:

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings

# 创建嵌入
embeddings = OpenAIEmbeddings()

# 从文档创建向量存储
vectorstore = Chroma.from_documents(
documents=splits,
embedding=embeddings,
collection_name="my_collection"
)

# 持久化存储
vectorstore = Chroma.from_documents(
documents=splits,
embedding=embeddings,
persist_directory="./chroma_db"
)

# 检索
results = vectorstore.similarity_search("query", k=3)

2. Pinecone

云端向量数据库,支持大规模部署:

from langchain_pinecone import PineconeVectorStore
from langchain_openai import OpenAIEmbeddings
import pinecone

# 初始化 Pinecone
pinecone.init(
api_key="your-api-key",
environment="us-west1"
)

# 创建向量存储
vectorstore = PineconeVectorStore.from_documents(
documents=splits,
embedding=embeddings,
index_name="my-index"
)

# 检索
results = vectorstore.similarity_search("query", k=3)

3. Weaviate

开源向量搜索引擎:

from langchain_weaviate import WeaviateVectorStore
import weaviate

# 连接 Weaviate
client = weaviate.Client("http://localhost:8080")

# 创建向量存储
vectorstore = WeaviateVectorStore(
client=client,
index_name="MyIndex",
text_key="text",
embedding=embeddings
)

# 添加文档
vectorstore.add_documents(documents)

4. Milvus

国产开源向量数据库,支持多种索引:

from langchain_milvus import Milvus
from langchain_openai import OpenAIEmbeddings

# 创建向量存储
vectorstore = Milvus.from_documents(
documents=splits,
embedding=embeddings,
connection_args={"host": "localhost", "port": "19530"}
)

# 检索
results = vectorstore.similarity_search("query", k=3)

5. Qdrant

Rust 编写的向量数据库,性能高:

from langchain_qdrant import Qdrant
from langchain_openai import OpenAIEmbeddings

# 创建向量存储
vectorstore = Qdrant.from_documents(
documents=splits,
embedding=embeddings,
location=":memory:", # 内存模式,或使用 url 连接到远程
collection_name="my_collection"
)

6. FAISS

Facebook 的向量检索库,适合本地测试:

from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

# 创建向量存储
vectorstore = FAISS.from_documents(
documents=splits,
embedding=embeddings
)

# 保存到磁盘
vectorstore.save_local("faiss_index")

# 加载
loaded_vectorstore = FAISS.load_local("faiss_index", embeddings)

向量数据库操作

创建索引

# 方式1:从文档创建
vectorstore = Chroma.from_documents(
documents=documents,
embedding=embeddings,
collection_name="my_docs"
)

# 方式2:手动添加
vectorstore = Chroma.from_texts(
texts=["text1", "text2", "text3"],
embedding=embeddings
)

相似度搜索

# 基本搜索
results = vectorstore.similarity_search("query", k=3)

# 带相似度分数
results = vectorstore.similarity_search_with_score("query", k=3)

# 查看分数
for doc, score in results:
print(f"内容: {doc.page_content[:50]}...")
print(f"相似度分数: {score}\n")

删除和更新

# 删除集合
vectorstore.delete_collection()

# 删除指定文档
vectorstore.delete(ids=["doc_id1", "doc_id2"])

# 更新文档
vectorstore.update_document("doc_id", new_document)

检索器配置

as_retriever

# 创建检索器
retriever = vectorstore.as_retriever(
search_type="similarity", # 类型
search_kwargs={
"k": 3, # 返回数量
"score_threshold": 0.8 # 相似度阈值
}
)

# 使用检索器
docs = retriever.invoke("query")

搜索类型

类型说明适用场景
similarity相似度搜索默认场景
similarity_threshold阈值过滤精确匹配
mmr最大边际相关多样性结果
similarity_score_threshold分数阈值质量控制

嵌入模型

OpenAI Embeddings

from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(
model="text-embedding-3-small" # 或 text-embedding-3-large
)

# 文本嵌入
vector = embeddings.embed_query("Hello world")
print(f"维度: {len(vector)}")

本地 Embeddings

from langchain_community.embeddings import HuggingFaceEmbeddings

embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2"
)

其他 Embeddings

# Google
from langchain_google_genai import GoogleGenerativeAIEmbeddings

# Anthropic
from langchain_anthropic import AnthropicEmbeddings

# Cohere
from langchain_cohere import CohereEmbeddings

实际应用示例

1. 文档问答系统

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.prompts import ChatPromptTemplate

# 1. 加载文档
loader = TextLoader("document.txt")
documents = loader.load()

# 2. 分割
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
splits = splitter.split_documents(documents)

# 3. 嵌入存储
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(splits, embeddings)

# 4. 创建问答链
prompt = ChatPromptTemplate.from_template("""
基于以下文档回答问题:

{context}

问题:{input}
""")

qa_chain = create_stuff_documents_chain(model, prompt)
retrieval_chain = create_retrieval_chain(vectorstore.as_retriever(), qa_chain)

# 5. 问答
result = retrieval_chain.invoke({"input": "你的问题"})
print(result["answer"])

2. 本地知识库

# 使用 FAISS 本地存储
from langchain_community.vectorstores import FAISS

# 创建
vectorstore = FAISS.from_documents(documents, embeddings)

# 保存
vectorstore.save_local("knowledge_base")

# 加载
vectorstore = FAISS.load_local("knowledge_base", embeddings)

# 检索
results = vectorstore.similarity_search("查询内容")

3. 多租户系统

# 为每个租户创建独立的向量存储
def get_tenant_vectorstore(tenant_id: str):
return Chroma.from_documents(
documents=get_tenant_documents(tenant_id),
embedding=embeddings,
collection_name=f"tenant_{tenant_id}"
)

# 使用
for tenant in ["tenant_a", "tenant_b"]:
vs = get_tenant_vectorstore(tenant)
results = vs.similarity_search(user_query)

性能优化

索引类型

# Pinecone 索引配置
index = pinecone.Index("my-index",
dimension=1536,
metric="cosine",
pod_type="p1"
)

批处理

# 批量添加文档
from langchain_community.vectorstores import Chroma

# 分批添加
batch_size = 100
for i in range(0, len(documents), batch_size):
batch = documents[i:i+batch_size]
vectorstore.add_documents(batch)

缓存嵌入

from langchain.embeddings import CacheBackedEmbeddings

# 创建缓存嵌入
cache_embedder = CacheBackedEmbeddings.from_bytes_store(
underlying_embeddings=embeddings,
bytes_store=InMemoryByteStore(),
namespace="embeddings"
)

常见问题

1. 检索结果不准确

  • 检查文档质量
  • 调整 chunk_size
  • 尝试不同的嵌入模型

2. 性能问题

  • 使用索引加速
  • 增加服务器资源
  • 使用更小的嵌入模型

3. 数据持久化

  • 定期备份向量数据库
  • 检查磁盘空间

下一步

现在你已经掌握了向量数据库的使用,接下来学习: