LangChain RAG 简述
在 LangChain 中实现 RAG(检索增强生成,Retrieval-Augmented Generation)的核心思路是:让大模型在生成回答前,先从外部知识库(如文档、数据库等)中检索相关信息,再基于检索到的内容生成更准确、更可靠的回答。LangChain 提供了丰富的组件和工具链,支持多种 RAG 实现方法,适配不同场景(如简单文档问答、多源信息整合、对话式问答等)。以下是常见的方法及具体实现步骤:
一、基础 RAG:单文档/单源检索增强
适用场景:简单的文档问答(如单篇论文、手册、长文本的精准问答),核心是“加载→分割→嵌入→存储→检索→生成”的完整流程。
具体做法:
-
文档加载(Document Loading)
用 LangChain 的DocumentLoaders
加载目标文档(支持 PDF、TXT、Word、网页等多种格式),将文档转换为 LangChain 标准的Document
对象(包含文本内容page_content
和元数据metadata
)。
常用工具:PyPDFLoader
(PDF)、TextLoader
(TXT)、UnstructuredFileLoader
(多格式)、WebBaseLoader
(网页)等。from langchain.document_loaders import PyPDFLoader loader = PyPDFLoader("论文.pdf") # 加载 PDF 文档 documents = loader.load() # 得到 Document 列表
-
文档分割(Text Splitting)
长文档直接嵌入会丢失上下文,需用TextSplitter
分割为短片段(chunk)。关键是控制chunk_size
(片段长度)和chunk_overlap
(片段重叠度,保留上下文关联)。
常用工具:RecursiveCharacterTextSplitter
(通用分割,按标点/换行递归分割)、CharacterTextSplitter
(简单字符分割)等。from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, # 每个片段 1000 字符 chunk_overlap=200 # 重叠 200 字符,保留上下文 ) splits = text_splitter.split_documents(documents) # 分割后的 Document 列表
-
文本嵌入(Embedding)
将分割后的文本片段转换为向量(嵌入),以便后续通过向量相似度检索相关内容。需用嵌入模型生成向量。
常用工具:OpenAIEmbeddings
(OpenAI 的 embedding 模型)、HuggingFaceEmbeddings
(开源模型如 BERT、Sentence-BERT)等。from langchain.embeddings import OpenAIEmbeddings embeddings = OpenAIEmbeddings() # 使用 OpenAI 的 embedding 模型
-
向量存储(Vector Storage)
将嵌入向量和对应的文本片段存储到向量数据库(VectorStore),支持高效的相似度检索。
常用工具:轻量本地库Chroma
、FAISS
;云端服务Pinecone
、Weaviate
、Milvus
等。from langchain.vectorstores import Chroma # 初始化向量库并添加文档(自动完成嵌入和存储) vectorstore = Chroma.from_documents( documents=splits, embedding=embeddings, persist_directory="./chroma_db" # 本地存储路径 ) vectorstore.persist() # 持久化存储
-
构建检索器(Retriever)
从向量库中检索与问题相关的文本片段,作为 RAG 的“检索”环节。LangChain 的VectorStore
可直接转换为Retriever
。retriever = vectorstore.as_retriever( search_kwargs={"k": 3} # 检索最相关的 top 3 片段 )
-
生成回答(Generation)
用大模型(LLM)结合检索到的内容生成回答,通过RetrievalQA
链串联“检索→生成”流程。from langchain.chat_models import ChatOpenAI from langchain.chains import RetrievalQA llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0) # 大模型 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", # 将检索到的内容全部传入模型 retriever=retriever, return_source_documents=True # 返回检索到的源文档(可选) ) # 提问并获取回答 query = "这篇论文的核心创新点是什么?" result = qa_chain({"query": query}) print(result["result"]) # 回答内容 print(result["source_documents"]) # 检索到的源文档
二、进阶 RAG:多阶段检索与精准优化
适用场景:当基础 RAG 检索相关性不足(如文档量大、歧义问题)时,通过多阶段检索或重排序提升精度。
具体做法:
-
多查询检索(Multi-Query Retrieval)
对原始问题生成多个相似查询(由 LLM 自动扩展),用多个查询检索后合并结果,覆盖更多相关片段。from langchain.retrievers.multi_query import MultiQueryRetriever # 用 LLM 生成多个查询 retriever_from_llm = MultiQueryRetriever.from_llm( retriever=vectorstore.as_retriever(), llm=ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0) ) # 用多查询检索结果回答 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=retriever_from_llm )
-
上下文压缩检索(Contextual Compression)
先检索初步结果,再用“重排序模型(Reranker)”或“过滤模型”对结果二次筛选,保留最相关的片段。
常用工具:ContextualCompressionRetriever
结合CohereRerank
、RankGPT
等重排序工具。from langchain.retrievers import ContextualCompressionRetriever from langchain.retrievers.document_compressors import CohereRerank # 初始化重排序器(需 Cohere API 密钥) compressor = CohereRerank(model="rerank-english-v2.0", top_n=3) # 构建压缩检索器 compression_retriever = ContextualCompressionRetriever( base_compressor=compressor, base_retriever=vectorstore.as_retriever(search_kwargs={"k": 10}) # 先检索 top 10 ) # 用压缩后的结果生成回答 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=compression_retriever )
-
混合检索(Hybrid Retrieval)
结合“向量检索(语义相似)”和“关键词检索(精确匹配)”,兼顾语义理解和精准关键词匹配(如专业术语)。
常用工具:Pinecone
、Weaviate
等支持混合检索的向量库,或用LangChain
的MultiRetriever
组合。
三、多源 RAG:跨类型/跨库信息整合
适用场景:需要从多个数据源(如文档、数据库、API、表格等)检索信息,整合后生成回答(如企业知识库+产品数据库的问答)。
具体做法:
-
多向量库检索(Multi-VectorStore Retrieval)
为不同类型的文档(如技术手册、用户案例、API 文档)创建独立向量库,检索时并行查询并合并结果。# 初始化多个向量库 vectorstore_tech = Chroma.from_documents(tech_docs, embeddings, persist_directory="./tech_db") vectorstore_case = Chroma.from_documents(case_docs, embeddings, persist_directory="./case_db") # 构建多检索器 from langchain.retrievers import MultiRetriever retrievers = [ vectorstore_tech.as_retriever(search_kwargs={"k": 2}), vectorstore_case.as_retriever(search_kwargs={"k": 2}) ] multi_retriever = MultiRetriever(retrievers=retrievers) # 用多检索器生成回答 qa_chain = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=multi_retriever)
-
结构化+非结构化混合检索
结合非结构化文档(向量检索)和结构化数据(如 SQL 数据库、CSV 表格),用SQLDatabaseChain
或TableQA
处理结构化查询,再与文档检索结果整合。from langchain.chains import SQLDatabaseChain from langchain.sql_database import SQLDatabase # 连接 SQL 数据库 db = SQLDatabase.from_uri("sqlite:///产品库存.db") sql_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True) # 定义路由逻辑:判断问题需要文档检索还是数据库查询 from langchain.chains import RouterChain, LLMRouterChain, MultiPromptChain from langchain.prompts import PromptTemplate # 路由提示:让 LLM 判断问题类型 route_prompt = PromptTemplate( template="""判断问题需要查询文档还是数据库:{input} 输出 'doc' 或 'sql'""", input_variables=["input"] ) router_chain = LLMRouterChain.from_llm(llm, route_prompt) # 整合链:根据路由结果调用对应工具 chains = {"doc": qa_chain, "sql": sql_chain} multi_chain = MultiPromptChain(router_chain=router_chain, destination_chains=chains) # 提问(如“产品A的库存有多少?”→ 路由到 SQL;“产品A的使用场景?”→ 路由到文档) result = multi_chain.run("产品A的库存和使用场景分别是什么?")
四、对话式 RAG:带历史记忆的检索增强
适用场景:对话场景(如客服机器人),需要结合历史对话上下文动态检索,确保回答连贯性(如“上一个问题提到的功能如何操作?”)。
具体做法:
用 ConversationalRetrievalChain
替代基础 RetrievalQA
,自动处理对话历史,生成包含历史上下文的检索查询。
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory # 初始化对话记忆(存储历史对话)
memory = ConversationBufferMemory( memory_key="chat_history", # 记忆键名 return_messages=True, # 返回消息对象 output_key="answer" # 输出键名(与链对齐)
) # 构建对话式 RAG 链
conv_chain = ConversationalRetrievalChain.from_llm( llm=llm, retriever=retriever, memory=memory, return_source_documents=True
) # 多轮对话示例
query1 = "这篇论文的研究背景是什么?"
result1 = conv_chain({"question": query1})
print(result1["answer"]) query2 = "基于这个背景,作者提出了什么方法?" # 依赖上一轮历史
result2 = conv_chain({"question": query2})
print(result2["answer"])
五、多模态 RAG:整合文本、图片、表格等跨类型信息
适用场景:文档包含图片、表格、公式等非文本内容(如 PDF 中的图表、PPT 中的图片),需检索多模态信息生成回答。
具体做法:
- 多模态文档加载:用
UnstructuredFileLoader
或PyPDFLoader
加载含多模态内容的文档,保留图片/表格元数据。 - 多模态嵌入:对文本用常规嵌入模型,对图片用视觉嵌入模型(如 CLIP),存储到支持多模态的向量库(如
Qdrant
、Weaviate
)。 - 多模态检索:检索时同时匹配文本和图片向量,生成回答时引用图片内容(如“图1展示了XXX流程”)。
# 示例:加载含图片的 PDF 并保留图片元数据
from langchain.document_loaders import PyPDFLoader
loader = PyPDFLoader("带图片的文档.pdf", extract_images=True) # 提取图片
documents = loader.load() # 多模态向量库存储(以 Qdrant 为例)
from langchain.vectorstores import Qdrant
from langchain.embeddings import HuggingFaceBgeEmbeddings # 文本嵌入
from PIL import Image
import clip # 视觉嵌入模型 # 文本嵌入 + 图片嵌入逻辑(需自定义处理)
# ...(省略图片嵌入细节) # 构建多模态检索器并生成回答
qdrant = Qdrant.from_documents(...)
retriever = qdrant.as_retriever()
qa_chain = RetrievalQA.from_chain_type(llm=llm, retriever=retriever)
总结
LangChain 实现 RAG 的核心是通过“组件化”灵活组合文档处理、检索、生成环节,关键方法可归纳为:
- 基础流程:加载→分割→嵌入→存储→检索→生成;
- 精度优化:多查询、重排序、混合检索;
- 多源整合:多向量库、结构化+非结构化混合;
- 场景适配:对话式记忆、多模态检索。
实际应用中需根据文档类型、问答场景选择合适的方法,并通过调整 chunk_size
、检索 k
值、重排序策略等优化效果。