从领域文档到可量化知识库评测:Easy Dataset 实战指南

发布时间:2026/9/9 8:01:32
从领域文档到可量化知识库评测:Easy Dataset 实战指南 做知识库评测这件事最尴尬的往往不是模型答得不好而是你压根说不清它“哪里不好”。我们团队维护的企业知识库上线三个月每次被问“效果怎么样”只能翻出几个截图回一句“还行大部分都能答”。直到我们决定让数据说话才发现面前横着一道绕不过去的坎手里没有一套属于自己业务领域的评测集Benchmark。后来我们把自己攒的领域文档扔给 Easy Dataset 跑了一遍产出了一千多条带元数据的问答对知识库的检索命中率、答案忠实度才第一次变成可以量化对比的数字。这篇文章就把这条“从领域文档到可量化评测”的路拆开聊一聊包括工具怎么用、指标怎么算、坑在哪里以及评测结果如何转化成优化动作。这套思路适合正在做 RAG 知识库、智能客服、企业内部问答助手以及 Agent 检索工具评测的团队。只要你的知识库有底层文档就能用同样的方式建一套属于自己业务的评测基线。1. 知识库上线后最缺的不是模型是“标准答案”1.1 凭感觉验收的隐性成本很多团队对知识库的验收方式是拉几个人问几个问题觉得回答“看起来挺对”就算通过。但“看起来对”和“真的对”之间隔着一条很宽的信息鸿沟。举一个我们真实踩过的例子HR 模块上线后测试同事问“离职需要提前多久申请”系统回答“需要提前一个月”。这个说法看着没毛病业务上也常见但翻开原始制度文档里面写的是“试用期员工提前 3 天正式员工提前 30 天”。系统的回答属于“说对了一半”却在最关键的规则边界上犯了错。这种错误靠人工抽查问题列表很难发现因为抽查问题本身不够体系化也不一定能命中规则细节。更隐蔽的问题是回归风险。知识库升级了模型、改了提示词、换了分块策略之后可能 A 类问题变好了B 类问题悄悄变差了。没有一套固定的评测集和量化指标这种劣化只能等业务方投诉时才暴露。到那个时候定位问题成本就高了。所以我们在做知识库评测时第一步不是调模型而是先把“标准答案”沉淀下来。1.2 评测集为什么必须从“领域文档”来有人会问公开的评测集那么多直接用现成的行不行答案是不行。通用评测集测的是模型的通用语言能力、常识问答水平而你的知识库回答的是具体业务问题——某个流程怎么走、某条制度怎么规定的、某个系统报错怎么处理。这些问题的答案只存在于你领域内部的一堆文档里通用评测集覆盖不到。领域文档是知识库唯一的“事实源”。业务规则、操作流程、产品说明、审批条件都写在文档里。从文档反向生成评测集最大的好处是每道题都有可追溯的出处系统答得对不对不是靠人拍脑袋而是拿检索到的原文去比对。这样评测集就有了客观的参照物。一份能用的知识库评测集至少要覆盖四类问题场景流程步骤类例如“设备报修具体分几步走每步负责人是谁”规则边界类例如“哪些情况下不满足年假申请条件”数据状态类例如“系统里哪些单据状态可以撤回”操作指引类例如“批量导出订单遇到超时如何处理”这四类问题对检索和生成的要求各不相同评测时也要分维度统计不能只看一个总分。2. Easy Dataset 的处理链路把“建评测集”变成流水线2.1 五个阶段一次跑通Easy Dataset 解决的核心问题是把零散的领域文档转换成结构化的问答评测集。它把整个过程拆成了五个阶段每个阶段都有明确的输入输出可以单独调整。第一阶段是文档接入。支持常见的 PDF、Word、Markdown、HTML以及扫描版 PDF 的 OCR 识别。这一阶段最重要的不是格式解析而是保留文档的“来源身份”——每一段文字最终都要能追溯到它来自哪个文件、哪个章节。否则后续评测时发现答案有问题根本没办法回到原文去核对。第二阶段是内容清理。真实的业务文档远没有教科书干净。页眉页脚、目录页码、表格错位、重复水印这些噪声不处理掉后续生成的问题和答案都会被污染。我们第一次跑的时候有一份 40 页的 PDF 因为页眉里带着公司全称生成的问答里反复出现“这个公司如何如何”这种无意义的问题清理之后就正常了。第三阶段是智能分块。Easy Dataset 不是按固定字符数硬切而是按文档的标题层级和语义边界切并把“标题上下文”注入到每个分块里。这一步直接决定了后续检索评测的粒度。分块太粗一个问题对应多个无关片段分块太细答案被切得七零八落。这块的具体影响后面坑的部分会详细说。第四阶段是问答对自动生成。工具会对每个分块调用大模型根据配置的问题类型模板生成若干个“问题-答案”对同时记录每个问题命中的分块编号、所属文档、答案原文位置。这里有一个细节答案要求尽量保留原文表述而不是让模型自由发挥改写是为了后面算忠实度时有一个干净的对照基础。第五阶段是人工审核与导出。自动生成的结果不能直接当评测集用Easy Dataset 会产出一个抽样审核清单支持按文档来源分层抽检。审核通过后统一导出为 JSONL 格式的评测集文件包含问题、标准答案、来源文档、分块 ID、题型分类等字段。2.2 为什么选“自动生成 人工抽检”而不是纯手工整理手工整理评测集的方案我们也试过。当时组织了两名业务同学花了一周时间整理出不到 200 条问答。问题有三个速度太慢覆盖不均大家倾向于挑自己熟悉的问题写答案格式五花八门后面做指标统计时还得花大量时间清洗。自动生成加人工抽检的模式把成本结构彻底改变了。生成一千条问答对跑一次任务可能只需要一个下午人工抽检 10%再把抽检发现的高风险批量问题统一修掉。对比下来同样的规模人力投入能降到原来的五分之一而且覆盖更均匀——每个文档分块都有对应的问题不会出现某块业务完全没有评测数据的盲区。当然这个模式自己也要控制两个风险。第一是自动生成的问题质量方差大需要靠问题类型模板和抽检来兜底第二是模型生成答案时可能夹带领域文档之外的常识需要在生成提示词里做强制约束。这两块的应对方法我会在第五部分展开。3. 实操演示用 Easy Dataset 构建第一版知识库评测集3.1 环境准备与输入目录设计Easy Dataset 以 Python 包的形式发布安装很简单pip install easy-dataset运行前要准备好两样东西待解析的文档目录以及一个大模型 API 的访问配置用于问答对生成。文档目录建议按业务模块分子文件夹例如docs/ ├── hr/ │ ├── 考勤管理制度.pdf │ └── 离职办理流程.md ├── finance/ │ ├── 报销标准与流程.pdf │ └── 发票注意事项.docx └── it/ ├── 账号开通指引.md └── 系统故障处理手册.pdf按模块分目录是为了后续生成评测集时可以分层抽样确保每个业务模块都被覆盖到而不是所有问题集中在篇幅最大的那份文档上。3.2 最小可跑的配置示例在项目根目录下新建一个config.yaml这是核心配置。下面是一份我们实际用过的、可以跑通全流程的最小配置input_dir: ./docs output_dir: ./benchmark_v1 split: strategy: semantic # 语义分块按标题层级和语义边界切 max_tokens: 800 overlap: 80 generation: model: your-llm-api # 换成你的模型 API 名称 temperature: 0.2 # 低温度减少自由发挥 question_types: - fact # 事实确认类 - process # 流程步骤类 - policy # 规则边界类 - comparison # 对比判断类 questions_per_chunk: 2 review: sample_ratio: 0.1 # 按来源分层抽检 10% stratified_by: source_doc export: format: jsonl include_source: true # 导出时保留来源文档和分块 ID有几个参数值得单独说。split.strategy选semantic而不是fixed。固定字符切分虽然实现简单但会把一段完整业务规则拦腰截断生成问题时经常出现“答案不在问题所在分块”的尴尬情况。语义分块会在句号、段落、标题边界处找切点代价是分块大小不均匀但对后续评测集质量帮助很大。generation.temperature设到 0.2。问答对生成最怕模型自由发挥温度越低答案越贴近原文。这个值我们试过调到 0.8生成的答案华丽了很多但和原文对不上的地方也多了很多审核时改得想骂人。questions_per_chunk设为 2。每个分块生成 2 个问题覆盖两类题型。设得太高问题之间会很相似设得太低一个 800 字的分块只生成 1 个问答浪费了信息密度。3.3 运行命令与产物解读配置写好后直接运行easy-dataset build --config config.yaml跑完后会在./benchmark_v1下生成三个文件。questions.jsonl是所有问题及题型标注answers.jsonl是每道题的标准答案与来源信息metadata.jsonl是每个分块的元数据包括分块在原文中的位置和标题上下文。三个文件通过id字段关联。answers.jsonl中一行的结构大致如下{ id: hr-00042, category: policy, question: 正式员工申请离职需要提前多少天提交书面申请, answer: 正式员工离职需提前30天向部门负责人提交书面申请。, source_doc: hr/离职办理流程.md, chunk_ids: [hr-离职办理流程-007], ref_text: 正式员工应提前三十日提交书面离职申请…… }这条记录的ref_text比较关键它保存了答案对应的原文片段。后面算检索和生成指标时chunk_ids用来判断检索系统有没有命中正确分块ref_text用来判断生成答案有没有忠于原文。这两个字段就是整个评测能“量化”的根基。第一次跑完建议先不急着做任何优化把产出的 JSONL 文件导入到表格里按category和source_doc各做一次分布统计。这一步能快速暴露文档覆盖的盲区。我们第一版跑出来就发现 IT 模块的文档页数占 40%但生成的问题只占 15%原因是那批 PDF 有大量图片和表格文本抽取率太低。后来对 PDF 做了 OCR 增强问题分布才恢复正常。4. 评测集拿到手之后用三个指标衡量知识库真实水平评测集只是工具最终要落到知识库本身的效果量化上。我们会用同一套问答集去跑目标知识库比如 Dify、RAGFlow 或自研 RAG 流水线得到三个维度的指标。4.1 检索质量RecallK 与 MRR知识库回答问题的第一步是检索。如果检索不到正确答案所在的分块后面生成能力再强也白搭。评测检索质量时我们把评测集中的chunk_ids作为标准答案把 RAG 系统检索出的分块列表作为预测结果计算两套指标RecallK前 K 个检索结果中包含多少个“正确分块”的比例MRR第一个正确分块排在第几位的倒数实现很简单Python 几十行def recall_at_k(relevant_ids, retrieved_ids, k5): if not relevant_ids: return 0.0 top_k set(retrieved_ids[:k]) hit len(set(relevant_ids) top_k) return hit / len(set(relevant_ids)) def mrr(relevant_ids, retrieved_ids): relevant_set set(relevant_ids) for rank, cid in enumerate(retrieved_ids, start1): if cid in relevant_set: return 1.0 / rank return 0.0注意relevant_ids可能不止一个分块因为同一个答案可能分散在两个相邻分块里。这时候 RecallK 可以“宽进”为命中任意一个就算命中也可以“严进”为全部命中才算命中。我的建议是两种口径都算宽口径反映“信息有没有被找到”严口径反映“信息是不是完整被找到”。真实业务里回答一个规则问题只找到一半信息和没找到区别不大。4.2 生成质量忠实度与可回答率检索命中并不等于回答正确。生成阶段可能出现两种情况模型把检索到的内容提炼错了或者模型绕开检索内容凭自己记忆回答。这两种情况我用“忠实度”指标来抓。忠实度的计算思路是拿“检索到的分块文本 系统生成的答案”一起交给你配置的评测模型让它判断答案里的每个关键断言是否都能在检索文本中找到依据。评测提示词可以这样设计你是评测员。给你三部分内容用户问题、检索到的文档片段、系统生成的回答。 请逐句判断回答中的核心断言是否能由检索片段直接支撑。 如果所有断言都有依据输出 faithful 如果存在无依据或与检索片段冲突的断言输出 unfaithful 并列出具体的不支持表述。 用户问题{{question}} 文档片段{{context}} 系统回答{{answer}}判断结果中faithful的比例就是忠实度。我们在实际使用中这个指标比“整体对不对”更容易发现问题。有的系统回答读起来通顺合理但拆开逐句比对会发现某个关键数字或条件是模型自己脑补的。另一个指标是“可回答率”。评测集中所有问题有多少能在知识库里得到有效回答。理想情况下应该接近 100%但实际跑会发现有些问题因为文档缺失、检索不到、或者生成被拦截最终没有得到有效答案。这个指标用来衡量知识库的“覆盖能力”低于预期时优先去排查文档覆盖而不是调模型。4.3 指标汇总与基线对比单个指标说明不了问题最好把评测结果按业务模块、问题类型分维度汇总。我们习惯用一张表来呈现指标全局值HR模块财务模块IT模块检索 Recall50.830.880.790.81检索 MRR0.740.810.690.72生成忠实度0.790.840.750.77可回答率0.870.920.810.85第一版跑出来全局数值再好看也要盯着模块差异看。财务模块如果有明显洼地说明那份报销制度文档的检索路径有问题而不是整体模型不行。这种分维度拆解才是评测集真正的价值所在。5. 生成评测集时最容易翻车的四个环节Easy Dataset 这类工具能省下大量体力活但评测集质量不是白来的。我们在实际使用中翻了四次车每次都是教训写出来供你避坑。5.1 分块边界切碎了答案第一次用固定长度切分跑 HR 文档时发现一批问题很奇怪问“年假天数怎么计算”生成的答案只有前半句“累计工作满一年享有多少天年假”后半句“当年入职员工按比例折算”被切到了下一个分块。模型生成答案时只看到了当前分块于是给出不完整的回答。这类问题不算模型幻觉因为答案的来源确实在检索片段里只是源文本被切断了。但它会让下游的忠实度评测失真——你会以为是生成错了实际是分块把答案“腰斩”了。解法有两个层面。分块层面改用语义分块尽量在标题和段落边界切同时保留部分 overlap。评测集层面生成问答对时不要只盯着单个分块而是把当前分块的前后邻居也作为上下文喂给生成模型这样跨块答案也能被正确写到ref_text里。5.2 问题类型全挤在“是什么”不配置问题类型模板时模型默认生成的问题里八成是“XX是什么”“XX的定义是什么”这种事实确认题。这类问题对检索来说最简单——问题里的关键词往往就是文档里的原词一搜一个准。但知识库真正难答的是流程题、边界题、对比题比如“A 和 B 的区别”“什么情况下可以提前转正”“哪些费用不允许报销”。后来我们手动配置了 question_types并给每个类型提供了示例模板情况才改善。关键是每一类都要有否则评测集只能评估知识库的“最低难度”表现高难度问题覆盖不到评测结果会虚高。5.3 模型生成答案时混入文档之外的常识这是我们在生成阶段遇到的最头疼的问题。问“报销发票有什么要求”标准答案应该是文档里列的“发票抬头需为公司全称、发票内容需与实际消费一致”等条目。但生成模型偶尔会自己补一句“增值税专用发票需在认证期内完成认证”这句话本身不算错但它不在我们的制度文档里。如果评测集的“标准答案”混入了原文之外的信息那后续评测知识库时就会出问题知识库的回答即使完全忠于文档也会被判定为漏答知识库回答如果覆盖了这个额外信息反而可能被判为忠实。标准答案一旦不标准整个评测就失真了。对策是三重保险。第一生成阶段的提示词里强制写明“只使用给到的文档内容不得加入任何领域外的知识”第二生成的每条答案都要附带ref_text人工抽检时重点核对答案是否能在ref_text中找到第三跑完统一做一轮“答案可溯源”检查凡是答案里的关键句子在原文里找不到的自动标记为待复核。5.4 抽检比例拍脑袋漏掉重灾区自动生成一千条问答人工全看一遍不现实但我们一开始随机抽 10% 审核效果并不好。原因是问题分布不均匀某个文档的问题质量特别差但因为它在总量占比不高随机抽样很容易漏掉。后来改成按source_doc分层抽样每个文档至少抽一个批次问题量大的文档按比例加抽。对抽检不达标比如答案不可溯源比例超过 5%的文档直接把该文档下的所有生成结果打回重新生成而不是逐条修。抽检时我最看三个东西答案是否能在原文找到依据、问题本身是否通顺且不产生歧义、问题之间是否有重复表述。重复问题对评测尤其危险它会虚高某类题型的样本量最后统计指标时造成误导。6. 从分数变化反推知识库优化动作评测集建起来不是为了发朋友圈而是用来指导优化。下面是我们用这套 Benchmark 完成的一轮实际优化循环。6.1 一次真实优化案例第一版评测跑完IT 模块的检索 Recall5 只有 0.72全局表现最差。我们拿评测集里的失败案例一查发现典型模式是用户问“账号被锁定怎么办”但系统检索到的片段是“账号策略管理规范”里关于锁定阈值的定义没有检索到“解锁操作步骤”那一节。问题出在分块策略上——原来的分块把“问题说明”和“处理步骤”切到了两个块而检索排名时含“怎么办”这类意图词的问题并没有特别加分。针对这个问题做了三项改动分块策略从固定 512 字符改为按章节结构语义分块并把标题信息作为前缀注入每个分块检索参数top_k 从 3 提到 5增加找回概率排序阶段增加了一个基于重排模型的环节把关联意图更强、关键词更密的片段排到前面改完用同一套评测集重跑对比结果如下指标优化前优化后检索 Recall50.720.89MRR0.580.76生成忠实度0.680.86可回答率0.810.93最明显的变化是忠实度从 0.68 涨到 0.86。原因很简单检索到的分块更准了生成器拿到正确的上下文自然不容易瞎编。这也印证了一件事——很多知识库“回答不对”的问题根源根本不在模型而在检索链条。6.2 评测集本身也要版本化维护建好第一版 Benchmark 之后还要持续维护别指望一劳永逸。我们参照软件版本管理的方式给评测集打版本号。benchmark_v1对应初次上线的知识库基线之后每次更换模型、调整知识库结构都跑同一份评测集对比。如果某次优化让指标出现明显回退立即回滚策略这就是评测集的“回归测试”价值。同时文档会更新业务会新增。每次有新的制度文件或操作手册发布我们会把新文档增量补充进评测集生成新的批次再合并而不是推倒重来。新文档的评测数据会在metadata里打上version标签方便单独看新内容的得分情况。这里有一个小建议评测集不要轻易删除旧数据。即使某条旧规则已经失效保留它在评测集里也有价值——它能顺便检验知识库在文档更新后是否做到了“旧内容不答新问题”的正确覆盖。从我们团队的经验来看做知识库评测最难的从来不是写出一个评分函数而是建一套稳定、可追溯、贴近业务事实的评测数据。Easy Dataset 把最费人力的部分——从领域文档生成结构化问答对——自动化了剩下的关键在于你怎么设计分块、怎么定问题类型、怎么审答案。只要这套地基打得稳知识库的效果就不再是“感觉还行”而是每次都能拿出来说的具体数字。