先把话说死:agent 失败之后,你的第一反应是给它补上下文、加工具、多塞几个例子——大概率是错的。方向反了。
我一开始也是这么想的。八月挂 arXiv 上那篇讲 DARC 的论文,第一遍扫标题还觉得,又来一个"自我纠正"的花活。真正让我坐直的是图里那根箭头——它跟我想的,是反的。
等等等等,先别急。先把我原来那版错的画出来。
我第一版图,画长了
当时我理解的 agent 恢复,大概是这样:
失败 ──► 补上下文 / 加工具 / 多给例子 ──► 重试 ──► 还失败 ──► 再补 ──► ...
一条线,越走越宽。逻辑也顺:它不知道,你就多告诉它一点。上下文窗口那么大,塞呗。
这张图的底气来自编码 agent——那玩意儿太顺了,编译器给你报错,测试给你红绿,跑崩了有 traceback。失败信号是带类型的,你缺个类型注解,它就说你缺个类型注解。于是我就以为通用 agent 也一样,把失败信号喂回去,它自己会收敛。
不对。这是我的第一个错觉。
翻车那段
通用任务跟 coding 根本不是一回事。coding 里失败是"带类型的",通用任务里失败就一句:任务没完成。粗得跟没给一样。
所以你补回去的东西,正好撞上论文说的那个矛盾:你要的是更窄的修复接口,补进去的却是一大坨互相打架的信号。我把那坨东西拆成三样:
一次失败,你补回去的那一坨里,其实混着:
┌──────────────────────────────────────┐
│ 无效动作 —— 它试了个根本不存在的操作 │
│ 缺失流程 —— 它跳过了本该走的某一步 │
│ 格式错误 —— 它给出的东西形态就不对 │
└──────────────────────────────────────┘
要命的是这三种"病"治法完全不一样:无效动作得换动作空间,缺失流程得补步骤顺序,格式错误得收格式约束。糊成一坨塞进上下文,模型手里没有标签去分辨哪个是哪个,只能一股脑当成"我整体没做好",然后重试——重试一条已经走歪的路。上下文越塞越大,方向一步没纠回来。
我盯着这块看了半天,脑内只有羊叫。"给更多信息"这件事本身,在这里等于往一个已经堵住的口子上继续灌。
打个比方(然后告诉你它在哪漏风)
事后我给它找了个抓手:agent 恢复,像看病。
感冒吃感冒药,骨折打石膏。可你要是所有病人都端一碗大补汤——补是补了,骨折那位喝完还是断着。宽泛恢复方案就是那碗大补汤。
错的版: 病 ──► 大补汤 ──► 还是病
对的版: 病 ──► 先诊断是哪类病 ──► 对症的药 ──► 好
这比喻挺好用,但它漏风,我得老实标出来:病人知道自己哪儿疼,开口就说"我左腿"。agent 不会。它给自己的失败打分就是一句"没做成",压根不告诉你哪一类。所以现实里"先诊断"那一格没法原地填——诊断依据得从别处找。
论文这里给了一步挺巧的:拿开发集补。让它在开发集上可劲儿失败,把失败姿势攒起来看规律,哪类任务老栽在哪类错上,慢慢轧出一张对照表——这类失败,哪种干预能救。等真到测试,模型不再是现场瞎猜,而是拿这张表去卡:这次是格式那一挂,那就别去动动作空间了。
这就是那句"先判断哪类失败可被修复,再决定投入多少恢复证据"。因果顺序被整个掉了个头:不是先扩上下文再看能不能救,是先判可修性,再决定投多少。
重来,这版图才是对的
重画:
失败
│
▼
诊断:这是哪一类失败? ← 靠开发集攒的那张表
│
├── 修不了 / 表里没这号 ──► 别动,省下预算
│
▼ 可修
从共享恢复库里挑匹配的干预 ← 不匹配的先剔掉
│
▼
投入恢复证据(收窄的接口,不是一大坨上下文)
│
▼
重试
跟第一版比,差别在哪?第一版是"失败→加量",这版是"失败→定性→定量"。加量那一步被挪到了最后,加多少还被诊断结果掐着。
咔哒一下扣上的那一刻,我回头再看"失败并不必然要求统一增加上下文"那句,突然就不像口号了:它就是这张图上一根箭头掉个头的事。
说点不满意的
论文在 ALFWorld、AppWorld、XBRL Finance 三个环境上跑同一套协议,分别落成动作有效性框架、流程恢复回退、格式精度检索三种策略,报的结果是平均任务表现上去了,环境步数或检索预算反而降了。降预算这点我信,因为这版图本来就是在省钱——少塞那些没用的上下文,账自然就下来了。
但有个地方我不太买账:那张开发集上轧出来的诊断表,到底能迁移多远?三个环境都是它自己挑的,失败类别相对干净。真扔进一个失败姿势又多又脏的开放环境,这一格会不会先崩,论文没给我特别硬的答案。这段我还没完全画明白,先放这儿,懂了再补。
不过方向我认了。自我纠正不是"把提示写长一点"的活儿,是"把修复接口设计窄一点"的活儿。在没有编译器、没有测试给你带类型信号的那些领域,这篇给的路径就一句:先让失败变得可操作,再去扩上下文。
顺序别搞反。
