news 2026/4/23 17:20:35

LangChain RAG PDF 问答 Demo

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain RAG PDF 问答 Demo

LangChain RAG PDF 问答 Demo

一、任务目标

本示例实现一个基于 RAG(检索增强生成)的 PDF 问答应用:用户先导入一份 PDF,再针对文档内容提问,系统会先检索与问题相关的片段,再结合这些片段由大模型生成答案,而不是仅靠模型自身知识回答。

核心能力:文档入库 → 按问题检索相关段落 → 将检索结果与问题一起交给大模型 → 返回基于文档的答案。


二、技术栈与依赖

模块作用
Chroma向量数据库,存储文档块对应的向量,支持相似度检索
ChatZhipuAI大模型接口(智谱),用于根据「上下文 + 问题」生成回答
FastEmbedEmbeddings文本嵌入模型,将文本转为向量供检索
PyPDFLoader加载 PDF,解析为文本
RecursiveCharacterTextSplitter将长文本按块切分,便于检索与上下文限制
PromptTemplate / StrOutputParser提示模板与输出解析,组成 LCEL 调用链

三、代码结构概览

  • ChatPDF,封装「入库 + 检索 + 生成」全流程。
  • 主要方法
    • __init__:初始化大模型、文本分割器、RAG 提示模板。
    • ingest(pdf_file_path):加载 PDF → 切块 → 写入向量库 → 构建检索器与调用链。
    • ask(query):对当前已入库的 PDF 进行提问,走 RAG 链得到答案。
    • clear():清空向量库、检索器与链,便于重新加载文档。

四、逻辑说明

4.1 初始化__init__

  • 大模型:使用智谱glm-4-flash。API Key 建议通过环境变量或配置文件传入,不要写死在代码中。
  • 文本分割:块长 1024 字符,块间重叠 100 字符,在保留上下文与控制单块长度之间做平衡。
  • 提示模板:采用「系统角色 + 用户问题 + 检索上下文」的结构,要求模型严格依据上下文作答、不知道则明确说明、回答简洁(如最多三句话)。
def__init__(self):# 大模型:api_key 建议用 os.environ.get("ZHIPU_API_KEY") 等从环境变量读取self.model=ChatZhipuAI(model="glm-4-flash",api_key=None)# 文本分割:块长 1024,重叠 100self.text_splitter=RecursiveCharacterTextSplitter(chunk_size=1024,chunk_overlap=100)# 提示模板:系统角色 + 用户问题 + 检索上下文self.prompt=PromptTemplate.from_template("""<|system|> 你是专业的问答助手,需严格根据提供的检索上下文回答问题,未知内容直接回复不知道,答案最多三句话且保持简洁。 <|user|> 问题:{question} 上下文:{context} <|assistant|> """)

4.2 文档入库ingest(pdf_file_path)

  1. PyPDFLoader加载指定 PDF,得到页面级文档列表。
  2. RecursiveCharacterTextSplitter将文档切分为多个块(chunks)。
  3. 使用filter_complex_metadata过滤掉不利于向量化的复杂元数据。
  4. FastEmbedEmbeddings为每个块生成向量,并写入Chroma向量库。
  5. 基于向量库创建retriever
    • search_type="similarity_score_threshold":按相似度阈值检索;
    • k=3:最多取 3 个相关块;
    • score_threshold=0.5:仅保留相似度 ≥ 0.5 的块。
  6. 构建RAG 链:输入为用户问题;context由 retriever 根据问题检索得到;question原样传入;再经 prompt → 大模型 →StrOutputParser()得到最终字符串答案。
defingest(self,pdf_file_path:str):# 1. 加载 PDF,得到页面级文档列表docs=PyPDFLoader(file_path=pdf_file_path).load()# 2. 切分为多个块(chunks)chunks=self.text_splitter.split_documents(docs)# 3. 过滤复杂元数据chunks=filter_complex_metadata(chunks)# 4. 生成向量并写入 Chromavector_store=Chroma.from_documents(documents=chunks,embedding=FastEmbedEmbeddings())# 5. 创建 retriever:相似度阈值检索,k=3,score_threshold=0.5self.retriever=vector_store.as_retriever(search_type="similarity_score_threshold",search_kwargs={"k":3,"score_threshold":0.5},)# 6. 构建 RAG 链:context 来自 retriever,question 原样传入self.chain=({"context":self.retriever,"question":RunnablePassthrough()}|self.prompt|self.model|StrOutputParser())

4.3 提问ask(query)

  • 若尚未调用ingest(即self.chain为空),则提示「请先添加 PDF 文件」。
  • 否则对query调用self.chain.invoke(query),链内部会先检索再生成,返回基于当前 PDF 的答案。
defask(self,query:str):ifnotself.chain:return"请先添加PDF文件"returnself.chain.invoke(query)

4.4 清空clear()

  • 将向量库、检索器、链引用置为None,便于后续重新加载另一份 PDF 或重置状态。
defclear(self):self.vector_store=Noneself.retriever=Noneself.chain=None

五、RAG 数据流简述

用户问题 query ↓ retriever.invoke(query) → 从 Chroma 中按相似度取 top-k 文档块(如 k=3) ↓ Prompt 填入:context = 检索到的文本,question = query ↓ 大模型(ChatZhipuAI)根据 context + question 生成回答 ↓ StrOutputParser() 得到字符串 → 返回给用户

即:检索(Retrieval)→ 用检索结果增强提示(Augmented)→ 大模型生成(Generation),构成完整 RAG 流程。


六、使用方式示例

