实战 RAG(检索增强生成):用 LangChain 构建简单的知识问答系统,3 种 chain_type 效果对比

RAG(检索增强生成)是解决大模型 “知识过时” 与 “事实性错误” 的核心方案,本文将通过一个完整案例,带大家用 LangChain 实现基于 PDF 文档的卢浮宫知识问答,并对比不同chain_type的效果差异,帮你快速上手实用级 RAG 应用。

一、RAG 核心逻辑:让大模型 “有据可依”

传统大模型回答问题依赖训练数据,无法获取私有文档(如本地 PDF)或实时信息。RAG 通过 “检索 + 生成” 两步解决这一问题:

  1. 检索:从私有知识库(本文为卢浮宫 PDF)中,精准找到与问题相关的文本片段。
  2. 生成:大模型结合检索到的 “事实依据”,生成准确、有来源的回答,而非 “凭空想象”。

本文案例的技术链路为:PDF加载→文本分割→向量存储→检索→对话式生成,全程基于 LangChain 生态实现。

二、完整代码实战:从 0 搭建卢浮宫问答系统

1. 环境准备与依赖安装

首先安装核心库,cryptography用于解决部分环境下的加密依赖问题。

# 安装依赖
!pip install --upgrade cryptography langchain langchain_community langchain_openai langchain_text_splitters faiss-cpu pypdf dashscope

2. 核心步骤拆解

步骤 1:加载 PDF 文档

PyPDFLoader读取本地的 “卢浮宫.pdf”,将 PDF 每页内容转换为 LangChain 可处理的Document对象。

from langchain_community.document_loaders import PyPDFLoader

# 加载PDF,docs为Document对象列表,每个对象对应PDF一页
loader = PyPDFLoader("./卢浮宫.pdf")
docs = loader.load()
步骤 2:文本分割(关键优化点)

PDF 内容通常是长文本,直接嵌入会丢失上下文关联。用RecursiveCharacterTextSplitter按中文语义分割,平衡 “上下文完整性” 与 “检索精准度”。

from langchain_text_splitters import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,          # 每个文本块500字符
    chunk_overlap=40,        # 块间重叠40字符,避免语义断裂
    separators=["\n", "。", "!", "?", ",", "、", ""]  # 按中文标点分割,更符合语义
)
texts = text_splitter.split_documents(docs)  # 分割后得到文本块列表
步骤 3:构建向量数据库

将文本块转换为向量(嵌入),存储到 FAISS(轻量级向量库)中,方便后续快速检索相似文本。这里用阿里云 DashScope 的嵌入模型,也可替换为 OpenAI Embeddings。

from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import DashScopeEmbeddings

# 初始化嵌入模型,需替换为自己的DashScope API Key
embeddings_model = DashScopeEmbeddings(
    model="text-embedding-v2",
    dashscope_api_key="你的API Key"
)

# 将文本块嵌入并存储到FAISS,db即为向量数据库
db = FAISS.from_documents(texts, embeddings_model)
步骤 4:配置检索器与大模型
  • 检索器:从向量数据库中 “按相似度” 提取相关文本,是 RAG 的 “信息来源”。
  • 大模型:这里用 DashScope 兼容 OpenAI 格式的 “qwen-plus” 模型,也可替换为 GPT-3.5/4。
from langchain_openai import ChatOpenAI

# 构建检索器,默认按相似度返回相关文本
retriever = db.as_retriever()

