文档助手
Agent 1 重新整理版
一句话
把任意格式的文件变成完整、干净的文字。做法是让模型从 17 个解析工具里挑:先试一个,看结果好不好,不好就换一个对比,实在不行用 OCR。
识别文件格式-构建工具池-质量指标-React-训练(SFT,拒绝采样与难样本重采样与事后纠正)
输入:一个文件(PDF、Word、PPT、Excel、网页、编码文本……)
输出:解析出的正文,附带用了哪个工具、质量指标、每一步的思考记录
一、工作流程
① 识别格式(规则)
- 看文件开头的字节判断真实格式,不信扩展名。PDF 改名成 .docx 也能认出来
- 文本如果像 Base64、摩斯码这类编码,就给模型一个提示
- MD5 是哈希,不可逆,直接拒绝(⚠️ 不要说「MD5 加密」)
② 工具池(17 个)
| 类别 | 工具 |
|---|---|
| PyMuPDF、pymupdf4llm、pdfplumber、pypdf | |
| Office | python-docx、mammoth、python-pptx、openpyxl |
| 通用 | MarkItDown、pandoc、plain-text |
| 解码 | Base64、Hex、摩斯码、URL、ROT13 |
| 兜底 | Tesseract OCR |
为什么要这么多:没有一个工具在所有文件上都最好。
③ 质量指标:每个工具跑完,都会算出这几项给模型看
- 有效词数:抽得全不全
- 自然度:像不像人话,乱码或没解码的内容分数很低
- 干净度:乱码字符少不少
- 重复率:有没有同一段内容被抽了两遍
- 标题 / 表格 / 公式数:结构保住了没有
④ ReAct 循环:模型每一步输出一个 JSON,三选一
call_tool:调用某个工具finish:选定某个结果,结束fail:解析不了,告诉用户原因
例子:先调 PyMuPDF → 看到有表格的迹象 → 换 pymupdf4llm 对比 → 词数更多,表格也保住了 → finish。
安全阀:最多调用 6 次工具;模型连续输出错误格式超过 2 次,就退回规则选的结果,保证一定有输出。
二、评测
- 测试集:79 个真实文件,6 种格式(9 篇 arXiv 论文的 PDF / 扫描件 / docx / html / md,8 个中英文维基词条的各种格式)
- 标准答案:论文用作者的 LaTeX 源码,维基用官方接口返回的正文
- 指标:词级 F1,即解析结果和标准答案的词重合程度。兼顾「漏没漏」和「有没有混进垃圾」
- 对照组:
- 规则 baseline:17 个工具全跑一遍,按质量指标打分选最高的
- oracle:天花板
- 训练集和测试集的文件完全不重叠
三、训练:轨迹蒸馏 SFT
基本思路:让强的教师模型先做一遍,把它的解析过程(思考 + 调用)记下来,教给小的 Gemma 27B。
数据构建(一共 222 条):
| 步骤 | 做法 | 为什么 |
|---|---|---|
| ① 跑教师轨迹 | 教师在 166 个训练文件上跑 ReAct | 获得示范 |
| ② 拒绝采样 | 只留选对的轨迹 | 不让学生学到错误 |
| ③ 难样本重采样 | 教师容易错的类别(论文转的 docx / html),提高随机性再跑 4 次,捞回做对的那几次 | 拒绝采样会把难样本删光 |
| ④ 事后纠正 | 4 次都错的 17 个文件,用标准答案告诉它正确工具,构造出正确路径,再让教师按看到的指标补写理由 | 最难的样本也要有正确示范 |
| ⑤ 上采样多步轨迹 | 「对比了多个工具」的轨迹复制 2 倍 | 大部分轨迹是调 1 次就结束,学生学不会对比;不删简单样本,避免已会的能力被遗忘 |
训练设置:
- 只对模型输出的部分算 loss:学「怎么决策」,不学「背工具返回的内容」
- QLoRA(基座压缩到 4-bit,只训练小的 LoRA 参数,r=16),单卡 48G,约 50 分钟
- 部署时用 FP8
关键一句:学生能超过教师,是因为它学的不是教师的原始行为,而是筛过、补过、纠正过的正确示范。
四、结果
| 方案 | F1 | 选对率 | 平均调用 |
|---|---|---|---|
| 规则 baseline | 0.873 | 82% | 4.3 次 |
| 教师 | 0.884 | 86% | 1.2 次 |
| 27B 未训练 | 0.873 | 82% | 1.1 次 |
| 27B 训练后 | 0.888 | 89% | 1.2 次 |
| oracle(天花板) | 0.895 | — | — |
三句话解读:
- 超过教师和规则 baseline,而且工具调用次数只有 baseline 的三分之一
- 离天花板只差 0.007,所以 Agent 1 不需要再做 GRPO
- 4B 模型训练后也能达到 0.893,说明简单决策任务里数据质量比模型大小更重要。选 27B,是为了让 4 个 Agent 共用一个基座
五、踩过的坑(挑 1~2 个讲)
- 越长不等于越完整:mammoth 把图片转成超长的 base64 字符串塞进输出,长度是正常的 130 倍,被误判成「最完整」。改成只统计可见文字后,baseline 从 0.806 升到 0.873
- 提示会误导模型:ROT13 的编码提示一度被标在所有英文文本上,模型照着去解码,F1 跌到 0.03。改成「解码后明显更像人话才提示」
六、高频追问
- 为什么不用规则直接选? 规则要为每种新情况打补丁,补完选对率也才 82%,而且每个文件要把所有工具跑一遍
- 为什么不做 GRPO? 离天花板只差 0.007,没什么可挖的。强化学习的预算留给更难的 Agent 2~4
- 79 个文件够吗? 差距小于 0.01 的结论不可靠,但「超过 baseline」「调用次数降到三分之一」这两个结论是稳的
Agent 2 整理版
一句话
把 Agent 1 解析出来的乱文本修干净,再切成每块不超过 4096 token、话题完整的块,交给 Agent 3 抽问答。
子任务修复(网页残留,页眉,保留公式)与切块(模型标注新话题从哪开始,rule确定上线)- SFT+GRPO(完整度,清晰度,长度上限,块间独立,块尽量大)- 调权重(1:1:1:1:1,然后统计每项奖励的饱和比例和组内标准差)(公式被拆分导致完整度低,退回到agent1以f1存公式)
输入:Agent 1 的文本,里面有断行、断词、页眉页码、网页导航残留、被拆散的公式
输出:干净的正文,切成若干块
为什么要切块:Agent 3 一次读不了一整篇论文,要分块读;但切在话题中间,Agent 3 就会看不懂。
一、两个子任务
① 修复
- 正文按约 2500 token 分成窗口,模型逐个窗口修复
- 修什么:合并断行、修断词、删页眉页脚页码、删网页残留、恢复标题
- 原则:只修格式,不改写内容
- 公式不经过模型:Agent 1 已经把公式换成占位符
⟦F1⟧,模型原样保留,最后由程序换回 LaTeX。避免模型把公式改错 - 兜底:模型输出为空,或者正文句子丢得太多,就退回规则清洗
② 切块(Agent 2 最核心的设计)
- 一开始:让模型直接输出切块方案(每块从第几段到第几段),结果 70% 以上的方案超长
- 原因:要判断超没超长,得把几十段的 token 数加起来,大模型不擅长长串加法
- 改成两步:
- 模型只标出「新话题从第几段开始」(语义判断,这是它擅长的)
- 程序按 4096 上限装箱,快满时在离上限最近的话题转换点切开(算术,这是程序擅长的)
- 结果:不合法率从 70% 以上降到 0,长度上限由程序保证,永远不会超
核心思想:语义交给模型,算术交给程序。
二、评测
- 测试集:37 篇(PDF 9、扫描 PDF 4、维基网页 8、PPT 8、维基 md 8),输入就是 Agent 1 的输出
- 指标:
| 指标 | 怎么算 | 看什么 |
|---|---|---|
| 完整度 F1 | 和标准答案比词重合(同 Agent 1) | 有没有丢内容 |
| 清晰度 | LLM 打 1~5 分 | 读起来干不干净 |
| 格式缺陷 / 千词 | 规则统计断行、乱空格等 | 客观的脏度 |
| 切分点 | LLM 打 1~5 分 | 切的位置合不合理 |
| 块利用率 | 平均每块装了多满 | 有没有切得太碎 |
- 对照组:规则清洗 + 规则切块;教师模型
三、训练:先 SFT,再 GRPO
SFT(打基础):一共 819 条数据,来源有三类
- 教师在 63 篇训练文档上的修复结果
- 脚本合成的「弄乱 / 还原」样本:把干净文本人为弄乱(插断行、加页码),让模型学会还原
- 教师标出的话题转换点
GRPO(10 轮):每轮 16 道题 × 每题 8 个回答。
5 项奖励:
| 奖励 | 管哪个子任务 | 怎么算 | 类型 |
|---|---|---|---|
| 完整度 | 修复 | 原文正文句子保留了多少,编造内容扣分 | 规则,连续,有惩罚 |
| 清晰度 | 修复 | LLM 打 1~5 分 + 规则缺陷分 | LLM,离散 |
| 长度上限 | 切块 | 超长或格式错误记 −1 | 规则,门槛 |
| 块间独立 | 切块 | LLM 给切分点打分 + 「没切在句子中间」 | LLM + 规则 |
| 块尽量大 | 切块 | 块利用率高加分,碎块(< 512 token)扣分 | 规则,连续,有惩罚 |
所有奖励先换算到 0~1 再加权平均,解决量纲不同的问题。
完整度为什么不用 LLM 判:判断「删掉的是不是无关内容」,规则更准也更便宜。先找出窗口里像正文的句子,再看保没保留;导航、链接列表不算正文,删掉不扣分。
四、调权重(第一个故事)
- 先按 1:1:1:1:1 训一轮
- 统计每项奖励的饱和比例和组内标准差:
- 长度:96% 的组饱和,因为装箱已经保证不超长了,这一项没有学习信号 → 权重改成 0,只保留 −1 门槛
- 切块的组内差异只有修复的一半,被压着 → 块间独立权重提到 1.5
- 清晰度组内差异最大,主导学习
- 训练稳定性:KL 每轮平均 0.01~0.11,偶尔有尖峰也会回落,没有出现 reward hacking
五、清晰度归因(第二个故事,最亮眼)
GRPO 后清晰度卡在 3.53,教师是 4.15。我让 LLM 对 116 个低分块逐块说出原因:
| 原因 | 占比 | 根源在哪 |
|---|---|---|
| 网页残留 | 40% | Agent 2 自己的问题 |
| 公式被拆成一行一个字符 | 37% | 上游:解析工具把公式拆散了,连测试数据的标准答案里公式都是碎的 |
| 表格乱 | 18% | 上游:PDF 工具只抽纯文本,表格结构没了 |
| 断行、OCR 错字 | 5% | 原文件本身 |
发现一个矛盾:标准答案里公式就是碎的,所以「完整度」奖励模型保留碎片,「清晰度」奖励又惩罚碎片,两项奖励在互相打架。
修上游:
- Agent 1 工具池加上 pymupdf4llm,能把 PDF 表格转成 Markdown
- 网页公式取出 LaTeX 源码,换成占位符
- 用 LaTeX 重新生成测试数据
结果:Agent 2 不用重新训练,清晰度 3.53 → 3.87,格式缺陷 17.4 → 1.7(每千词)。Agent 1 也没有退步(0.873 → 0.874)。
这个故事说明:分数上不去时,先查问题出在哪,而不是盲目加训练。
六、结果
| 方案 | 完整度 F1 | 清晰度 /5 | 格式缺陷 / 千词 | 切分点 /5 | 块利用率 |
|---|---|---|---|---|---|
| 处理前(Agent 1 输出) | 0.806 | — | 21.5 | — | — |
| 规则清洗 + 规则切块 | 0.810 | 3.63 | 0.1 | 3.96 | 0.70 |
| 教师 | 0.850 | 4.17 | 0.8 | 3.83 | 0.83 |
| Gemma 27B SFT + GRPO | 0.853 | 3.87 | 1.7 | 3.98 | 0.81 |
三句话解读:
- 完整度和切分点超过教师,格式缺陷接近教师
- 清晰度还差 0.3,集中在 PDF 和扫描件。原因是模型训练时没见过 Markdown 表格,扫描件的 OCR 错字本身也最难修
- 已经达到事先定的标准(清晰度 ≥ 3.7、缺陷 ≤ 10),所以停止训练,转向下游
七、踩过的坑(挑 1~2 个讲)
- 思考型教师吃光了输出额度:教师模型思考太长,把输出长度用完了,返回空结果,内容被悄悄丢掉。改成关闭思考的模型,并加上「正文句子保留率」检查兜底
- dropout 让新旧概率对不上:采样时 dropout 是关的,训练时是开的,同一个模型算出来的概率不一样,本不该触发的截断被触发了。GRPO 时关掉 dropout
- 每轮平均分看不出趋势:每轮抽的题不一样,平均分主要反映题目难不难。后来加了固定的验证集
八、高频追问
- 为什么切块不让模型直接输出? 长度约束是算术,大模型做长串加法不可靠。拆开后各做擅长的事
- 5 项奖励怎么加权? 先 1:1:1:1:1,看饱和比例和组内差异调。长度项总饱和,改成门槛;块间独立差异大,加到 1.5
- 为什么不继续训练补清晰度? 已达标,剩下的差距集中在 PDF 和扫描件,主要是输入格式变了和 OCR 本身难修,投入产出比不划算
- 怎么判断问题在模型还是上游? 逐块归因到固定类别,再逐类追根源。修了上游、不重训就提升,说明判断是对的
Agent 3 整理版
一句话
把 Agent 2 切好的块,变成一棵知识树:文档 → 主题 → 问答,相关的问答之间连线,并和已有知识库去重。
知识树-逐块抽取-合并-并入知识库-有向到无向-教师模型评测-SFT+GRPO(召回,准确,结构)
输入:Agent 2 的块(每块 ≤ 4096 token)
输出:
1 | 文档:GRPO 论文 |
- 树:负责分类,每条问答只属于一个主题
- 边:负责跨主题的关联,是无向的「相关」关系
- 每条问答都带一句原文摘录,作为证据,方便 Agent 4 核对
⚠️ 不要叫它「知识图谱」,统一说「知识树 + 关联边」。
一、工作流程(3 步)
① 逐块抽取(抽取模型)
- 每块输出若干主题,每个主题下若干问答
- 每条问答附原文摘录
- 要求问题自足
② 合并(关系判断模型 + 程序)
- 找候选对:embedding 找出最相似的问答对,加上 RefD 检查。不可能把所有问答两两比较
- 逐对判断:关系判断模型判定每一对是
same(同一知识点)、related(相关)还是none(无关) - 处理结果:
same用并查集合并去重;related存成边;相似的主题也合并
③ 并入知识库:新文档的问答和已有知识库用同样的方法去重、连边。
又一次「模型做语义判断,程序做结构操作」:模型只判断两条问答是什么关系,怎么合并、怎么建树都交给程序。
二、关键决策:为什么从「有向依赖」改成「无向相关」
原本的设计:有向的「前置依赖」边。比如「要懂 GRPO 的奖励更新,得先懂相对优势」,A → B。
遇到的问题:试了更严格的提示、成环检查、RefD,连教师模型的依赖边正确率也只有 0.32~0.65。
查文献找原因:读了概念前置关系学习方向的文献(RefD、LectureBank 等),结论是:
- 方向需要外部信号,比如教材的章节顺序、论文的引用结构
- 光靠语义相似度判断不了方向。在我的数据里,真正有依赖的对,相似度反而比「看起来像但无关」的对还低
决定:先做无向的「相关」边,有向依赖等以后有外部信号再加。
⚠️ 关于简历上的「0.25 → 0.90」:0.25 是在有向定义下评的,0.90 是在无向定义下评的,两者不是同一道题。面试官很可能会问「你是不是换了一道简单的题」。建议这样回答:
对,这两个数不是同一个标准下的比较,0.90 不代表模型变强了 3 倍。它说明的是:有向依赖这个任务,在没有外部信号的情况下本身就做不好,连教师都只有 0.32~0.65。所以我把任务定义改成了数据能支撑的版本。改成无向后,学生能稳定达到 0.90,「不连正确」0.77,这才是有意义的指标。
三、评测
- 测试集:37 篇,和 Agent 2 相同
- 参考答案:DeepSeek V4 Pro 从原文(不是从 Agent 2 的输出)抽出的问答。我人工通读了 3 篇共 147 条,没有发现内容错误
- 打分:DeepSeek Flash
| 指标 | 怎么算 |
|---|---|
| 召回率 | 每条参考问答,用 embedding 找学生最像的 3 条,再让 LLM 判断有没有覆盖 |
| 准确率 | LLM 对照原文,判断学生的答案对不对 |
| 问题自足 | LLM 判断问题能不能脱离原文看懂 |
| 归属主题 | 问答挂的主题对不对 |
| 关系边正确 | 连上的边,是否真的相关 |
| 不连正确 | 最像但没连的对,是否真的无关(防止模型偷懒少连边) |
四、训练
两个 LoRA,挂在同一个 27B 基座上:
| LoRA | 任务 | SFT 数据 |
|---|---|---|
| 抽取 | 一块 → 主题和问答 | 282 块、7255 条问答 |
| 关系判断 | 一对问答 → same / related / none | 2989 对 |
SFT 数据整理:
- 教师在英文文档上写出了中文问答,翻译回英文
- 修正归属错误的问答
- 合并过小的主题(只有 1~2 条问答的)
两个坑:
- loss 要按 token 平均:输出长度从 20 token 到 3400 token 不等。按样本平均时,短样本的权重太大,模型学会了「输出空列表最安全」,直接塌缩。改成按 token 平均后恢复正常
- 关系数据不要人为配平:把「依赖」样本上采样后,模型预测依赖的比例从教师的 5% 涨到 11%,多出来的大部分是错的。按自然比例训练就好
GRPO(只对抽取模型,3 轮),3 项奖励:
| 奖励 | 怎么算 | 类型 |
|---|---|---|
| 召回 | 每条教师问答找最像的学生问答,相似度 0.6~0.9 线性映射到 0~1 | Embedding,连续 |
| 准确 | 0.7 × LLM 判断答案有没有原文依据 + 0.3 × 原文摘录是否逐字出现在块里 | LLM + 规则 |
| 结构 | 主题归属 + 小主题惩罚 + 语言和原文一致 + 问答数不超过教师的 1.3 倍 | Embedding + 规则 |
输出不是合法 JSON,整条记 −1。
设计要点:「数量不超过 1.3 倍」是专门用来制衡召回的。召回奖励鼓励多抽,不加约束的话,模型会把一个知识点拆成很多条来刷召回。
五、结果
| 方案 | 召回 | 准确 | 问题自足 | 归属主题 | 关系边正确 | 不连正确 |
|---|---|---|---|---|---|---|
| 27B 未训练 | 0.319 | 0.915 | 0.958 | 0.817 | — | — |
| 教师(Flash) | 0.691 | 0.965 | 0.985 | 0.858 | — | — |
| SFT | 0.692 | 0.934 | 0.950 | 0.841 | 0.897 | 0.754 |
| SFT + GRPO 3 轮 | 0.697 | 0.928 | 0.947 | 0.836 | 0.899 | 0.766 |
解读:
- 召回从 0.319 涨到 0.697,追平教师。未训练时问题在于抽得太少,每篇 78 条,教师 102 条
- 准确率差教师 0.03,主要出在维基网页上:模型把导航、参考文献这类网页残留也抽成了问答
- GRPO 和 SFT 在测试集上持平(差距都在 ±0.012 以内)。GRPO 真正的收益是训练中无效输出从 21% 降到 2%:SFT 模型在一些块上会写出失控的超长回答,GRPO 学会了不这样做
六、⚠️ 简历上要处理的两个问题
- 召回写的是 0.797 / 教师 0.791,但报告里是 0.697 / 0.691。 如果没有重算过,要改回 0.697 / 0.691;如果按 README 里那条 TODO 做过二次复核重算,就得能讲清楚复核口径,否则别用
- 标题写的是「(GRPO)」:GRPO 的贡献是稳定性,不是指标提升。被问「GRPO 带来了什么」时,要诚实回答:
3 轮 GRPO 在测试集上和 SFT 持平,主要收益是无效输出从 21% 降到 2%。原因有两个:一是召回奖励以教师为标准,而 SFT 已经追平教师,天花板就在那里;二是为了控制成本只跑了 3 轮。要继续提升,奖励就不能只对标教师,比如准确率直接对照原文判。
承认 GRPO 没涨分,再讲清楚为什么,比硬说它有效更可信。
七、高频追问
- 为什么用两个 LoRA,不用一个? 抽取和关系判断是两种完全不同的任务:一个是长输出生成,一个是三分类。分开训互不干扰,都挂在同一个基座上,部署成本不变
- 为什么不把所有问答两两比较? 一篇文档 200 条问答,两两比较就是约 2 万对,每对都要调一次模型。先用 embedding 筛出候选,只判最可疑的那些
- 召回奖励用 embedding,会不会被钻空子? 会,模型可以多抽来刷相似度,所以加了「数量不超过教师 1.3 倍」来制衡;准确率还要求原文摘录必须逐字出现,防止编造
- 测试集参考答案是 LLM 生成的,可靠吗? 是从原文生成,不是从 Agent 2 的输出生成,人工抽查了 147 条没有发现错误。局限是参考答案的抽取粒度是教师的习惯,学生拆得更细时会被低估召回
Agent 4 整理版
一句话
逐块检查前三个 Agent 的工作:找出问题,归因到出错的那一步,写出修改意见,再由程序决定打回给谁重做。
输入:同一块内容在三步里的样子
- Agent 1 解析的原文片段
- Agent 2 整理后的块
- Agent 3 从这块抽出的问答和连线
输出:先写推理,再输出问题列表(JSON)
1 | {"issues": [ |
一、9 类错误,按负责的 Agent 分
| Agent | 错误类型 | 例子 |
|---|---|---|
| 1 解析 | 解析残缺 | 乱码、OCR 错字成片、表格被打散 |
| 2 整理 | 删了正文 | 原文有的段落,整理后没了 |
| 多出垃圾 | 成片的空表格、JSON、重复字符 | |
| 改动内容 | 数字、名称、公式和原文不一样 | |
| 3 抽取 | 漏抽 | 重要知识点没抽成问答 |
| 答错 | 答案和原文不符,或者是编造的 | |
| 问题不自足 | 「该方法」「本文」这种指代不明 | |
| 主题归错 | 问答挂在不相关的主题下 | |
| 连错边 | 连线的两条问答其实没关系 |
二、核心设计:模型找问题,程序做决定
- 模型只负责「找问题、说理由」
- 程序按固定规则决定打回给谁:
- 有 Agent 1 的问题 → 打回 Agent 1(下游跟着重做)
- 有 Agent 2 的问题 → 打回 Agent 2
- Agent 3 漏抽 ≥ 2 个,或者答错 + 不自足 ≥ 这块问答的 20% → 打回 Agent 3
- 零星小错不打回:每块都难免有,重做的代价比它大
- 主题归错、连错边只报告,不触发打回:主题归属本身就偏主观,只因为这个重做一块不划算
- 每个 Agent 最多重试一次,防止死循环
第三次出现「模型做语义判断,程序做规则决策」。和 Agent 2 的切块是同一个思想,面试时可以把这三处串起来讲。
三、最难的部分:标签从哪来
质检员要训练,就得有「这块到底有什么问题、该怪谁」的标准答案。我用了两个来源:
① 沿 ground truth 逐级追查(真实错误,自动标注)
拿一个漏抽的知识点,顺着流水线往下查:
1 | 标准答案里有,Agent 1 的正文里没有 → Agent 1 没解析出来 |
- 全程只用规则,不调模型
- 宁可少标,也不错标:查到的命中比例处在「在」和「不在」之间,或者以公式为主(各工具写公式的方式不同,对不上不代表丢了),就不打标签
② 错误注入(人造错误,标签确定)
真实错误分布很不均衡(大部分是 Agent 3 的问题),所以往真实输出里注入 9 类错误补足样本。比如:
- 往 Agent 1 的原文里加 OCR 噪声(
rn→m、l→1) - 删掉 Agent 2 块里的一段正文
- 改掉一个数字
注入类型轮流选,保证各类均衡。
四、训练数据:教师写推理
做法:DeepSeek V4 Pro 当质检员,在真实样本和注入样本上写「推理 + 问题列表」,再蒸馏给 Gemma。
一个关键难点:防止「作弊信息」泄露给学生
- 为了让教师报得准,我额外给了它一份内部备忘:注入了哪些错误、核对员初查的结果
- 但学生训练时看不到这份备忘。如果教师在推理里写「备忘中提到 q3 有问题……」,学生学到的就是「凭空知道答案」
- 解决办法:
- 要求教师把推理写得像自己发现的一样,每个问题都引用原文作证据
- 程序自动删掉推理里提到「备忘」「参考信息」等词的句子
- JSON 部分里出现这些词,整条丢掉
- 教师漏报了注入的错误,重试一次,还漏就丢掉
数据来源各一半:
- 学生模型的输出:带着真实的毛病(残留 HTML、空表格)
- 教师模型的输出:比较干净,多给一些「这块没问题」的样本,让 Agent 4 学会不乱报
一共 814 条,其中「没有问题」的占 25%。
五、GRPO 的 6 项奖励(已设计,尚未训练)
| 奖励 | 看什么 | 怎么算 |
|---|---|---|
| 打回决定 | 打回对象和标准答案一致吗 | 规则 |
| 召回 | 标准答案里的问题报出了多少 | 规则 |
| 精确 | 报出的问题是不是真的 | 规则 + LLM:对不上标准答案的,交给 Flash 复核。学生可能发现了教师漏掉的真问题,不能一概算错 |
| 归因 | 问题归到的 Agent 对不对 | 规则 |
| 理由有据 | 推理里引用的原话,是否真的出现在输入里 | 规则,防止编造证据 |
| 理由一致 | JSON 里的每个问题,推理里是否讨论过 | 规则,结论要有推理支撑 |
两个专门的设计:
- 不奖励沉默:该报的一个都没报,精确、归因、有据、一致这 4 项全记 0
- 不奖励误报:块本来没问题却报了问题,精确率直接记 0
六、⚠️ 现状:要诚实面对的部分
1. SFT 版目前效果不好
| 方法 | 打回决定准确 | 误报 | 漏报 | 输出不合法 |
|---|---|---|---|---|
| 全部放行(什么都不做) | 0.206 | 0 | 1.0 | 0 |
| Gemma 27B 未训练 | 0.431 | 0.37 | 0.46 | 7% |
| 教师参考线(Flash) | 0.439 | 0.09 | 0.55 | 11% |
| SFT 版 | 0.298 | 0.07 | 0.80 | 26% |
SFT 后反而变差了。问题出在两个地方:
- 26% 的输出不合法:教师的推理太长(训练样本平均 8600 token),学生学着写长推理,还没写到 JSON 就被截断了
- 漏报 0.80:学生变得过于保守,大部分该报的问题都没报
2. v2 已经针对性修复,但还没跑
- 让 V4 Pro 压缩推理,问题列表不变,推理长度的 p90 从 7103 字降到 2270 字
- 「没有问题」的样本减半,减轻保守倾向
- 训练长度上限提高,不再丢长样本
3. GRPO 只设计了奖励、写好了脚本,还没有训练(data/agent4/grpo/ 是空的)
七、简历上的问题
简历这一段写的是「SFT + GRPO」,还列了 6 项奖励。如果面试前 GRPO 还没跑完,被问「效果怎么样」就答不上来。三个选择:
| 选择 | 做法 |
|---|---|
| A. 跑完 v2 | 把 SFT v2 和 GRPO 训完,拿到真实数字(推荐) |
| B. 改简历 | 改成「SFT(GRPO 进行中)」,面试时讲设计思路和遇到的问题 |
| C. 维持现状 | 风险最高:一被追问效果,就会露馅 |
如果选 B,面试时可以这样说:
Agent 4 是最后做的,现在还在迭代。第一版 SFT 的打回准确率只有 0.298,比未训练的基座还差。我分析发现两个原因:一是教师的推理太长,学生学着写,26% 的输出被截断;二是「没问题」的样本太多,学生变得过于保守,漏报到 0.8。第二版已经把推理压缩到原来的三分之一、减半了无问题样本,GRPO 的奖励里也专门加了「不奖励沉默」。
这样讲,一个失败的实验反而能体现你的分析能力。
八、高频追问
- 为什么 Agent 4 不直接给出打回决定,而是交给程序? 「几个问题算严重」是规则问题,不是理解问题。交给程序,可解释、可调整,阈值改一个数就行,不用重新训练
- 为什么需要错误注入? 真实错误分布不均衡,绝大部分是 Agent 3 的问题,Agent 1 的很少。注入能保证每类错误都有足够的样本,而且标签确定
- 怎么防止 Agent 4 编造问题? 两道关:「理由有据」要求推理里引用的原话必须真的出现在输入里;「精确」要求报出的问题要么对上标准答案,要么经过 Flash 复核成立
- 为什么不奖励沉默? 精确、归因这类指标,不报就不会错。不加限制,GRPO 会把模型训成什么都不报