1,377
社区成员
发帖
与我相关
我的任务
分享论文:SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering
论文链接:https://arxiv.org/abs/2405.15793
方向:软件工程 Agent、代码修复、Agent-Computer Interface(ACI)
版本:arXiv v3,2024-11-11 修订
过去一年,大家讨论代码 Agent 时,最容易想到的是“换一个更强的模型”。SWE-agent 这篇论文给出了一个很有启发性的答案:模型能力固然重要,但模型如何观察代码仓库、如何修改文件、如何运行测试,同样决定了 Agent 最终能不能把任务做完。
论文提出 Agent-Computer Interface(ACI) 的概念,把 Agent 与计算机交互的命令、输出格式和上下文组织方式,当成一个需要专门设计的产品接口。作者基于这一思路构建 SWE-agent,让语言模型自动处理 GitHub issue,并在 SWE-bench 上取得了当时开源代码 Agent 中很有竞争力的结果。
这篇论文值得读的地方在于,它把“提示词调优”提升成了“交互系统设计”:不是只告诉模型应该做什么,还要认真设计模型能用什么工具、每次能看到什么、失败后如何恢复。
SWE-bench 中的每个任务通常来自真实 GitHub issue。Agent 需要在一个陌生代码仓库里完成一条完整链路:
这和“根据函数签名补全几行代码”完全不同。任务的难点不只在推理,还在于持续操作环境。一个模型即使知道正确的修复方向,如果搜索命令不好用、输出过长导致上下文被截断,或者编辑工具容易破坏文件格式,最终也可能无法提交正确补丁。
论文的核心问题可以概括为:如何为语言模型设计一套适合软件工程的计算机接口,使它能够稳定地完成搜索、编辑、执行和验证?
传统 Agent 往往直接把终端暴露给模型,模型可以自由生成 shell 命令。这种方式灵活,但也有几个明显问题:命令输出可能非常长;模型容易在目录中反复搜索;编辑文件时需要自己拼接复杂的 shell 语句;失败信息没有统一格式。
SWE-agent 的做法是提供面向软件工程任务的 ACI。可以把它理解成“给模型定制的 IDE 操作层”,主要包含以下几类能力:
这里有一个重要区别:ACI 不是简单的工具清单,而是一个交互协议。工具的参数、输出、错误消息和状态变化共同决定了模型能否形成可靠的操作习惯。
SWE-agent 基本上遵循“观察—思考—行动”的循环:
GitHub issue
|
v
读取仓库状态与相关文件
|
v
模型选择 ACI 命令
|
v
执行搜索 / 编辑 / 测试
|
v
把结构化结果返回给模型
|
+------ 测试失败:继续定位与修复
|
+------ 测试通过:输出最终补丁
每一步动作都会改变环境状态,因此 Agent 不是一次性生成答案,而是在一个真实的代码沙箱中逐步完成任务。论文系统还会控制单次观测的大小,避免无关日志吞噬上下文窗口。
从工程角度看,这个循环至少包含三个状态:
如果只保存对话文本而不显式管理环境状态,Agent 很容易重复操作或误判当前仓库状态。
论文最值得借鉴的观点,是把 Agent 的表现拆成“模型能力”和“接口效率”两部分。一个接口设计得不好,会出现以下连锁问题:
好的 ACI 则会把这些不确定性压缩掉。它不替模型做推理,但能让每次推理都更容易转化为有效动作。这也是论文标题中“Enable”的含义:接口不是装饰,而是在能力和结果之间起到放大作用。
论文在 SWE-bench 上评估 Agent 是否能够解决真实 issue,并在 HumanEvalFix 上评估其修复代码的能力。论文摘要报告:SWE-agent 在 SWE-bench 上的 pass@1 为 **12.5%**,在 HumanEvalFix 上的 pass@1 为 **87.7%**,在论文对应的实验设置下达到当时的 state-of-the-art。
这里的数字不能简单理解为“12.5% 的代码都能自动写完”。它表示在严格的仓库、依赖和测试环境中,Agent 生成的补丁能够通过评测的任务比例。剩余任务失败的原因可能包括:
因此,这个结果更适合被看作一个系统基线,而不是“通用软件工程已经被自动化”的证明。论文真正的贡献,是展示了 ACI 设计对结果的显著影响,并提供了一套可复用的 Agent 系统实现思路。
下面的伪代码展示了 ACI Agent 的最小骨架。实际系统还需要沙箱、超时、日志裁剪、补丁校验和资源限制。
def solve_issue(issue, repo, llm, tools, max_steps=30):
state = tools.inspect_repo(repo)
messages = [
{"role": "system", "content": "You are a software engineering agent."},
{"role": "user", "content": issue},
{"role": "tool", "content": state},
]
for _ in range(max_steps):
action = llm.choose_action(messages, tools.schema())
if action.name == "finish":
return tools.export_patch(repo)
result = tools.execute(action, repo)
result = tools.truncate_observation(result, limit=12000)
messages.append({"role": "assistant", "content": action.to_json()})
messages.append({"role": "tool", "content": result})
raise RuntimeError("agent reached the step limit")
这个示例有三个容易被忽略的设计点:
tools.schema() 必须稳定且清晰,模型才能学会调用;truncate_observation() 需要保留错误位置、退出码和关键上下文;max_steps 是必要的资源边界,否则单个任务可能无限消耗计算预算。第一,SWE-bench 主要衡量“补丁能否通过测试”,不等于补丁具备良好的可维护性。一个过度拟合测试的实现,也可能被判定为成功。
第二,结果高度依赖基础模型、提示模板和运行环境。更换模型后,ACI 的收益幅度未必完全相同,因此不能把论文结果直接外推到所有模型。
第三,软件工程任务之外的 Agent 需要不同的接口。例如数据分析 Agent 更需要表格、绘图和数据库工具;浏览器 Agent 更关心页面状态和权限。ACI 的思想可以迁移,但具体命令不能照搬。
第四,真实企业仓库通常包含私有依赖、网络权限和敏感凭据。论文中的沙箱隔离是基础能力,生产环境还需要权限分级、审计、人工确认和成本控制。
先定义 Agent 能观察到哪些状态、哪些状态变化必须记录,再编写提示词。没有稳定状态模型,Prompt 写得再长也难以避免重复操作。
人类喜欢完整日志,模型更需要高信息密度的摘要。工具应优先返回退出码、错误行、文件路径、行号和少量上下文,并支持按需展开。
错误消息应该告诉模型“发生了什么”和“下一步可以尝试什么”。统一的错误格式,比堆叠更多工具更能提升稳定性。
不要只评估模型是否生成了看似合理的解释。更有价值的指标包括:任务完成率、有效补丁率、平均工具调用次数、失败恢复率、成本和人工接管比例。
在删除文件、修改依赖、执行高风险命令或提交代码前设置确认点,可以显著降低 Agent 失控的代价。自动化程度和可控性应该一起设计。
SWE-agent 论文最重要的结论可以用一句话概括:Agent 的上限由模型决定,但 Agent 的下限往往由接口决定。
当我们构建代码 Agent、浏览器 Agent 或数据分析 Agent 时,不应该只问“要接入哪个模型”,还应该问:模型看到什么?它能做哪些原子动作?失败时如何恢复?上下文怎样裁剪?什么时候必须停下来让人确认?
ACI 提供了一种很实用的设计视角:把 Agent 当成一个需要操作系统、工具和反馈闭环共同支撑的软件系统。对今天的 Agent 工程来说,这个视角可能比再增加一段 Prompt 更有长期价值。
说明:本文面向技术交流,论文指标按公开论文版本与项目资料概括;不同基础模型、评测子集和运行配置会导致结果差异,引用时请以论文原文和最新项目说明为准。