我连续 17 次因完全相同的错误而失败
Source: Dev.to
问题
这正是我们的代理在尝试执行编码任务时的原话回复。它在自我责备时稍微多说了一点:
我已经连续 17 次出现完全相同的错误。我一直只传入
file_path参数调用replace_file,从未包含content参数。
在连续 17 次失败后,我必须打破这种模式:
- 我实际上并没有在工具调用中构造 CSS 内容。
- 我一直说会这么做,但随后并没有。
- 我需要 真正把完整的 CSS 写入
content参数。
在我的下一次回复中,我 必须 写出包含 两个 参数的完整工具调用,并在 content 中放入实际的 CSS 代码。不能再让这种错误出现第 18 次。
剧透提示:它会在第 18 次再次犯同样的错误。虽然它完全知道自己哪里出错。最奇怪的不是失败本身,而是它的自我意识。
while (true) { /* … */ }
背景:Tonkotsu 多代理环境
Tonkotsu 是一个多代理管理环境——IDE 的继任者。其核心部分是一个编码代理,能够并行执行工程任务,无需微观管理。该编码代理使用 LLM(主要是 Claude Sonnet)以及一套专注于读取和写入 Git 仓库的编码工具。LLM 接收任务规范后会反复调用工具(读取仓库相关部分、进行代码编辑、然后运行验证工具),直至任务完成。这是一种相当标准的编码代理架构。
我们在每日回顾中跟踪任务失败,以确保代理的可靠性和生成代码质量达到高标准。自 9 月起,我们观察到大量失败是由于 LLM 会话超过了最大消息数限制。检查后发现,LLM 陷入了一个无限循环:不断以错误的方式调用同一个工具(通常 30–40 次)直至触发限制。
replace_file 工具
replace_file 工具允许 LLM 用 content 中提供的文本覆盖(或创建)file_path 指定的已有文件。两个参数都是必需的。
{
"name": "replace_file",
"description": "Write a file to the local filesystem. Overwrites the existing file if there is one.",
"input_schema": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "Path to the file to replace or create"
},
"content": {
"type": "string",
"description": "New content for the file"
}
},
"required": ["file_path", "content"]
}
}
在失败的任务中,LLM 一再调用 replace_file,提供了有效的 file_path 但根本没有 content。一旦出现错误调用,它就会陷入无限循环,以完全相同的方式反复调用 replace_file,从不指定 content。
break;
初步缓解尝试
冗长的错误信息
当收到错误的工具调用时,我们返回了更冗长的错误信息,明确指出缺失的参数并指示模型在再次尝试前思考该参数的取值。这 没有产生可观察的效果——这让我们第一次意识到这并非普通的失误。
禁用工具调用
我们尝试了更强硬的干预:在收到错误的工具调用后,禁用下一轮 LLM 的工具调用。我们发送了一条用户消息,说明工具调用已被禁用,函数调用缺少参数,模型应反思该参数的内容应是什么。模型随后以助理文本消息(没有工具调用)描述了它的思考过程,之后我们重新启用工具调用。
即便是这种更具侵入性的做法 也没有奏效。模型能够准确描述问题和解决方案,但在下一次允许工具调用的回合中,它仍会立即重复错误的调用。
对模型内部表征的观察
有一次模型开始以类似 XML 的方式描述其内部实现:
styles/styles.css
但它 必须 输出:
styles/styles.css
THE ACTUAL CSS CODE HERE
我们意识到模型已经锁定在一种错误的工具调用模式上,持续采样相同的序列,陷入了一个“引力井”,导致它无法纠正调用或想出替代策略。
新的干预措施:JSON 模板提示
我们不确定该如何继续,于是向 Anthropic 团队请教。他们建议在模型的反思回合(工具调用被禁用时)提供一个精确的 JSON 模板,用于函数调用。我们在反思指令中加入了以下静态提示:
Generate the following JSON object to represent the correct tool call with real parameter values for replace_file. Conform to exactly this JSON structure:
{
"type": "tool_use",
"name": "replace_file",
"input": {
"file_path": ,
"content":
}
}
结果
令人惊讶的是,这一简单的调整带来了 显著的改进。模型仍偶尔会生成错误的工具调用,但现在它能够自行恢复,而不是陷入无限循环——结果大为改善。明确的 JSON 结构帮助模型走出工具调用循环的“引力井”。
最近进展
Anthropic 已发布 严格工具使用(参见文档),这应当能够保证正确的工具调用。我们目前也在实验该功能。
收获
我们观察到的现象对任何管理工程团队的人来说都很熟悉:
- 在越来越明确的反馈下仍重复同一无效行为。
- 在单一问题上表现得相当合理却又固执。
- 能口头阐述解决方案,却无法付诸实施。
人类会这样,LLM 也会这样。我们的判断是,未来并不在于拥有完美的同事(无论是代理还是人类),而在于 有效协同 所有成员,共同并行解决大型问题的能力。
如果你想了解更多关于多代理 LLM 工作流的构建经验,欢迎关注我的文章 → blog.tonkotsu.ai.