if__name__=="__main__":chatpdf=ChatPDF()# 先入库一份 PDF(路径按实际替换)chatpdf.ingest(r"你的PDF路径.pdf")# 针对该 PDF 内容提问answer=chatpdf.ask("请简要介绍这份文档的主要内容")print(answer)

注意:运行前需配置大模型 API Key(如智谱开放平台申请),并通过环境变量或ChatZhipuAI(..., api_key=...)传入,避免在代码或文档中明文出现密钥。


七、小结

项目说明
任务基于 RAG 的 PDF 问答:先检索再生成,答案依托指定文档
关键技术向量库(Chroma)+ 嵌入(FastEmbed)+ 检索器 + 大模型(智谱)+ LCEL 链
使用顺序ingest( pdf 路径 ),再ask( 问题 );可调用clear()后重新ingest其他 PDF

完整代码

fromlangchain_community.vectorstoresimportChromafromlangchain_community.chat_modelsimportChatZhipuAIfromlangchain_community.embeddingsimportFastEmbedEmbeddingsfromlangchain_core.output_parsersimportStrOutputParserfromlangchain_community.document_loadersimportPyPDFLoaderfromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromlangchain_core.runnablesimportRunnableLambda,RunnablePassthroughfromlangchain_core.promptsimportPromptTemplatefromlangchain_community.vectorstores.utilsimportfilter_complex_metadata# 可选:导入环境变量模块,推荐用环境变量存储密钥,更安全# import osclassChatPDF:vector_store=Noneretriever=Nonechain=Nonedef__init__(self):self.model=ChatZhipuAI(model="glm-4-flash",api_key="YOUR_ZHIPU_API_KEY_HERE")self.text_splitter=RecursiveCharacterTextSplitter(chunk_size=1024,chunk_overlap=100)self.prompt=PromptTemplate.from_template("""<|system|> 你是专业的问答助手,需严格根据提供的检索上下文回答问题,未知内容直接回复不知道,答案最多三句话且保持简洁。 <|user|> 问题:{question} 上下文:{context} <|assistant|> """)defingest(self,pdf_file_path:str):docs=PyPDFLoader(file_path=pdf_file_path).load()chunks=self.text_splitter.split_documents(docs)chunks=filter_complex_metadata(chunks)vector_store=Chroma.from_documents(documents=chunks,embedding=FastEmbedEmbeddings())self.retriever=vector_store.as_retriever(search_type="similarity_score_threshold",search_kwargs={"k":3,"score_threshold":0.5,},)self.chain=({"context":self.retriever,"question":RunnablePassthrough()}|self.prompt|self.model|StrOutputParser())defask(self,query:str):ifnotself.chain:return"请先添加PDF文件"returnself.chain.invoke(query)defclear(self):self.vector_store=Noneself.retriever=Noneself.chain=Noneif__name__=="__main__":chatpdf=ChatPDF()chatpdf.ingest(r"F:\Documents\项目大纲-AI就业班.pdf")answer=chatpdf.ask("请介绍一下这份AI就业班的项目大纲")print(answer)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 16:07:12

VibeVoice避坑指南:网页推理常见问题全解析

VibeVoice避坑指南&#xff1a;网页推理常见问题全解析 VibeVoice-WEB-UI 是微软开源的高性能TTS系统&#xff0c;主打长文本、多角色、高表现力语音合成。它不像传统TTS那样“念字”&#xff0c;而是真正理解对话逻辑、记住角色特征、控制情绪节奏——但再强大的模型&#xf…

作者头像 李华
网站建设 2026/4/23 11:48:54

基于Multisim与74LS192的智能抢答器仿真设计与实现

1. 智能抢答器设计概述 智能抢答器是各类知识竞赛和抢答活动中不可或缺的设备&#xff0c;它能准确识别最先按下抢答按钮的选手&#xff0c;并显示其编号。传统抢答器设计需要搭建实体电路&#xff0c;不仅耗时耗力&#xff0c;调试起来也相当麻烦。而借助Multisim这款强大的电…

作者头像 李华
网站建设 2026/4/23 14:43:11

Clawdbot部署教程:Qwen3-32B与Clawdbot Control UI的Token安全体系搭建

Clawdbot部署教程&#xff1a;Qwen3-32B与Clawdbot Control UI的Token安全体系搭建 1. 为什么需要这套组合&#xff1a;从零理解Clawdbot的核心价值 你是不是也遇到过这样的问题&#xff1a;本地跑着好几个大模型&#xff0c;每个都要单独开终端、记不同端口、手动改配置&…

作者头像 李华
网站建设 2026/4/23 14:48:47

DeepAnalyze实际效果:高校思政课学生发言→价值观倾向/逻辑严密性/表达感染力三指标量化分析

DeepAnalyze实际效果&#xff1a;高校思政课学生发言→价值观倾向/逻辑严密性/表达感染力三指标量化分析 1. 为什么思政课需要“看得见”的文本分析能力 高校思政课不是单向灌输&#xff0c;而是师生共建的价值观对话场。但长期以来&#xff0c;教师面对几十份甚至上百份学生…

作者头像 李华
网站建设 2026/4/23 14:41:12

电力电子技术综合实验simulink仿真模型(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

电力电子技术综合实验simulink仿真模型(设计源文件万字报告讲解)&#xff08;支持资料、图片参考_相关定制&#xff09;_文章底部可以扫码 十实验报告三相桥式全控整流电路:开环模型、定电流控制模型 挑 三相桥式有源逆变电路:开环模型、定电压模型直流输电:开环模型、闭环模型…

作者头像 李华