English version: Controlled revision in reflection loops。“LLM 应用工程”系列第 10 篇。
问题:“草稿→自我修订×N”为什么常常越改越差
自主生成流水线的标准收尾是反思环:初稿完成后,让模型自我审视、修订若干轮。直觉上多改几轮至少不会更差。我们的第一版实现就是这个直觉的直接翻译——critique 产一段散文点评,revise 据此整篇重写,新稿无条件替换上一版:
msgs.append({"role": "assistant", "content": draft})
yield {"type": "draft", "text": draft} # 无条件保留这一版
实证测量表明这个直觉是错的。arXiv:2601.13217(Beyond Single-shot Writing: Deep Research Agents are Unreliable at Multi-turn Report Revision,我们读过 arXiv 原文核验)对 deep research agent 的多轮修订做了测量:处理反馈时,整篇重写式修订平均回退 16–27% 已覆盖内容,并伴随引用质量下降;更值得警惕的是,无引导的“请自己反思并修订”对几乎所有被测 agent 无效——5 个里仅 1 个有提升(+3.6%),且比定向反馈造成更大的附带损伤。机理侧,Self-Refine(arXiv:2303.17651,检索摘录、未对抗核验)的结论一致:反馈必须具体可执行,泛化反馈显著掉分,收益集中在前 1–2 轮,错误难自检的任务上几乎无效。正面对照是 PaperOrchestra(arXiv:2604.05018):其精修环带显式“改好才收、改差就撤并停”闸门,报告 79–81% 胜率、0% 变差(该细节取自论文正文,未独立核验)。
对照下来,第一版实现三个雷全踩:
| 失效模式 | 实证 | 对应改造 |
|---|---|---|
| 整篇全量重写 | 平均回退 16–27% 已覆盖内容、引用降质(2601.13217,已手工核验) | 改造一 + 改造二 |
| 开放式散文反馈 | 泛化反馈显著掉分;无引导自反思几乎无效且附带损伤更大 | 改造一:定位到节 + 可执行动作 |
| 无接受/回退闸门 | 带闸门的精修环才有 79–81% / 0% 变差(PaperOrchestra,未独立核验) | 改造三:零 token 回归门 |
下文按侵入性从小到大拆解三段改造。语境是一个 LaTeX 报告生成 agent(scan→探索→出图→撰写→反思×N→bib→编译自修复),但机制与格式无关。
改造一:反思输出结构化编辑计划
第一刀砍在反馈的形态上。critique 不再是散文,而是强制输出 JSON 编辑计划:
_REFLECT_SYS = (
"你是实验报告 / 课程笔记的审稿人。对照【原始素材】审视【当前草稿】,只找出**确实需要修正**的问题,"
"并把每个问题**定位到具体某一节**(给该节的 anchor,如 n2);跨章节 / 整体结构 / 摘要关键词类问题用 \"whole\"。"
"每条给 issue(问题)与 action(怎么改,可执行)。已达标的不要提、不要泛泛润色。"
"严格只输出 JSON:{\"changes\":[{\"section\":\"n2 或 whole\",\"issue\":\"\",\"action\":\"\"}]};"
"整体已合格则输出 {\"changes\":[]},不要任何额外文字。"
)
四个设计点:
- 每条问题必须定位到具体节(分节器给的 anchor,如
n2),跨章节、整体结构、摘要关键词类问题显式标"whole"。定位不是装饰——它决定下一步走哪条应用路径。 - **issue 与 action 成对。**光说“误差分析太浅”不够,必须给可执行动作,直接对应 Self-Refine 的“反馈须具体可执行”。
- 允许空数组。
{"changes":[]}即“整体已合格”,反思环提前终止。修订从“默认要改”反转为“默认不改、有据才改”。 - 解析失败不炸流程。
_parse_reflect_plan遇到非 JSON 或无changes一律返回空表,调用方视为“无需修改”;计划封顶 8 条;anchor 命不中时的标题兜底是“先精确等值、再取最长被包含标题”——“结果”不会抢先匹配到“结果与讨论”头上。
配套改动:反思全程改用 fresh 最小上下文(system + 素材 + 当前稿),不再背着探索阶段的全程消息;素材作为稳定前缀,跨轮命中缓存。
改造二:纯 section 级问题走 scoped 逐节 splice
计划里的每一条按定位分流。纯 section 级问题不再触发整篇重写,而是复用交互编辑侧的成熟机件(分节器、作用域提示词、片段体检、确定性 splice——即第 07 篇那套)逐节应用:_scoped_reflect_apply 对每条计划项,在当前 working 文本上重新解析定位(前一次 splice 之后 offset 已移动),只把目标节加该条 issue/action 加相关素材发给模型;拿回的片段过体检(非空、花括号配平、环境配平、不带 \documentclass),不过体检就跳过该节——绝不拼回坏片段;过了就 splice 拼回,其余节字节级不动。跨章节、摘要关键词、无法分节的稿子,才回退整篇最小必要重写。
这一步有个实现坑,由内部对抗审查发现(定级[中]):
# 片段必须保持被替换跨度内的顶层 \section 数(通常 =1;子节 =0)——否则 splice 改变全文节数,
# 令同轮后续 scoped 项的位置型 anchor 漂移、改错节;且“增节”方向不被 regression_check 兜住
# (它只报“减节”)。数不符 → 跳过该节,绝不拼回会移位的片段。
if len(re.findall(r"\\section\{", new_text)) != len(re.findall(r"\\section\{", section_src)):
continue
模型偶尔会“热心”地把一节拆成两节:片段本身健康、体检全过,但 splice 之后全文节数 +1,同一轮里后续计划项的位置型 anchor 整体漂移、改错节;而回归门只报“减节”不报“增节”,这条路径上原本没有兜底。守恒检查把它收口在拼回之前。
改造三:零 token 回归门
无论走 scoped 还是整篇回退,每轮产出落库前都过 regression_check——六项全部是确定性判据、零 API 调用:
- 丢失可编译骨架(
\documentclass/\end{document}); - 篇幅骤缩到上一版 60% 以下(截断或“其余不变”式省略);
- 结构分下降;
\citekey 集合变小(报出丢了哪些 key);- 章节数减少;
- 插图或数据表减少。
任一触发即判 regressed:回退保留上一版、终止反思。两版去空白后逐字相同则判 converged,同样提前停——收敛不浪费轮次。
为什么不用 LLM 评委当闸门?理由写在模块注释里:这个失败模式(丢内容)本身可确定性检测,而配对评委在中文域的可靠性未经验证(这是评委模块自己的告诫),且每轮要多付一次真实调用——更对,且更省。评委的正确位置在离线评测,不在在线闸门;效度问题见第 09 篇。
闸门自身也有边界 case:流水线里 bib 生成排在反思之后,反思阶段 bib 恒为空,此时“引用闭合”检查对任何含 \cite 的稿子恒为 False——新增一处引用会被误判成结构分下降、误回退好改动。修复:bib 为空时把该项移出闸门比分,引用是否丢失改由“key 集合非减”单独判定,并加一条专门的回归测试(bib 空不误判)钉死。
闸门决策以 step 事件呈现并持久化(日志页、断线重连都能看到),附结构化 reflect_gate 字段进 trace,供实验台观测“反思是否真在提质、哪一轮回退”。
改造后的闭环全景
测试随改造分批进入:闸门落地时 test_eval_report +7(接受/回退/收敛/丢章节/丢引用/篇幅骤缩/bib 空不误判)、test_run_agent_mock +1(修订劣化→回退保留上一版并停),后端 303 个测试全绿;scoped 反思落地后 306;本轮全部改造收尾时 322(另有实验台 19 个)。生成质量本身离线测不了,但闭环的每个确定性构件——计划解析、分流、splice、闸门——都可以。
研究过程自身的教训
这次改造的证据链本身也值得复盘。对标前沿时我们跑了一个 105-agent 的联网研究工作流;对抗核验阶段因订阅会话额度打满而整批失败,25 条 claim 全部停在 unverified。于是手工补核最吃重、也最可能被检索 agent 编造的 3 篇论文(读 arXiv 原文):2601.13217 真实、核心数字坐实;PaperOrchestra 真实,但有两处更正——它不是 Google 论文,且摘要自称 flexible 而非“刚性固定”,只能拿来证“结构化多 agent 分工胜过自主循环”(胜率 +50–68% / 整体质量 +14–38%),不能证“越固定越好”;RP-ReAct(arXiv:2512.03560)架构真实,但检索 claim 里“简单任务被 vanilla ReAct 反超”的具体分数在摘要中不存在,疑为检索 agent 从正文抽取或补全,标为未核实。还有一处口径更正:检索 claim 写“break rate 21–31%”,那是正文口径,摘要口径为 16–27%,本文以摘要为准。
教训与正文同构:检索 agent 的产出同样需要一道接受/回退闸门——手工核验就是研究流程里的 regression_check。
什么时候不要这么做
- **闸门判据是代理指标,防“变差”不证“变好”。**章节数、引用集合、篇幅测的都是结构保全;内容写错了但结构完好,闸门照样放行。偏好层的质量仍要靠离线评测与评委,这套闸门不能替代它们。
- **scoped 反思的前提是可分节。**解析不出结构的稿子直接走整篇回退路径——这条回退不是缺陷,是对边界的承认。
- **结构本身错了,scoped 无能为力。**需要全局重组(挪节、并节、换叙事线)的问题必须标 whole 走整篇重写;硬塞进逐节编辑只会产出局部通顺、全局失调的稿子。
- **别把这套闸门套到已有外部信号的环上。**编译自修复环有编译器当裁判、报错指纹无进展即停,是另一种闭环、已是正解;给它再加结构闸门是重复建设。
- **N 要小。**Self-Refine 报告收益集中在前 1–2 轮(未对抗核验),2601.13217 显示多轮修订的破坏率是瓶颈——预算花在第 5 轮反思上,大概率在为回退买单。
本文与第 11 篇《确定性边界》呼应:那篇把闸门与 scoped 机制升格为统一的架构原则,本文是该原则在“反思环”这一个闭环上的完整改造记录。
参考
- Beyond Single-shot Writing: Deep Research Agents are Unreliable at Multi-turn Report Revision(arXiv:2601.13217)——整篇重写式修订平均回退 16–27% 已覆盖内容、引用降质;无引导自反思几乎无效且附带损伤更大;点名解法:结构化编辑计划、专职 Reviser。已读原文核验。
- PaperOrchestra: A Multi-Agent Framework for Automated AI Research Paper Writing(arXiv:2604.05018)——结构化多 agent 流水线胜自主基线 +50–68% / +14–38%(已核验);“改好才收、改差就撤”精修闸门 79–81% 胜率、0% 变差(正文细节,未独立核验)。
- Self-Refine: Iterative Refinement with Self-Feedback(arXiv:2303.17651)——反馈须具体可执行、泛化反馈显著掉分;收益集中前 1–2 轮;错误难自检的任务需外部信号。检索摘录,未对抗核验。
- Reason-Plan-ReAct(arXiv:2512.03560)——plan/execute 解耦架构(已核验);“简单任务被 vanilla ReAct 反超”的具体分数摘要中无,未核实。