恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
从上传PDF问答到真正的RAG知识库:解析、检索与评测实战
首页
资讯中心
/
从上传PDF问答到真正的RAG知识库:解析、检索与评测实战
从上传PDF问答到真正的RAG知识库:解析、检索与评测实战
发布时间:2026/9/4 16:33:20
实际项目里一种很常见的认知偏差是只要界面上有一个“上传 PDF”按钮问答效果不错就认为已经做了一个 RAG 知识库。许多演示场景都把 PDF 拖进对话框然后问“这份文档的主要观点是什么”模型回答得很流畅。换到生产环境用户上传几十份合同、政策或设备手册问题往往带页码、条款、排除条件甚至跨文档对照结果回答开始含糊、引用错误、找不到重点。问题未必出在大模型参数上而是处理链路根本没有把 PDF 当成一个可检索知识库来建设。要理解这个问题需要区分两个概念一种是把 PDF 内容直接注入到大模型上下文里另一种是先用文本解析、切片、向量化、检索等手段把 PDF 变成随时可以被精准调取的资料片段再让大模型基于片段回答。前者可以叫“长文本直传问答”后者才符合 RAG即检索增强生成的核心思想。接下来从最典型的实现开始拆解。1. 为什么“把 PDF 扔进对话框”能回答问题但很难用1.1 页面式上传问答的实现方式与限制很多团队在上线 PDF 问答功能时先做的是“上传文件后读取全文再拼到 Prompt 里”。代码结构通常类似下面这样# 示意代码用于说明“直传全文”的做法 def ask_with_full_pdf(pdf_path: str, question: str, llm): pages read_pdf_pages(pdf_path) # PDF 可能存在多页直接拼接全部文本 content \n\n.join(page.get_text() for page in pages) prompt f 请阅读以下材料并回答问题。 材料正文 {content[:80000]} 问题 {question} 回答要求 1. 如果材料中没有依据请明确说“材料未提及”。 2. 不要编造材料中不存在的内容。 return llm.invoke(prompt)这种写法确实能在简单场景下得到看起来合理的回答。原因是PDF 内容已经作为上下文进入大模型大模型本身具备很强的信息抽取和归纳能力面对“文档讨论了什么”“有什么结论”这类问题时它可以靠整体阅读完成回答。但这种方法有几个天然限制。第一它受上下文窗口约束PDF 一旦超过窗口长度就需要截断而截断很容易丢掉答案所在的中段。第二它只能处理“单份 PDF”如果要跨 20 份合同查同一类条款Prompt 会迅速超出长度。第三它对“答案在第几页”这类来源问题无能为力因为模型只能看到拼接后的长文本缺少片段定位能力。第四每次输入相同长度的问题都会消耗同样的 Token成本会随文档页数线性增长。从工程视角看这种方案更像“长上下文问答”和 RAG 之间还有一段明显的距离。1.2 RAG 的真实工作流程不是“全文注入”而是“先检索后生成”RAG 的全称是 Retrieval-Augmented Generation检索增强生成。用一句通俗的话描述系统收到用户问题后先从已经建好的知识库索引中找出与该问题最相关的一批片段再让大模型只基于这些片段来生成答案。一个完整的 RAG 流程至少包含以下阶段文档解析从 PDF 中提取文本、表格、图片中的信息并清理无用内容。文本切分把长文档拆成一个个语义相对完整的小块即 chunk。向量化把每个 chunk 通过 embedding 模型转换成向量也叫 dense vector search 的基础。索引存储把向量和原始文本、元数据一起存入向量数据库或搜索引擎。查询召回用户提问时把问题向量化在索引中执行相似度检索。重排与过滤对召回结果做二次排序筛掉无关片段。生成把最终选中的片段拼进 Prompt让大模型据此组织答案。RAG 的命名重点在“检索”。它并不要求把整份 PDF 塞进模型而是要先把文档资源拆成能被“查询”的单元让模型在回答时只依赖与该问题强相关的内容。这才是“知识库问答”与“单文档长文本问答”的本质差别。1.3 直传全文与 RAG 检索的适用场景对比判断维度把 PDF 全文直接交给大模型用 RAG 方式构建知识库文档数量适合单份、短文档适合多份、长时间累积的文档集上下文成本每次问答都要处理全文Token 消耗高每次只处理 Top K 个片段更省答案溯源很难给出准确页码或章节可通过 chunk 元数据返回来源跨文档问题几乎不可行窗口不够可以跨文档检索后综合回答文档更新需要重新拼全文只需要更新新增或变更的切片实现难度简单、演示上手快复杂依赖解析质量和检索效果典型场景小册子速览、单文档总结合同条款查询、法规知识库、设备手册问答需要注意这张表讨论的是“要不要用 RAG”不是判断某种方案完全不能用于生产。如果业务场景只是让用户上传一份几十页的 PDF要求做全文总结或简介生成直传方式反而更直接。但一旦进入“从大量文档中检索特定答案”的场景RAG 才是更合理的工程路线。1.4 为什么演示阶段看不出问题用过“上传 PDF 问答”演示的人都会发现模型在演示时表现得很好。原因很简单演示者通常问的是“概括一下这份文档”“这份材料核心讲了什么”这些问题不需要精确到具体条款即使模型遗漏一段内容用户也未必察觉。生产问题往往截然不同。用户会问“这份报价单里的维保费用在哪个表格和上一版相比变化了多少”也可能问“供应商在保密义务条款中列出的例外情形是否覆盖法律要求”。这些问题对检索粒度和来源一致性要求很高。如果只有整文件注入没有切片索引模型即使回答正确也找不到支撑证据如果某个关键片段被截断模型会无意识补全产生不可控的幻觉。一个可靠判断方法是当用户要求“请按第 3 页的表格回答”或“引用原文对应条款”时系统能否给出稳定且可解释的结果。如果做不到说明系统还没有真正把 PDF 转化为可检索的知识库。2. PDF 本身不是知识库解析与切片比模型选型更影响效果2.1 PDF 不是按“段落流”设计的文本文件在构建 RAG 前最容易低估的步骤是 PDF 解析。许多开发者的默认假设是PDF 和 Word 一样可以直接抽出完整、连续的文本抽出来就可以直接切分和向量化。实际情况远比这复杂。PDF 是一种按页面布局组织的文档格式。文件中可能存在文字层也可能没有文字层有文字层时文字对象的位置不一定符合视觉阅读顺序存在多栏排版时按坐标顺序读出来的文本可能把左栏和右栏混在一起表格和插图在 PDF 中是图形对象单靠get_text()类接口经常会丢失行列对应关系。扫描件则更特殊。扫描 PDF 本质上是一组页面图片没有可选择、可复制的文字层必须先做 OCR。如果跳过 OCR后续切分和向量化拿到的都是空内容知识库自然无法召回任何答案。举个例子同样一份 PDF如果是从 Word 导出的电子文档解析后文本质量通常较高如果是扫描仪生成的图片型 PDF则需要 OCR 模型介入如果原文件包含多栏论文或复杂表格还需要版面分析模型辅助恢复阅读顺序。文档类型不同RAG 链路的前置处理方式也应不同。2.2 文档治理链路要先于向量化进入 embedding 之前PDF 需要经过一条“文档治理链路”通常包括识别文档类型电子型 PDF、扫描型 PDF、混合型 PDF。抽取文本电子型直接解析扫描型走 OCR。版面恢复识别标题、正文、表格、页眉页脚、栏顺序。数据清洗去掉页码、页眉、页脚、重复水印和导航文字。结构抽取保留章节目录、标题层级、列表和表格结构。元数据补充记录来源文件名、章节标题、页码、页内位置。如果没有这一层治理常见后果是用户问“第 5 页的表格说明了什么”系统检索到的内容里没有页码用户问“合同中的结算方式”系统召回的 chunk 被表格换行截断内容残缺用户问“这个 PDF 图片里的审批意见是什么”系统因为没做 OCR 而完全找不到。因此高质量 RAG 的起点不是 embedding 模型而是“能不能把 PDF 变成结构清晰、语义完整的文本”。这一步决定检索上限后面的向量化只会在该上限之内工作。2.3 切分不是单纯按字数截断而是按语义单元组织很多团队的第一个版本会这么切分 PDF# 不推荐的固定字符切分 chunks [content[i : i 800] for i in range(0, len(content), 800)]这种切分方式在连续正文里也许还能用但一旦遇到表格、标题、条款列表就会把语义完整的内容拦腰截断。比如一份采购合同中的“付款方式”小节中间有一个表格。固定 800 字符切分可能让表格的前半段进入上一个 chunk后半段进入下一个 chunk检索时无论匹配到哪一块都缺少完整上下文。推荐的思路是“优先按文档的标题和章节边界切分其次再按段落最后才按字符数量截断并增加重叠。” 可以参考下面的示意逻辑# 围绕文档结构切块下面代码用于说明思路 def split_preserving_sections(blocks, max_tokens800, overlap_tokens80): chunks [] current_section current_lines [] for block in blocks: if block.kind in (h1, h2, h3): if current_lines: chunks.append(build_chunk(current_section, current_lines)) current_lines [] current_section block.text else: current_lines.append(block.text) if current_lines: chunks.append(build_chunk(current_section, current_lines)) return chunks理想情况下一个 chunk 应该是一段可以被独立理解的文字。它既不能短到只包含半句话也不能长到把无关内容混在一起。切分还需要和检索指标联动验证而不是凭感觉拍一个固定值。2.4 “页面”不应该成为默认切分单元有些项目会直接把 PDF 的每一页做成一个 chunk。单页内容看起来像是一个天然边界但它也有明显问题。PDF 分页位置由排版决定与语义边界不一定一致。一个表格可能跨两页一个条款可能从页底延续到下一页顶部如果按页切割这两部分会被分到不同的 chunk检索时无法同时命中。页面更适合作为“元数据”存在而不是作为唯一的切分单元。比较稳妥的做法是在解析和切片时记录每个 chunk 对应哪些页码检索结果返回后把页码作为引用来源展示给用户同时允许用户点击跳转到 PDF 原页面。这样既保留版式可读性又避免让页面边界破坏语义完整性。3. 让 PDF 知识库具备真正的 RAG 能力最小链路要这么搭3.1 从“读全文”到“查片段”整体链路设计真正可用于生产的 PDF RAG 流程建议按下图顺序落地但实际操作中每个环节都可以替换成对应技术栈PDF 上传 - 文档解析与 OCR - 文本清洗与结构识别 - 切片并记录元数据 - embedding 向量化 - 写入向量库/搜索引擎 - 用户问题改写与向量化 - 混合检索 - 重排 - 组装上下文与生成这里每一步都值得单独测试。最容易出现问题的是“解析结果不可见”和“检索结果不可见”。建议尽快把中间产物暴露到调试界面比如能查看某一个 PDF 被切成了多少 chunk、某个问题实际召回哪些片段、每个片段的相似度是多少。否则上线后很难判断错误是来自解析、切分、召回还是生成。3.2 混合检索不要只做向量搜索很多早期 RAG 项目只做了向量检索也就是把 query 转成向量再到向量库里找语义最接近的 chunk。这种 dense vector search 对“同义改写”很有效例如用户问“多少钱”文档里写的是“费用金额”两者仍可能被匹配。但向量检索对精确词并不总是友好尤其是合同编号、PID、型号、身份证号这类必须逐字一致的信息。实际工程中更推荐“混合检索”同时执行向量检索和关键词检索再把两类结果合在一起。关键词侧可以使用 BM25 类的稀疏检索能力向量侧负责语义相似最后通过加权或 RRF 融合排序。可以参考下面的融合思路RRF 融合 score 1 / (k rank_vector) 1 / (k rank_keyword) 加权融合 score alpha * vector_score (1 - alpha) * keyword_scorealpha的取值需要根据业务调。如果文档术语很统一比如内部制度全文使用固定名称关键词权重可以高一些如果资料里有大量口语表达或用户提问很随意向量权重可以高一些。上线前要在真实问题上比较“纯向量”“纯关键词”“混合检索”三种方式的效果而不是默认选一种。3.3 重排是为了补检索的最后一公里向量检索一般先返回几十个候选片段称为 Top 50 或 Top 100但最终放到 Prompt 里的只能是 3 到 6 个且必须有强相关性。这里通常会加一次重排。重排模型将 query 和每个候选片段一起打分计算出的相关度比单纯 embedding 余弦相似度更适合排序任务。重排可以显著改善一个问题候选片段“看起来包含类似关键词但并不是真正回答用户问题”。向量检索擅长找候选重排模型擅长从候选中找到更准确的片段。两者配合才能减少错误内容进 Prompt 的概率。3.4 组装 Prompt 时不要丢掉来源当系统已经能从知识库中召回若干片段生成环节也需要有约束。一个推荐做法是把检索到的 chunk 原始文本与元数据一起拼入上下文要求模型只依据这些片段回答并在答案中说明引用来源。def build_rag_prompt(question, retrieved_chunks): context_lines [] for index, chunk in enumerate(retrieved_chunks): source f[{index 1}] 来源{chunk.title}第{chunk.page_num}页 context_lines.append(source \n chunk.content) context_text \n\n.join(context_lines) prompt f 请使用检索材料回答问题。 如果检索材料不充分请直接回答“根据已有资料无法确定”。 引用时请标注来源编号如 [1]。 材料列表 {context_text} 问题 {question} return prompt该设计的关键约束有两个一是要求模型在资料不足时“拒答”而不是猜测二是强制模型在引用时给出来源编号方便校验答案是否忠实于材料。实际业务中还可以继续加入“如果模型答案与材料冲突以材料原文为准”等规则。3.5 向量库选型参考向量库并非越复杂越好选型要看团队基础设施、数据量和运维能力。存储方案适用场景主要特点Faiss小规模原型单机向量检索需自行管理持久化pgvector已在用 PostgreSQL 的团队复用 SQL适合中低并发Milvus / Qdrant大规模专用向量库功能全支持过滤、分布式运维成本更高Elasticsearch / OpenSearch想同时做词法检索和向量检索适合混合检索有成熟运维生态选型原则建议是如果明确知道数据量不超过百万级且团队已有 PostgreSQL可以先用 pgvector 跑通如果检索结果要求复杂的元数据过滤或并发访问很大再引入专业向量库。索引只是 RAG 的一个组件不应该让它成为前期唯一焦点。3.6 最小链路完成后怎么验证“真的是 RAG”跑通最小链路后可以用三个问题做自测这份 PDF 有 200 页系统回答时是不是只用了少量片段而不是拼入全文用户追问“你在第几页看到的依据”系统能否返回页码。把一个不属于该知识库的问题抛进去系统能否回答“没有找到依据”。如果这三个自测都能稳定通过说明你已经把上传 PDF 从“全文注入”迁移到了“检索增强生成”。如果做不到下一步优先检查检索而不是生成。4. 检索结果决定答案质量RAG 评测要分开看两层4.1 没有评测集调参就没有方向RAG 项目最怕“只在一个问题上优化”。很多人会针对当前测试文档反复调整 chunk size发现一个固定问题回答好了另一个问题又变差。原因是缺少一份结构化的评测集。评测集不需要一开始就很大但必须覆盖典型业务问题类型。对 PDF 知识库问答建议包含单点事实题某份文档中的具体数值、日期、人名。多段综合题答案分布在同一文档的不同页。跨文档题答案需要综合多份 PDF。约束条件题问题包含否定条件、排除条款、时间前提。无答案题知识库里根本没有对应资料。引用核对题对已有回答校验页码和原文是否匹配。可以把评测集放在一个 JSON 文件里方便程序自动跑分[ { question: 该供应商合同中的维保响应时间是几小时, expected_chunk_ids: [contract-a-p12-t3], answer_points: [2小时内], source_pages: [12] }, { question: 2023版制度是否允许员工自行采购办公电脑, expected_answer: 不允许, source_pages: [8] } ]这里的expected_chunk_ids用于评测“检索是否命中正确片段”answer_points用于评测“最终回答是否包含关键信息”。如果只测最终回答会分不清失败来自检索还是来自大模型生成。4.2 检索层指标与生成层指标要分开看RAG 评测不能只看大模型回答是否“顺”而要把指标拆到两层。层级指标含义检索层RecallK标准答案对应的片段是否出现在前 K 个召回结果中检索层Hit Rate有多少测试问题的正确答案片段被成功召回检索层MRR第一个正确答案在排序中排多靠前检索层NDCG排序质量正确处理相关片段的位置权重生成层Faithfulness模型回答是否忠实于检索材料没有额外编造生成层Answer Correctness回答是否包含黄金答案中的关键信息生成层No-Answer Precision无答案问题时模型是否拒绝作答在实践中建议先看检索层指标。如果 Recall5 很低说明模型没拿到正确答案再优化 Prompt 也没用。如果检索层指标高但生成层正确率低才需要检查 Prompt、引用约束和重排策略。RAG 测评的具体做法不是“让大模型给自己打分”这么简单。即使引入大模型自动判分也必须有少量人工标注样本作为基准否则评测过程本身会引入新的错误。建议先标注 30 到 100 条问题优先保证测试集覆盖真实业务问题再迭代自动评测脚本。4.3 典型“检索失败”原因问题不在模型在切片和召回假设用户提问“这个 PDF 里违约金比例是多少”但系统回答错误。从评测角度可能原因包括PDF 扫描件未 OCR文档里根本没有可检索文本。切片把违约金条款和表格拆分成了两个 chunk召回时只命中其中一个不完整片段。向量检索只匹配到语义近似的其他条款例如把“赔偿金”当成了“违约金”。Top K 值太小正确片段排名在 K 之后被过滤。重排模型没有把正确片段排到最前面。多轮对话中用户上一个问题干扰了检索 query 的向量化。遇到这类问题时先打印出实际问题召回的前 10 个片段人工判断正确片段是否被召回。如果没有问题在索引和检索如果有问题在重排和生成。这个排查顺序能节省大量盲目调参时间。4.4 用“删除测试”判断模型是否依赖检索材料一个简单但有效的验证方式是删除或混淆正确答案片段观察模型是否还会给出原先答案。如果模型在缺少关键片段后仍然自信回答说明 Prompt 中的“只基于材料回答”约束没有生效或者模型上下文里残留了历史信息。在正式评估中可以把某些问题的正确答案片段从切片库中临时移除让系统进入“知识库中不存在该答案”的状态。正确行为应当是明确拒答或说明资料不足。如果模型依然编出看似合理的答案说明系统还需要在 Prompt 和输出约束上继续收敛。5. 上传 PDF 类 RAG 的常见误区和排查链路5.1 六个高频误区越早避开越省时间误区一所有 PDF 都可以直接抽取文本。实际项目中扫描件占比往往被低估尤其是用户上传的合同或票据。没有 OCR 的处理链路对这些文件几乎无效。误区二chunk 越小向量越准。chunk 过小会让单块信息不完整尤其影响表格和条款类内容。回答需要上下文时模型经常因为缺少周围段落而答错。误区三切分越精细越好。过度切分会导致同一个问题需要跨多个 chunk 才能拼出答案检索时反而容易遗漏后半段。合理的切片粒度需要结合业务问题测试。误区四去掉标题和页码可以省 Token。标题往往是最重要的上下文页码是来源追踪的依据。为了省 Token 删掉它们检索质量会整体下降。误区五向量检索能解决所有匹配问题。文档中大量出现型号、编号、政策发文号这些精确匹配需要关键词检索参与。纯向量方案对这些词的高频失效很常见。误区六模型回答不好就调 Prompt。在很多失败案例里模型没有回答好是因为召回的片段本来就是错误或残缺的。此时调 Prompt 只是让模型在错误材料上组织得更流畅。5.2 排查链路从现象倒推根因当系统回答不符合预期时建议按下面的顺序排查。顺序检查点查看方式1用户问题是否能在原文中找到答案对照 PDF 原文与人工预期2原始文本抽取是否正确把解析结果导出为纯文本或 JSON 查看3chunk 是否包含完整答案在调试界面搜索关键词定位 chunk4检索是否召回正确 chunk打印 Top K 召回结果和分数5重排后是否保留正确 chunk对比重排前后的排序差异6最终 Prompt 是否包含正确依据查看实际送入模型的内容是否被截断7生成结果是否忠实于依据逐句对比答案与原文定位幻觉这里最关键的检查习惯是不要只从最终答案去猜而要从链路里“看见中间产物”。解析、切分、向量化、召回、重排、生成每一步都应该留下可观测数据。生产系统如果没有日志记录召回片段和引用来源上线后几乎无法定位问题。5.3 当多个文档结构差异大时按文档类型分通道处理很多 PDF 知识库的文档来源不统一有的是制度文件有的是产品手册有的是扫描版合同。把它们全部丢进同一个解析和切分流程效果一定不稳定。建议先按文档结构分类单栏正文型按章节目录和段落切分解析成本低。多栏论文型先做版面分析恢复阅读顺序。表格密集型优先处理表格结构保留行列关系。扫描图片型走 OCR 通道。图纸、发票、图片型需要多模态模型或专用识别模型不能只靠文本抽取。这并不意味着每类文档都要完全定制但至少要区分“文本 PDF”和“扫描 PDF”两条通道否则后续检索会持续被基础解析问题拖累。6. 当文档和问题变复杂向 Agentic RAG、Ontology RAG 等方向扩展6.1 从 Naive RAG 走向 Advanced RAG朴素 RAG 的做法是“用户一个问题 - 一次检索 - 一次生成”。它适合单跳且相对独立的问答。例如用户问“这个型号的额定功率是多少”系统查一次就能得到答案。但生产问题越来越复杂。用户可能先问“这些设备里哪些符合项目准入条件”再追问“它们各自的维护成本和备件周期”。这类问题依赖多次检索、条件过滤和多步推理。于是 RAG 链路开始引入查询改写、子查询拆分、元数据过滤和重排形成 Advanced RAG。6.2 Agentic RAG让模型像助手一样决定搜索路径Agentic RAG 是目前比较活跃的方向它把大模型从“只做一次检索后生成”的角色变成“可以规划检索动作”的智能体。面对问题时模型可以先判断是否要做关键词检索再决定是向量检索、全文检索还是调用结构化数据接口发现结果不足时它还可以改写提问、查询上一轮上下文或者继续检索其他文档。以“对比两份 PDF 中的报价差异”为例Agentic RAG 的流程大致是先检索第一份 PDF 的报价页提取金额再检索第二份 PDF 的报价页提取金额最后汇总差异并生成结论。如果让朴素 RAG 一次检索完成很难同时把两份文档的关键页都召回到 Prompt 中。Agentic RAG 带来的额外代价是可控性降低。模型自己决定执行多步检索可能出现检索次数过多、调用链不稳定、Token 成本上升等问题。因此在生产落地时需要给 Agent 设定最大检索轮次并对中间检索行为做日志记录。6.3 Ontology RAG 和 Graph RAG适合实体关系密集的资料当知识库里全是合同、制度或技术规范时很多答案依赖“实体之间的关系”例如供应商、项目、条款、风险的关联。这时单纯靠文本相似度检索往往不够因为用户问的是“某供应商在多个项目中是否涉及同一类风险”答案分散在不同 PDF 中。Ontology RAG 强调在使用检索之前建立一套领域本体把业务概念、实体类型、属性和关系显式定义出来。例如“合同”和“供应商”之间是“签约关系”“供应商”和“违例记录”之间是“被记录关系”。图数据库或关系索引保存这些实体和边RAG 查询时先沿着关系找到候选文档再用文本片段组织答案。这种做法的价值在于它能把“文档里的文字”提升为“业务中的知识结构”帮助模型回答多跳问题。但门槛也比较高需要梳理业务本体、维护实体抽取、设计方案处理实体更新。对于小规模上传 PDF 问答不建议一开始就引入只有当实体关系类问题成为主要需求时再考虑。6.4 技术选型建议从简单方案起步用问题倒推升级技术路线不能因为热门而盲目升级。一个实用建议是先用朴素 RAG解析 PDF、切片、向量化、混合检索、生成。做评测集收集真实用户问题标出召回失败和回答失败。根据失败类型决定是否升级如果问题集中在单步检索不精准先优化切分和重排如果集中在跨文档、多跳、实体关系再引入 Agentic RAG 或图增强。每升级一次都重新跑同一套评测集看指标是否真的提升。这样能把“RAG 很复杂”的焦虑转换成“哪些问题需要什么能力”的工程判断。7. 把“上传 PDF 问答”升级成“PDF 知识库”时可复用的落地清单7.1 PDF 来源清理清单在把这些文件交给系统前先对文档本身做一次盘点检查项操作建议文件是否为扫描件是则先接入 OCR或确认多模态识别通道文本层是否可复制抽 3 页随机文本检查乱码、缺空格、顺序错乱是否有页眉页脚水印切分前统一清洗避免污染向量是否存在多栏排版确认是否有版面分析防止左右栏交错表格是否需要行列语义对表格保留结构化信息不要简单转成纯文本文档标题和版本号写入元数据检索和排序时保留文档版本信息7.2 切分与索引参数调试清单切分参数并非一次确定建议在首批文档中抽取典型文件做小规模测试后确定。优先以 H1 到 H3 标题为边界建立切片。单个小节过长时按段落继续拆分段落内部保留句号边界。文本切片可设置 400 到 800 token 的初始范围并设置 10% 至 20% 的重叠。每个 chunk 至少保留来源文件、标题、页码三个字段。表格在无法结构化时同样需要切到独立的 chunk并注明“表格”类型避免和正文互相打断。写入向量库后需要用测试问题做一次实际召回而不是只看入库条数。7.3 发布前手动验收清单开发环境和生产环境的验收标准差异很大。开发环境跑通一次完整链路并不等于生产可用。发布前建议人工过一遍以下场景上传一份 50 页以上、含多级标题和表格的 PDF观察解析结果。上传一份扫描版 PDF确认 OCR 后能检索到文字。询问包含精确编号的问题验证混合检索是否能召回原文。询问故意与知识库无关的问题确认系统会拒答而不是编造。连续问同一话题的多个问题检查多轮对话时是否被无关历史上下文干扰。删除或更新一个 PDF 版本确认旧的 embedding 不会被继续检索到。开启日志记录每一次请求召回哪些 chunk、模型输出哪些引用。7.4 上线后重要监控项系统上线后不要只观察“平均回答是否满意”。建议持续跟踪以下数据检索命中率通过用户对引用来源的点击或日志中是否成功返回引用片段判断检索是否有效。拒答率系统回答“无法确定”的比例是否合理过低可能说明模型过度自信。引用可核对率抽样比对模型答案检查每个关键结论是否能在引用 chunk 中找到原始出处。Top K 召回变化当新增 PDF 后原有问题是否出现召回漂移导致答案改变。解析失败率有多少 PDF 上传后没有产生任何可检索 chunk这个比例直接反映文档治理质量。7.5 给项目的最佳下一步如果你所在的项目已经有“上传 PDF 给大模型”的功能但尚未达到知识库标准最重要的动作不是立刻更换大模型或向量库而是先把“可检索单元”建出来。具体可以做三件事第一把 PDF 解析结果输出到一个可见界面确认内容没有被扫描件、表格和分页破坏第二建立一份包含 30 条真实问题的评测集分别记录检索命中和回答正确情况第三在前端展示来源页码和原文摘录让用户能够验证系统确实“找到了依据”。这三件事完成后再回来审视模型选型、切片大小、检索融合方式你会发现自己不再依赖运气调参而是在围绕一套可重复验证的流程做迭代。PDF 上传只是知识库的入口真正的 RAG 是从文档变成可检索、可溯源、可评估的工程能力。