
很多人在做长文档问答知识库的时候,最容易踩的一个坑,就是把几十页甚至上百页的 PDF 文件直接扔进系统,按默认的 500 字符切片,然后指望大模型能给出准确答案。我在做技术规程和财务年报问答系统时,一开始也是这么干的,结果准确率连 40% 都不到。用户问第 8 章里的一个设备参数,AI 经常引用第 2 章无关的介绍,或者干脆开始胡编乱造。
长文档之所以难处理,核心原因有两个:上下文碎片化和长上下文注意力衰减。长文档里的结论往往依赖前置定义,一旦暴力切分,段落之间的逻辑联系就断了。而且大模型普遍存在“迷失在中间(Lost in the Middle)”的问题,即使模型支持 128k 上下文,如果把大量未经筛选的内容一股脑喂给它,它对中间部分的内容召回率依然会大幅下降。
要做好长文档问答,必须按照以下六个具体步骤来搭建知识库。
第一步:文档预处理与结构化解析
不要直接使用普通的纯文本提取器。比如传统的 PyPDF,它只会机械地抽取文字流,遇到多栏排版、跨页表格或者页眉页脚时,会把文字顺序全部打乱,导致向量化后的内容毫无语义可言。
1.剔除冗余干扰项:先写脚本或者配置规则,把每一页的页眉、页脚、页码和版权声明彻底清洗掉。这些重复文本如果进入向量库,会严重污染检索结果。
2.使用基于版面分析的解析工具:选用能够识别文档层级结构的工具,比如 Docling、MinerU 或者 Marker。这类工具能把 PDF 转成保留层级标题(H1、H2、H3)和 Markdown 格式的干净文本。
3.表格独立处理:长文档中最关键的数据往往在表格里。遇到跨页表格,必须强制将其合并并转成标准的 Markdown 格式,且单独作为一个独立块存储,千万不要把表格从中间切成两半。
第二步:设计适配长文档的分块策略
传统的固定长度切分(比如 512 tokens,重叠 50 tokens)在长文档场景下表现最差。因为切出来的文本块经常出现“根据上述条款”这种代词,大模型根本不知道“上述条款”指的是什么。
为了解决这个问题,目前主流有四种分块方案。我把它们的核心参数和实测效果整理成下表:
| 分块方案 | 核心切分参数 | 检索命中率 (Recall@5) | 索引与计算成本 | 适用长文档类型 |
|---|---|---|---|---|
| 固定长度分块 (Fixed) | 块大小 512 tokens,重叠 50 tokens | 约 52% | 低(单次向量化) | 结构极简单的长篇小说、新闻通稿 |
| 父子块分块 (Parent-Child) | 子块 150-200 tokens,父块 1000-1500 tokens | 约 78% | 中等(需维护父子映射关系) | 规章制度、工程标准、合同协议 |
| 上下文增强分块 (Contextual) | 块大小 300-500 tokens,附加 50-100 tokens 摘要前缀 | 约 86% | 较高(构建期需调用模型生成前缀) | 章节关联极强、逻辑跨度大的研报和年报 |
| 语义切分 (Semantic) | 按语义相似度断句,阈值设为 95 分位数 | 约 68% | 中等(需计算句子间余弦相似度) | 无明确二级标题的技术白皮书、论坛长帖 |
在工程实践中,针对 50 页以上的专业文档,推荐优先使用“父子块分块”策略。
具体操作方法是:
•先把文档按层级结构(比如按三级目录)切成 1000 到 1500 tokens 的“父块”。
•再把每个父块细切成 150 到 200 tokens 的“子块”。
•向量数据库里只对“子块”进行 Embedding 索引,但每个子块的元数据中都记录所属“父块”的 ID。
•当检索命中某个子块时,返回给大模型的上下文不是子块本身,而是它对应的父块完整内容。这样既能保证小粒度检索的高准确率,又能让大模型看到完整的段落上下文。
如果你有足够的推理预算,可以在每个切片前调用轻量模型(比如 Claude 3.5 Haiku 或 GPT-4o-mini)生成一段 50 字的全局上下文背景说明并拼在段首。Anthropic 的公开评测数据显示,这种上下文增强方法配合重排序,可以将检索失败率降低 67%。
第三步:配置双路混合检索(Dense + Sparse)
不要只用单一的向量语义检索。长文档问答中,用户经常会问具体的参数代码、合同编号或特定专业术语,例如“GB/T 19001 标准第 8.5 条要求是什么”。
纯向量检索对这类精准字符非常不敏感,很容易因为语义泛化而召回一堆不相干的质量管理泛论。
1.双路召回配置:同时启动稠密向量检索(Dense Search)与传统 BM25 关键词检索(Sparse Search)。
2.向量模型选型:向量模型选择支持长上下文和多语言的开源模型,比如 bge-m3,或者商业 API 中的 text-embedding-3-large。
3.混合算法:两路召回的结果,统一使用互惠排序融合算法(RRF,参数 k 建议设为 60)进行分数合并。
4.初始召回量:初始阶段不要只取前 3 个或 5 个,长文档检索必须放宽候选池,将初始召回数量(Top-K)扩大到 30 到 50 个片段。
第四步:使用重排序(Rerank)过滤噪音
把初始召回的 30 个片段全部直接塞进大模型,会产生两个坏处:一是大幅增加 API 计费成本,二是过多无关信息会直接诱发大模型幻觉。
因此,在召回和大模型生成之间,必须插入一层重排序机制:
1.部署 Cross-Encoder 重排模型:选用专门的重排模型,例如开源的 bge-reranker-large,或者商业化的 Cohere Rerank v3。Bi-Encoder 向量模型只是把问题和文本独立编码算余弦值,而 Cross-Encoder 会把问题和候选文本放在一起进行交叉注意力计算,语义判别准确度要高得多。
2.截断阈值控制:经过重排序后,将候选片段从 30 个严格截断到得分最高的前 5 到 7 个。如果最高分片段的重排置信度低于设定的绝对阈值(比如低于 0.35),可以直接判定知识库中无相关内容。
3.调整上下文输入顺序:把重排得分最高、最核心的文本块放在 Prompt 上下文的最前面;得分第二高的放在最后面;其余相关片段放在中间。这种“首尾分布法”能有效迎合大模型的注意力权重特征,避开长文本中间注意力偏低的问题。
第五步:组装严格受限的提示词模版
长文档问答最忌讳模型自由发挥。大模型在面对大量信息时,容易把自己的预训练知识和给定的参考文档混淆。
编写提示词时,必须制定硬性边界:
1.明确拒答指令:在 System Prompt 中明确说明:“你只能根据提供的参考文档回答问题。如果参考文档中没有明确说明,请直接回复‘参考文档中未包含该信息’,严禁根据外部常识进行逻辑推测。”
2.强制溯源标注:要求模型在输出每一个关键数据、操作步骤或结论后,必须用方括号标注引用的片段编号或页码(例如 `[文档 1,第 12 页]`)。这不仅方便人工核验,还能在生成阶段强迫模型的注意力对齐到具体的文档片段上。
第六步:建立问答评估基准并迭代
知识库建好后,不能仅凭几次回合测试就上线。针对长文档,必须建立一套标准评测集。
1.准备测试集:挑出 3 到 5 篇典型的长文档,人工或者半自动生成 50 个测试问题。问题必须分成两类:
•单点事实题(占 60%):针对某一页特定数据或定义的精确定位。
•跨章节综合题(占 40%):答案需要综合第 2 章和第 7 章的内容才能答全。
2.使用评估指标量化:借助 Ragas 或 TruLens 等评估工具,重点追踪三个核心指标:
•检索召回率(Context Recall):用于衡量真实答案所需的片段是否被包含在送给模型的 Top-K 结果里。如果这个指标低于 80%,需要回头调整第一步的解析工具或第二步的分块大小。
•生成忠实度(Faithfulness):用于衡量模型输出的内容是否有文档依据。如果出现幻觉,需要收紧第五步的提示词约束。
•答案相关度(Answer Relevance):用于衡量输出是否直接回答了用户问题,避免答非所问。
长文档知识库没有一劳永逸的默认配置。先做好结构化解析,再用父子块配合混合检索和重排序,就能解决绝大多数由于文档过长导致的回答翻车问题。整个流程跑通之后,依据评测指标不断调整分块大小和召回阈值,才能得到稳定可用的问答效果。
原创文章,作者:七点互动,如若转载,请注明出处:https://ai.qidianhudong.com/aikonw/3539.html