跳到主要内容

mirothinker — 本课题摘录

读了哪几篇: 03-robustness-rollback(自我纠错:回滚、去重与容错修复)、04-context-and-answer(上下文管理与答案收尾)。 其余几篇本轮没读。

这一家的核心命题对本课题极重要:循环的健壮性不来自模型,来自围着"模型会犯的错"建的一张网。

它对本课题回答了什么

决定四:回滚 —— 把刚加进历史的那条撤掉,当这一轮没发生过

它的场景是开源模型:会把工具调用格式写错、会拒答、会反复搜同一个词、会吐出坏掉的结构。

做法:每一轮模型说完话之后,先不急着执行,拿几把尺子去量:

模型输出这一轮
↓ 解析层(读懂它):三种格式兼容 + 坏结构抢救
↓ 修复层(改对它):工具名、参数别名、补默认值 —— 不回滚

没有工具调用? ─是─► ◆ 文本里混着工具标签? → 回滚
◆ 命中拒答关键词? → 回滚
都不是 → 正常收尾
↓ 有工具调用
◆ 这个查询刚才查过? → 回滚
↓ 否
执行工具

◆ 结果是「未知工具 / 报错 / 空」? → 回滚
↓ 否
成功 → 连续回滚计数归零

回滚的动作只有四步:轮数减一、连续回滚计数加一、把刚加进去的那条助理消息弹出、然后继续——让模型基于"没出错的历史"重新说一次。 (依据:Agent 库 · MiroThinker · 自我纠错:回滚、去重与对模型输出的容错修复 —— 格式错/拒答/重复查询/结果报错或空四类触发统一走回滚——turn_count 减一、consecutive_rollbacks 加一、pop 掉最后那条 assistant 消息、continue 让模型重来)

这是本课题第三个决定("结果怎么回填")的一个反面选项:不回填,而是把这一轮从历史里抹掉。

前面所有实现的默认动作都是"把错误也写进历史让模型看见"(db-gpt、kun、aider)。 mirothinker 反过来:有些错误不该进历史,因为它们只会污染下一轮。

两者的判据可以这样分:

  • 信息型失败(命令报错、字段不存在)→ 写进历史,模型据此改正;
  • 格式型失败(写错格式、拒答、重复)→ 抹掉重来,写进历史只会让模型学坏。

回滚不是无限的:连续回滚上限默认 5,连续太多次就"放行"或"结束",防止在同一个坎上死循环。

这条护栏必须有。 没有它,一个总是写错格式的模型会把循环卡死在原地。 注意"成功就归零"——它数的是连续,不是累计。

三层容错,由外到内

层次干什么动作
回滚发现这轮废了就撤销重来弹出 + 重试
就地修复模型输出"差一点点",直接改对而不重来参数别名改名、补必填参数、从系统提示反解工具名
解析容错把模型吐的坏结构、三种格式统一解析出来结构修复、多格式兼容、过滤空值

它的一句话总结:回滚是"重来",修复是"改对",解析是"读懂"。

这个三分法很好用,而且顺序是对的:能读懂就别修,能修就别重来。 重来最贵——它浪费了一整轮的模型调用。

"从系统提示反解工具名"这一条特别有意思: 模型写错了工具名,但正确的名字就在系统提示里,所以能反查着修回去。 这是"就地修"的典型:信息是全的,只是模型拼错了。

决定四:把整段失败压成三段式复盘,带进下一次尝试

外层是一个重试循环:每次重试的任务描述 = 原始任务 + 累积的失败经验。

复盘的三段式:

内容
失败类型四选一:跑完轮数没做完 / 工具失败或缺信息卡住 / 走错方向 / 找到答案但格式没对
发生了什么用了什么思路、为什么没到最终答案
有用的发现列出发现的事实、中间结果、结论——给下一次复用

(依据:Agent 库 · MiroThinker · 上下文管理与答案收尾:压缩、失败经验重试、boxed 抽取 —— generate_failure_summary 复用当前对话历史,追加一段要求「不许调工具、按三段式写复盘」的指令与一段预填的 assistant 开头,产出 Failure type / What happened / Useful findings 三段,再拼进下一次尝试的任务描述)

第三段是关键:失败的尝试里也有有价值的发现,不该跟着失败一起丢掉。 这比 db-gpt 的"把失败原因当新输入"高一层——db-gpt 传的是错误,mirothinker 传的是"错误 + 已经查到的东西"。

对我们的最小原型:重试时带上"上次学到了什么"这个动作,成本很低但收益明显。

一个提示技巧:预填一段助理开头,把模型引导进结构化格式。 模型续写时会顺着那段引导走,格式更稳。

"预填助理开头"是让模型守格式的一个通用手段,前面 aider 用它来续写被截断的输出。 同一个机制,两种用法。

决定一:两招省窗口

做法
上下文裁剪只留最近 N 个工具结果,旧的换成一句占位话
窗口守卫每轮前估一下用量,快超了就"退一步"提前收尾

它的直觉句:把窗口当一块有限的白板。第一招是"擦掉旧草稿只留最近几笔";第二招是"白板快满时先把结论写下来,别再往上画"。

第二招值得单独记:"超窗前主动收尾"和"超窗后恢复"是两种策略。 主动收尾拿得到一个不完整但完整成句的答案;被动恢复往往只剩一堆碎片。

tongyi-deepresearch 的"超过阈值就强制收尾"是同一条。

它没回答什么

  • 循环骨架本身——在本轮没读的那一篇。
  • 并发——不在这两篇。
  • 人机协同——不在这两篇。

坑与代价

  • 回滚会丢掉这一轮里可能有用的思考。 抹掉的是整条助理消息,里面的推理过程一起没了。
  • "重复查询就回滚"需要一个查询指纹。 指纹取粗了会误伤(同一个词换个角度问也算重复),取细了抓不住。

    判断(无锚): 这跟 kun 的复读检测是同一个难题的两个位置——kun 检测的是"说的话重复",mirothinker 检测的是"查的东西重复"。后者更容易做,因为查询是结构化的。 如果错,会错在: 如果工具本身是有状态的(第二次查同一个词结果可能不同),那"查过就不许再查"是错的。

  • 连续回滚上限到了之后是"放行"还是"结束",这个选择很重要。 放行等于把一条已知有问题的输出送进执行。
  • 四把尺子里的"拒答关键词表"是硬编码的。 换语言、换模型要重列。