乐于分享
好东西不私藏

别再把 PDF 直接丢进知识库了

别再把 PDF 直接丢进知识库了

很多人第一次做知识库问答,流程特别顺:

把 PDF 拖进去。

点一下“构建知识库”。

然后问一句:这篇论文的核心贡献是什么?

如果答案看起来还行,就觉得 RAG 跑通了。

但真正麻烦的地方,往往要到第二天才出现。

你问一个细节,它答偏了。

你问一个实验设置,它把两篇论文混在一起。

你让它给出处,它给了一个看起来相关、但其实不支撑结论的片段。

这时候不要急着换模型。

很多 RAG 的问题,不是发生在“生成答案”的最后一秒,而是发生在前面几步:PDF 解析、文本切片、元数据、召回排序、证据引用

这篇不讲宏大的 RAG 原理。

只讲一套研究生自己能用的排故工作流。

Part 01
01 先记住一句话:RAG 的失败,通常不是“不会答”,而是“没拿到该看的证据”

很多人调 RAG,只盯着最终回答。

这个习惯很危险。

因为最终回答只是结果,不是病因。

一个知识库问答系统,至少要经过五步:

  • PDF 被解析成文本;
  • 文本被切成 chunk;
  • chunk 带着元数据进入向量库;
  • 查询时召回 top-k 片段;
  • 模型基于片段组织答案。

任何一步出问题,最后都会表现成“模型答得不准”。

但它们的处理方式完全不同。

如果 PDF 解析把表格读坏了,你调 prompt 没用。

如果 chunk 太碎,关键上下文被切断,你换更贵的模型也只是让它更有礼貌地猜。

如果召回 top-k 里没有正确段落,模型再强也只能在错误材料上写作文。

所以做 RAG,第一件事不是追求“答案像不像人写的”。

第一件事是追问:

它回答这个问题时,到底看见了哪几段原文?

Part 02
02 切片不是越小越精准,也不是越大越保险

切片是最容易被低估的一步。

LlamaIndex 文档里,SentenceSplitter(chunk_size=1024, chunk_overlap=20) 是一个很典型的示例配置;它也说明 node parser 会把文档拆成 node,并继承父文档的 metadata。

这个细节很重要。

因为 chunk 不是“随便截一段文本”。

它应该同时保留三件东西:

  • 当前段落本身;
  • 它来自哪篇文档、哪一页、哪个章节;
  • 它前后一点点上下文。

太小的问题是:一句话可能被切出来了,但它对应的实验设置、变量定义、表格标题都没了。

太大的问题是:召回命中了一大块文本,里面有多个主题,模型容易挑错重点。

我更建议研究生先用一个保守起点:

材料类型
起始切片建议
overlap 建议
重点检查
论文正文
700-1200 tokens
80-150 tokens
方法段和实验段是否断裂
综述文章
900-1500 tokens
100-200 tokens
小标题是否保留
课题组网页
400-800 tokens
50-100 tokens
导师、方向、项目是否串行
表格/清单
尽量按行或表块
少量 overlap
表头不能丢

这不是标准答案。

它只是一个能开始排故的参数区间。

真正的判断标准只有一个:召回出来的 chunk,能不能单独支撑答案里的那一句话。

Part 03
03 元数据不是装饰,它决定你能不能回到原文

很多知识库做不出专业感,不是因为没有向量库。

而是因为每个 chunk 都像无名小卒。

只有正文,没有来源。

只有内容,没有页码。

只有相似度,没有章节位置。

这样一来,答案即使对了,你也很难验证。

最低限度,建议每个 chunk 都带这几类 metadata:

  • doc_id
    :文档唯一编号;
  • title
    :论文或资料标题;
  • year
    :年份;
  • source_type
    :论文、网页、报告、导师主页;
  • page
    :页码或网页段落位置;
  • section
    :章节名;
  • chunk_id
    :该文档内部的切片编号。

如果是做导师库,还可以加:

  • school
  • department
  • research_area
  • lab_name
  • homepage_url

这些字段看起来像工程细节,但它们会直接改变内容质量。

没有 metadata,你只能问“它说了什么”。

有 metadata,你才能问:

只基于 2023 年之后的论文回答。只看方法章节,不要混入 introduction。给我列出同一导师主页里出现过的方向关键词。每个结论后面标出文档、页码和 chunk_id。

