一个 LLM 同时扮演程序员和测试员,不如两个分开

问题:一个 LLM 同时做太多事

让 LLM 生成代码时,通常会在同一个 prompt 里要求它:理解问题、考虑边界情况、写出正确代码、还要自己验证。这几件事的认知要求不同,放在一起往往互相干扰。

AgentCoder(Huang et al., 2023)的出发点是:把这些任务拆给不同的角色,每个角色专注一件事


三个角色

程序员(Programmer Agent)

只负责写代码。给它问题描述,它输出实现:

# Programmer Agent 的输出
def find_missing_number(nums: list[int]) -> int:
    n = len(nums)
    expected_sum = n * (n + 1) // 2
    return expected_sum - sum(nums)

程序员 Agent 的 prompt 里没有测试生成的指令,也没有执行结果的处理逻辑,只做一件事。

测试设计师(Test Designer Agent)

只负责生成测试用例。它看的是问题描述,而不是程序员写的代码——这是一个关键设计决策:如果测试设计师看到了代码,它生成的测试往往会迁就代码的实现,而不是真正检验问题的要求

# Test Designer Agent 的输出
test_cases = [
    ([3, 0, 1], 2),           # 基本情况
    ([0, 1], 2),               # 短数组
    ([9, 6, 4, 2, 3, 5, 7, 0, 1], 8),  # 长数组
    ([0], 1),                  # 单元素
]

测试执行器(Test Executor)

不是 LLM,是实际的代码执行环境。它运行程序员写的代码,用测试设计师给出的测试用例验证,把结果(通过/失败/报错信息)返回给程序员 Agent。


工作流程

问题描述
    │
    ├──→ 程序员 Agent → 生成代码 ──────────────────┐
    │                                              │
    └──→ 测试设计师 Agent → 生成测试用例            │
                                │                 │
                                ↓                 ↓
                           测试执行器(运行代码 + 测试)
                                │
                    ┌───────────┴───────────┐
                  通过                    失败
                    │                      │
                  返回代码          报错信息 → 程序员 Agent 修正
                                            → 循环

循环在代码通过所有测试时终止,或者达到最大迭代次数时停止。


测试设计师不看代码的原因

这个设计细节值得多说一点。

如果测试设计师能看到程序员写的代码,它会自然地顺着代码的逻辑来生成测试——比如看到代码处理了 nums = [] 的情况,就给 [] 写个测试,看到没处理 None,就不写 None 的测试。这样生成的测试是对代码的描述,而不是对问题要求的独立验证。

独立性才是测试的价值所在。测试设计师只看问题描述,生成的测试才真正反映了"这个问题应该满足什么条件",而不是"这个代码实际上做了什么"。


实验结果

论文在 HumanEval、MBPP 和 CodeContests 上进行了对比:

方法HumanEvalMBPP
GPT-3.5 直接生成72.6%65.9%
Self-Debugging76.8%69.4%
AgentCoder(GPT-3.5)79.9%73.9%
GPT-4 直接生成82.0%75.1%
AgentCoder(GPT-4)91.5%83.2%

用 GPT-3.5 的 AgentCoder 在 HumanEval 上接近了 GPT-4 直接生成的水平,说明多角色分工可以在一定程度上用结构设计弥补模型能力的差距。


和单 Agent 方法的比较

维度单 Agent(Self-Debugging)AgentCoder
角色一个 LLM 做所有事三个角色分工
测试来源执行报错独立 Agent 生成
测试质量依赖代码质量独立于代码
LLM 调用次数较少较多
可解释性一般较好(每步职责清晰)

角色分离的适用范围

AgentCoder 的角色分离在有明确输入输出规范的任务上效果好。对于需求本身就模糊的任务,测试设计师也无法生成有效的测试,这个架构的优势就消失了。

实际应用中,测试设计师生成的测试也可能有错(预期输出不对),这和 AlphaCodium 面临的问题一样。AgentCoder 没有专门的机制来验证测试本身的正确性,这是这个方案的局限之一。


对多 Agent 架构的参考价值

AgentCoder 是较早系统性研究"角色分离对代码生成的影响"的工作之一。它的核心发现——独立的测试生成比让同一个 LLM 又写代码又想测试效果更好——对更广泛的多 Agent 系统设计有参考意义:

当一个任务包含几个认知上不同的子任务时,拆分给不同的 Agent 分别处理,通常比让一个 Agent 全部承担更稳定。这不是因为多个 LLM 加在一起更聪明,而是因为每个调用更专注,减少了任务之间的干扰。

版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:11. AgentCoder:拆分角色,让代码生成和测试设计分开

本文链接:https://www.sshipanoo.com/blog/ai/code-agent-harness/11-AgentCoder/

本文最后一次更新为 天前,文章中的某些内容可能已过时!