LangChain 学习笔记 08:一个 PDF 问答系统,真正要检查哪些环节

PDF 问答大概是最常见的 RAG Demo:上传文件,输入问题,几秒后得到答案。演示效果很直观,但“能回答一两个问题”和“能稳定处理一批真实 PDF”之间,还有不小的距离。

第 9 章把前面的 Loader、切分器、Embedding、向量库、Retriever 和问答链串到一起。这个案例最适合用来练习的,不是复制代码,而是沿着整条证据链逐段排查。

系统其实有两条流程

文档处理和用户提问不应该混在一次请求里。

索引流程:PDF -> 文本抽取 -> 清洗切分 -> Embedding -> 写入索引
查询流程:问题 -> 检索证据 -> 组织上下文 -> 模型回答 -> 返回引用

索引流程可以异步执行,并记录文档状态;查询流程只读取已经准备好的索引。否则每次提问都重新解析 PDF,不仅慢,也很难处理更新和失败重试。

PDF 不是天然干净的文本

PDF 保存的是版面。双栏排版可能把左右两列交叉读取,页眉页脚会在每页重复,表格可能只剩下一串错位文字,扫描件还需要 OCR。

所以文件加载完成后,我不会立刻生成向量,而是先抽样检查:

  • 标题与段落顺序是否正确;
  • 表格、代码和列表有没有被打散;
  • 页码能否回到原文;
  • 扫描页是否识别成功;
  • 是否混入大量页眉、页脚和水印。

这一关没有过,后面调 Prompt 基本是在错误数据上继续加工。

切分要服务于“用户会怎样问”

技术手册适合优先按章节、标题和段落切分,再用长度限制兜底。合同、制度或论文则可能需要保留条款号、表格标题和脚注关系。

每个块除了正文,最好带上文件 ID、页码、章节、块序号、文档版本和权限标签。这样检索结果既能展示来源,也能在文档更新时准确删除旧向量。

内容哈希也很有用:没有变化的块无需重复生成 Embedding,修改过的块则可以单独重建。

回答必须和证据一起返回

在线查询时,系统先检索相关片段,再把问题与资料明确分开交给模型。Prompt 至少应约束三件事:只依据给定资料;资料不足时直接说明;回答要附带可核对的来源。

我更希望接口返回结构化结果:

{
  "answer": "退款申请需要在支付后 24 小时内提交。",
  "citations": [
    {"file": "售后手册.pdf", "page": 12, "chunk_id": "manual-12-03"}
  ],
  "grounded": true
}

模型生成的引用仍要校验,不能允许它凭空编一个页码。最稳妥的做法,是让模型引用系统提供的文档 ID,再由程序映射到真实文件和页码。

五类问题比“随便问一句”更有价值

我会至少准备下面五类测试:

  1. 答案明确存在于一个块中;
  2. 答案需要组合多个页面;
  3. 用户使用同义词或简称;
  4. 文档里根本没有答案;
  5. 不同版本或页面给出冲突信息。

评估时先看正确证据有没有被召回,再看回答是否忠于证据。模型凭常识碰巧答对,不算 RAG 成功;检索命中了正确页面,模型却遗漏例外条件,也不算完成。

权限必须发生在检索阶段

多用户知识库不能先召回所有文档,再要求模型“不要泄露”。租户、部门、密级等过滤条件,应在检索前或检索过程中生效。

上传文件也属于不可信输入。除了限制类型、大小和解析资源,文档里的指令性文字只能被当作资料,不能改变系统规则。

这章给我的启发

PDF 问答看似是一个应用案例,实际上把 RAG 的每个薄弱点都暴露了出来:抽取、切分、索引、检索、生成、引用和权限。

系统质量不是由最后一次模型调用单独决定的。只有当答案能沿引用回到原页,错误能沿 Trace 找到具体步骤,这个 Demo 才开始接近一个可用产品。

posted @ 2026-08-01 08:30  Hazy_star  阅读(7)  评论(0)    收藏  举报