# 初始化大模型,API Base为DashScope兼容地址
model = ChatOpenAI(
    model="qwen-plus",
    openai_api_key="你的API Key",  # 与DashScope API Key相同
    openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
步骤 5:对话记忆与 RAG 链构建

ConversationBufferMemory保存对话历史,让系统具备 “多轮对话理解” 能力;通过ConversationalRetrievalChain串联 “检索→记忆→生成” 全流程,核心差异在chain_type

三、3 种 chain_type 对比:哪种更适合你的场景?

chain_type决定了 RAG 链 “如何利用检索到的多个文本块生成回答”,不同类型各有优劣,以下是实战对比。

1. map_reduce:“并行处理 + 汇总”,适合多片段融合

逻辑:先对每个检索到的文本块单独生成回答(map),再汇总所有回答生成最终结果(reduce)。代码

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationalRetrievalChain

# 初始化对话记忆
memory = ConversationBufferMemory(
    return_messages=True,
    memory_key='chat_history',  # 与链的输入键对应
    output_key='answer'         # 存储生成的回答
)

# 构建map_reduce类型的RAG链
qa_map_reduce = ConversationalRetrievalChain.from_llm(
    llm=model,
    retriever=retriever,
    memory=memory,
    chain_type="map_reduce"  # 核心参数
)

# 调用问答,问题:“卢浮宫这个名字怎么来的?”
result_map_reduce = qa_map_reduce.invoke({
    "chat_history": memory,
    "question": "卢浮宫这个名字怎么来的?"
})
print("map_reduce回答:", result_map_reduce["answer"])

优势:能融合多个文本块的信息,适合问题需要 “多来源佐证” 的场景。劣势:调用次数多(每个文本块 1 次 map 调用),成本较高,速度较慢。

2. refine:“迭代优化”,适合逐步补充细节

逻辑:先基于第一个文本块生成初始回答,再逐个结合后续文本块 “优化” 回答(如补充细节、修正错误)。代码

# 重新初始化记忆(避免与其他链冲突)
memory_refine = ConversationBufferMemory(return_messages=True, memory_key='chat_history', output_key='answer')

# 构建refine类型的RAG链
qa_refine = ConversationalRetrievalChain.from_llm(
    llm=model,
    retriever=retriever,
    memory=memory_refine,
    chain_type="refine"
)

# 调用问答
result_refine = qa_refine.invoke({
    "chat_history": memory_refine,
    "question": "卢浮宫这个名字怎么来的?"
})
print("refine回答:", result_refine["answer"])

优势:回答会逐步完善,细节更丰富,适合需要 “深度解析” 的问题。劣势:依赖文本块顺序,若前序文本块信息不准确,后续优化可能受影响;速度同样较慢。

3. map_rerank:“评分筛选”,适合精准优先

逻辑:对每个文本块生成回答并打分(评分基于 “回答与问题的相关性”),最终返回评分最高的回答。代码

# 重新初始化记忆
memory_rerank = ConversationBufferMemory(return_messages=True, memory_key='chat_history', output_key='answer')

# 构建map_rerank类型的RAG链
qa_rerank = ConversationalRetrievalChain.from_llm(
    llm=model,
    retriever=retriever,
    memory=memory_rerank,
    chain_type="map_rerank"
)

# 调用问答
result_rerank = qa_rerank.invoke({
    "chat_history": memory_rerank,
    "question": "卢浮宫这个名字怎么来的?"
})
print("map_rerank回答:", result_rerank["answer"])

优势:只返回最优回答,精准度高,调用次数少(仅 map 阶段,无 reduce),速度快、成本低。劣势:无法融合多个文本块信息,若最优文本块信息不全,回答会遗漏细节。

3 种 chain_type 核心差异表

类型核心逻辑优势劣势适用场景
map_reduce多块并行生成→汇总多信息融合,全面性强调用多、成本高、速度慢需多来源佐证的复杂问题
refine单块初始→多块迭代优化细节丰富,逐步完善依赖顺序、速度较慢需深度解析的细节类问题
map_rerank多块生成→评分选最优精准度高、速度快、成本低无法融合信息,可能遗漏细节需快速获取精准答案的简单问题

四、实战优化建议

  1. 文本分割参数调优chunk_size并非固定值,若文档多为短句(如新闻),可设为 300-400;若为长段落(如论文),可设为 600-800,需结合实际文档测试。
  2. 检索器优化:默认检索器返回 5 个文本块,可通过retriever = db.as_retriever(search_kwargs={"k":3})调整数量,k 值越小速度越快,k 值越大信息越全。
  3. API Key 安全:实际项目中不要硬编码 API Key,可通过环境变量(如os.getenv("DASHSCOPE_API_KEY"))或配置文件加载。
  4. 记忆类型选择ConversationBufferMemory会保存全部对话历史,若对话轮次多,可换ConversationBufferWindowMemory(只保存最近 N 轮),减少 token 消耗。

五、总结

RAG 的核心价值是 “让大模型结合私有知识回答问题”,而 LangChain 已封装好从文档加载到对话生成的全流程工具,降低了开发门槛。选择chain_type时,需根据 “精准度需求”“成本预算”“速度要求” 综合判断:

  • 追求全面性:选 map_reduce
  • 追求细节丰富度:选 refine
  • 追求速度与精准平衡:选 map_rerank

PDF文档内容:

罗浮宫(法语:MuséeduLouvre,英语 /ˈluː v(rə)/ ),正式名称为罗浮博物馆,位于法国巴 黎市中心的塞纳河边,原是建于12世纪末至13世纪初的王宫,现在是一所综合博物馆,亦 是世界上最大的艺术博物馆之一,以及参观人数最多的博物馆,是巴黎中心最知名的地标。 罗浮宫的建筑物始建于1190年左右,并在近代曾多次进行扩建,今天所见的模样则一个巨 大的翼楼和亭阁建筑群,主要组成部分的总面积则超过60,600平方公尺(652,000平方英尺), 馆内永久收藏则包括雕塑、绘画、美术工艺及古代东方、古代埃及和古希腊罗马等7个分类, 主要收藏1860年以前的艺术作品与考古文物,罗浮宫博物馆在1793年8月10日开幕起正 式对公众开放,平均每天有15,000名游客到此参观,其中65%是外国游客。 位置 罗浮宫与杜乐丽花园的卫星照片 罗浮宫博物馆位于巴黎市中心的卢浮宫内,位于塞纳河右岸,毗邻杜乐丽花园。最近的两个 地铁站是皇家宫-罗浮宫站和卢浮-里沃利站,前者有直达地下购物中心 CarrouselduLouvre 的地下通道。 在1980年代末和1990年代大改建之前,罗浮宫共有好几个街道入口,目前大部分入口已经 永久关闭。自1993年以来,博物馆的正门位置位于拿破仑广场金字塔底下的地下空间,游 客可以从金字塔本身、旋转阶梯处连接到博物馆的通道。 博物馆的参观时间随著时代的推移而变化。自18世纪开放以来,只有艺术家和来自外国的 观光游客享有特权参观,这项特权后在1850年代才消失。当博物馆从1793年首次开放时, 新历法法国共和历规定了“十天周”(法语:décades),其中前六天为艺术家和外国人访问, 后三天为将军访问,民众仅能在最后一天参观,后在在1800年代初期在恢复七天周后,民 众在每周只有4小时的时间能在罗浮宫参观,周六和周日则是缩减至下午2点至下午4点期 间参观。 从1824 年开始的一项新规定允许公众在星期日和节假日时参观,然而其他日子只对艺术家 和外国游客开放,这种情况到1855年才发生了变化,博物馆更改成除了周一外全天向公众 免费开放,直到1922年才开始收费。 当前自1946年开始,罗浮宫除了在周二公休和特殊假日外,通常向游客全面开放参观,内 部允许使用照相机和录像机,但禁止使用闪光灯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值