LangChain 向量数据库详解
·
文章目录
LangChain 向量数据库详解
本文介绍如何使用 FAISS 向量数据库存储文档向量,并实现语义检索功能。
1. 什么是向量数据库?
1.1 海马体的比喻
人类大脑中,海马体负责存储和检索记忆。向量数据库就像是 AI 的"海马体",专门用于存储和检索嵌入向量。
传统数据库: 存储结构化数据(表格、文本)
向量数据库: 存储嵌入向量,支持语义相似度搜索
1.2 核心功能
| 功能 | 说明 |
|---|---|
| 存储向量 | 将文本的嵌入向量持久化存储 |
| 相似度搜索 | 根据向量相似度返回最相关的文档 |
| 实时检索 | 将用户查询转换为向量,匹配最相似结果 |
2. 什么是 FAISS?
2.1 FAISS 简介
FAISS(Facebook AI Similarity Search)是 Facebook 开发的开源向量检索库:
| 特点 | 说明 |
|---|---|
| 高性能 | 亿级向量秒级检索 |
| 多种索引 | 支持 IVF、HNSW 等多种索引算法 |
| 易用 | 纯 Python 接口,与 LangChain 无缝集成 |
| 内存优化 | 支持量化压缩,减少内存占用 |
2.2 其他向量数据库对比
| 数据库 | 特点 |
|---|---|
| FAISS | Facebook 开源,适合本地小规模场景 |
| Chroma | 轻量级,适合快速原型开发 |
| Milvus | 企业级,支持分布式部署 |
| Pinecone | 云服务,无需自建 |
| Weaviate | 支持混合搜索(向量+关键词) |
3. 代码解析
3.1 完整代码
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain_openai.embeddings import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 加载文档
loader = TextLoader("./demo.txt", encoding="utf-8")
docs = loader.load()
# 2. 文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=40,
separators=["\n\n", "\n", "。", "!", "?", ",", "、", ""]
)
texts = text_splitter.split_documents(docs)
# 3. 初始化嵌入模型
embeddings_model = OpenAIEmbeddings(
model="text-embedding-3-large",
openai_api_key="sk-xxxx",
openai_api_base="https://api.xxx.com/v1"
)
# 4. 构建向量数据库
db = FAISS.from_documents(texts, embeddings_model)
# 5. 创建检索器
retriever = db.as_retriever()
3.2 向量数据库创建
db = FAISS.from_documents(documents, embedding_model)
| 参数 | 说明 |
|---|---|
documents |
Document 对象列表(分块后的文本) |
embedding_model |
嵌入模型(必须与检索时一致) |
4. 检索功能
4.1 创建检索器
retriever = db.as_retriever()
4.2 执行检索
# 语义检索:用户提问,系统返回最相关的文档块
retrieved_docs = retriever.invoke("卢浮宫这个名字怎么来的?")
# 查看检索结果
print(retrieved_docs[0].page_content)
4.3 检索流程示意
用户问题: "卢浮宫这个名字怎么来的?"
↓
转换为向量 [0.123, -0.456, ...]
↓
在 FAISS 中搜索最相似的文档块
↓
返回 top-k 相关文档
5. 完整 RAG 流程
from langchain_openai import ChatOpenAI
# 1. 加载并分块文档
loader = TextLoader("./demo.txt", encoding="utf-8")
docs = loader.load()
texts = text_splitter.split_documents(docs)
# 2. 构建向量数据库
db = FAISS.from_documents(texts, embeddings_model)
retriever = db.as_retriever()
# 3. 用户提问
query = "卢浮宫这个名字怎么来的?"
# 4. 检索相关文档
retrieved_docs = retriever.invoke(query)
# 5. 构建提示词(将检索结果注入上下文)
context = "\n".join([doc.page_content for doc in retrieved_docs])
prompt = f"根据以下内容回答问题:\n\n{context}\n\n问题:{query}"
# 6. 调用 LLM 生成答案
llm = ChatOpenAI(model="gpt-4", api_key="sk-xxxx", base_url="https://api.xxx.com/v1")
answer = llm.invoke(prompt)
print(answer)
结果:
6. FAISS 高级用法
6.1 指定返回数量
retriever = db.as_retriever(search_kwargs={"k": 3}) # 返回3条
retrieved_docs = retriever.invoke("卢浮宫在哪里?")
6.2 相似度阈值过滤
# 只返回相似度 > 0.8 的结果
retriever = db.as_retriever(
search_type="similarity_score_threshold",
search_kwargs={"score_threshold": 0.8}
)
6.3 混合搜索(MMR)
# Maximum Marginal Relevance - 兼顾相关性和多样性
retriever = db.as_retriever(
search_type="mmr",
search_kwargs={"k": 3, "fetch_k": 10}
)
6.4 保存和加载
# 保存到本地
db.save_local("faiss_index")
# 加载
db = FAISS.load_local("faiss_index", embeddings_model)
7. 常见问题
Q1: FAISS 和 Chroma 哪个好?
| 场景 | 推荐 |
|---|---|
| 本地快速原型 | Chroma |
| 亿级大数据 | FAISS |
| 云服务 | Pinecone/Milvus |
Q2: 检索结果不准确怎么办?
- 调整
chunk_size:尝试 300-1000 范围 - 调整检索数量
k:更多候选但可能引入噪声 - 检查嵌入模型是否匹配
Q3: 如何提升检索速度?
- 使用 HNSW 索引(适合小规模数据)
- 启用量化压缩(适合大规模数据)
- 控制向量维度(用 dimensions 参数压缩)
Q4: 向量数据库需要持久化吗?
建议持久化,避免每次重启重新构建:
db.save_local("my_faiss_index")
db = FAISS.load_local("my_faiss_index", embeddings_model)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)