这时知识库才不像一个会背资料的聊天框,而像一个可以追溯的科研助手。

Part 04
04 召回不要只看 top-k,要看“错误答案是怎么被召回出来的”

很多教程会告诉你设置 top_k=3top_k=5top_k=10

但真正调系统时,只改 top-k 很粗。

你要看的是召回列表本身。

建议每次测试,都把下面这张表记录下来:

问题
应该命中的来源
实际 top-5
正确片段排名
错误原因
某方法用了什么数据集
论文实验章节
命中 introduction
未进入 top-5
query 太泛
某导师方向是什么
导师主页方向栏
命中新闻稿
第 4
metadata 缺失
某实验指标为何下降
ablation 表格附近
命中结论段
第 2
表格解析坏

这张表比“感觉效果不错”有用得多。

它能告诉你下一步该调什么:

  • 正确片段没进 top-k:优先调切片、embedding、query rewrite;
  • 正确片段进了 top-k 但排得低:考虑 rerank;
  • 正确片段进了 top-k 但答案仍错:检查 prompt 和引用约束;
  • 召回片段本身读不懂:回去修 PDF 解析。

LangChain 文档里有“contextual compression”这类检索后压缩思路;LlamaIndex 也有 CitationQueryEngine 这类强调引用粒度的组件。它们背后的共同逻辑是:不要把一堆粗糙材料直接塞给模型,要让模型看到更相关、更可引用的上下文。

Part 05
05 最小可用的 RAG 测试集:不要超过 30 个问题

很多人做知识库,没有测试集。

每次调完参数,就随便问两句。

这会让你永远不知道系统到底变好了,还是只是这次问题刚好命中。

建议研究生先做一个 20-30 个问题的小测试集。

不用复杂。

按五类问题分就行:

  1. 定位型问题
    :某个定义、公式、数据集在哪里出现;
  2. 对比型问题
    :两篇论文的方法差异是什么;
  3. 证据型问题
    :哪个实验支撑某个 claim;
  4. 限制型问题
    :只允许基于某一年、某个章节、某类来源回答;
  5. 反事实型问题
    :资料里没有的信息,模型是否会承认不知道。

最关键的是第五类。

一个 RAG 系统如果只会答,不会说“不知道”,它在科研场景里很危险。

因为研究里最贵的不是少答一句。

是把不存在的证据写进开题、综述或论文。

Part 06
06 给你一套可以直接照抄的排故流程

如果你已经有一个知识库,但感觉它“不太准”,可以按这个顺序查。

第一步,抽 5 个错误答案。

不要抽你最满意的,专门抽出错的。

第二步,把每个问题对应的 top-5 召回片段导出来。

不要只看最终回答。

第三步,判断正确证据有没有进入 top-5。

没有进入,就先修检索;进入了但答错,再修生成。

第四步,检查 chunk 是否完整。

看它有没有标题、页码、表头、前后文。

第五步,给每条答案加引用约束。

例如:

你的每一句结论后面都必须给出来源编号。如果来源片段不能支撑结论,就写“资料不足”。不允许使用知识库之外的信息补全。

第六步,保留一张调参记录表。

每次只改一个变量:chunk_size、overlap、top_k、rerank、query rewrite、prompt。

不要一次全改。

一次全改,看起来很勤奋,实际上是在制造迷雾。

Part 07
07 最后:知识库不是资料仓库,是证据机器

把 PDF 扔进去,只是开始。

能不能用,取决于它能不能稳定回答三个问题:

它看见了什么?

它为什么这么答?

我能不能回到原文复核?

如果这三件事做不到,知识库再漂亮,也只是一个会聊天的资料堆。

如果这三件事做到了,它才真的能进入科研流程:

帮你读论文。

帮你整理导师信息。

帮你写开题综述。

帮你把一个模糊方向拆成可验证的证据链。

如果你最近也在搭知识库、做导师信息整理、读论文、做开题,或者想把 RAG / AI 工作流用到自己的课题里,可以来找我聊。

导师选择、课题方向、技术路线、文献工具、AI 知识库搭建,都可以。

参考资料:

  • LlamaIndex 文档:Node Parser Usage Pattern;CitationQueryEngine。
  • LangChain 文档:Text splitters;Retrieval / contextual compression 相关文档。