Trae Agent Selector Agent 实战指南:面向仓库级 Issue 解决的 Agent 集成补丁选择方法
【免费下载链接】trae-agentTrae Agent is an LLM-based agent for general purpose software engineering tasks.项目地址: https://gitcode.com/gh_mirrors/tr/trae-agent
本文以 Trae Agent 仓库中的 evaluation/patch_selection/README.md 为主体,结合其配套源码与示例数据,系统讲解 Selector Agent 的设计动机、输入输出格式、命令行参数、运行流程与结果解读。读完本文,你将能够在自己的 SWE-bench 类评测任务上,用 Trae Agent 的 Selector Agent 从大量候选补丁中自动挑选出正确修复补丁,并用配套脚本实时分析与可视化选择结果。
一、Selector Agent 是什么:解决"哪个补丁是对的"
Trae Agent 是一款面向通用软件工程任务的 LLM Agent。在多 Agent 或单 Agent 多次采样的软件开发流程中,一个 repository 级别的 issue 常常会产生多个候选补丁(candidate patches),其中既有正确的也有错误的。Selector Agent 正是为此设计的第一种基于 Agent 的集成推理(agent-based ensemble reasoning)方案:它将"从候选补丁中选出正确补丁"这一目标形式化为一个最优解搜索问题,并通过"生成(generation)—剪枝(pruning)—选择(selection)"的模块化 Agent 组合,应对两个关键挑战:
- 大规模集成空间(large ensemble spaces):候选补丁可能多达几十个,直接让模型在全部候选中做判断既消耗 token 又难以收敛;
- 仓库级理解(repository-level understanding):判断补丁是否正确,需要真正读懂 issue、阅读相关代码库上下文,甚至动手运行测试,而非仅凭 diff 文本表面判断。
在 Trae Agent 仓库中,这套方法被落地为一个独立可运行的评测子项目,位于 evaluation/patch_selection 目录,核心组件如下:
| 组件 | 路径 | 作用 |
|---|---|---|
| 入口脚本 | selector.py | 解析命令行参数、加载配置与候选数据、编排整个评测流程 |
| Agent 实现 | trae_selector/selector_agent.py | 定义 SelectorAgent 类、系统提示词、工具调用解析与答案提取 |
| 评测编排 | trae_selector/selector_evaluation.py | 分组、回归测试筛选、补丁去重、多数投票、并发调度 |
| 沙箱 | trae_selector/sandbox.py | 基于 Docker 启动 SWE-bench 镜像并在其中执行 agent 工具 |
| 工具集 | trae_selector/tools/tools | bash 与基于字符串替换的编辑工具,供 Agent 在容器内验证补丁 |
| 数据分析 | analysis.py | 聚合 statistics 输出并可视化各分组的选择成功率 |
二、整体工作流程
从源码结构(selector_evaluation.py)可以看出,Selector Agent 对一个 instance 的处理大致分为以下阶段:
- 切分组:将
num_candidate个候选按group_size切成若干组(如 50 个候选、每组 10 个,得到 5 组); - 预剪枝:先利用可选的回归测试结果(
regressions字段)保留通过回归测试的候选;再对候选补丁做清洗去重(基于clean_patch得到的规范形式); - 沙箱就绪:以该 instance 的 base commit 启动对应的 SWE-bench Docker 镜像,并把工具脚本复制进容器;
- Agent 选择:让 SelectorAgent 在容器内阅读代码、运行测试,最后以固定格式输出所选的
Patch-x; - 多数投票(可选):对每个候选组重复多次选择,取被选频率最高的补丁作为该组最终答案;
- 落盘:将所选补丁写入
patch目录、将是否正确写入statistics目录,同时把完整 LLM 交互历史写入log目录、把标准输出写入output目录。
三、环境准备
3.1 前置依赖
- Python 3.10+(仓库使用
pyproject.toml管理依赖,可用uv或pip安装); - Docker 与 Docker Python SDK(
sandbox.py通过docker.from_env()创建并管理容器); - 一个可用的 LLM 服务配置(通过
trae_config.yaml之类的配置文件提供,见下文第 5 节)。
3.2 下载 Python 3.12 运行时(必须)
README 特别强调:需要从官方文档提供的下载链接获取一个 Python 3.12 的预打包目录,并将其解压到如下位置:
evaluation/patch_selection/trae_selector/tools/py312这个 Python 3.12 运行时用于在 Docker 容器内执行 Agent 工具(bash 工具与字符串替换编辑工具)。从 selector_agent.py 可以看到,工具命令正是通过/home/swe-bench/py312/bin/python3 execute_str_replace_editor.py与/home/swe-bench/py312/bin/python3 execute_bash.py这样的路径在容器内触发的,因此该目录必须就位,否则工具调用会失败。
3.3 回归测试(可选)
如果你需要对候选补丁做回归测试选择,README 说明可参考 Agentless 的 SWE-bench 回归测试流程(对应其 README 中的README_swebench.md)。这里的关键约定是:结果条目中的regression字段描述测试结果——
- 空数组
[]:该补丁通过了全部回归测试; - 非空数组:该补丁导致了测试失败,数组内为失败的具体测试名。
3.4 输入数据准备
- 实例文件(如
swebench-verified.json):SWE-bench 风格的问题实例列表,每个实例需包含instance_id、problem_statement、base_commit等字段(源码中分别用于构造镜像名、注入 issue 描述与 checkout 基线提交); - 候选补丁文件:JSON Lines 格式,详见下一节。
四、输入格式:候选补丁 JSONL
补丁候选存放在一个 JSON Lines 文件中,每行一个实例,结构如下:
{ "instance_id": "django__django-14017", "issue": "Issue description....", "patches": [ "patch diff 1", "patch diff 2", "...", "patch diff N" ], "success_id": [ 1, 0, "...", 1 ], "regressions": [ [regression_test_names for patch diff 1..], [regression_test_names for patch diff 2..], "...", [regression_test_names for patch diff N..] ] }字段说明:
| 字段 | 含义 | 是否必填 |
|---|---|---|
instance_id | 与实例文件中一致的实例 ID,用于关联与文件命名 | 是 |
issue | Issue 描述文本 | 是 |
patches | N 个候选补丁的 diff 字符串列表 | 是 |
success_id | 与patches一一对应的正确性标签,1表示该补丁是正确的,0表示错误 | 是 |
regressions | 与patches一一对应的回归测试结果列表,空数组表示通过全部回归测试 | 否 |
说明:
success_id的作用在于离线评估——一旦 Selector Agent 选出某个补丁,就可以立刻对照success_id判断这次选择是否正确。regressions为可选项;如果你已经用 Agentless 做过回归测试选择,可以在这里填入筛选出的回归测试名。若数据中没有regressions字段,selector.py 会自动为每个候选补丁填充空数组。
仓库自带的示例数据 evaluation/patch_selection/example/example.jsonl 就是一个真实样例:astropy__astropy-14369(astropy 的 CDS 单位解析 bug),包含 10 个候选补丁,success_id为[0, 1, 1, 0, 1, 1, 1, 0, 1, 1],其中 7 个是正确的、3 个是错误的。
五、运行 Patch Selection
5.1 标准命令
在仓库根目录执行:
python3 evaluation/patch_selection/selector.py \ --instances_path "path/to/swebench-verified.json" \ --candidate_path "path/to/patch_candidates.jsonl" \ --result_path "path/to/save/results" \ --num_candidate NUMBER_OF_PATCH_CANDIDATES_PER_INSTANCE \ --max_workers 10 \ --group_size GROUP_SIZE \ --max_retry 20 \ --max_turn 200 \ --config_file trae_config.yaml \ --model_name MODEL_NAME_IN_CONFIG_FILE \ --majority_voting5.2 参数详解
对照 selector.py 中的 argparse 定义,各参数的默认值与说明如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
--instances_path | swe_bench/swebench-verified.json | SWE-bench 实例 JSON 文件路径 |
--candidate_path | 必填 | 候选补丁 JSONL 文件路径 |
--result_path | 必填 | 结果保存目录(会在其中创建log/output/patch/statistics四个子目录) |
--num_candidate | 10 | 每个实例的候选补丁数量 |
--max_workers | 10 | 并发处理实例的最大进程数(底层使用ProcessPoolExecutor) |
--group_size | 10 | 每个分组的候选补丁数量 |
--max_retry | 3 | 单个实例处理失败后的最大重试次数(每次重试会重新启动沙箱容器) |
--max_turn | 50 | Selector Agent 单次选择的最大对话轮数 |
--majority_voting | 关闭 | 是否启用多数投票模式(BooleanOptionalAction) |
--config_file | config.yaml | LLM 配置文件路径 |
--model_name | default_model | 配置文件中要使用的模型名 |
5.3 LLM 配置要求
selector.py启动时会读取--config_file指定的配置文件(仓库提供trae_config.yaml.example与trae_config.json.example作为模板),并校验:
- 配置中必须包含
models字段,否则抛出No models found in config file.; --model_name必须存在于models中,否则抛出Model {name} not found in config file.。
随后它会取出对应的llm_config并调用resolve_config_values()完成环境变量等值的解析,最终用于构造 LLMClient 与 Agent 的工具集。
5.4 group_size 与多数投票:应对大规模集成空间
README 给出了一个典型调优场景:如果候选补丁很多(例如 50 个),可以将group_size设为 10。此时 50 个候选会被切成 5 组(selector_evaluation.py中的range(0, num_candidate, group_size)逻辑),每组独立运行一次选择,每组产出一个所选补丁;如果需要,再对这 5 个结果做二次选择。
--majority_voting是可选项。开启后,对每个候选组会进行多次独立的选择实验,最终以被选中频率最高的补丁作为该组的最终答案。从 selector_evaluation.py 的实现看,多数投票模式还有提前终止优化:当某个补丁的选中次数超过num_candidate / 2时即停止继续投票,降低开销。README 也明确提醒:该模式会消耗更多 token,适合对选择质量要求高、预算充足的场景。
六、运行结果与产物解读
6.1 结果目录结构
README 说明,用 example.jsonl 运行后,在result_path下会得到如下文件结构:
├── log │ └── group_0 │ └── astropy__astropy-14369_voting_0_trail_1.json ├── output │ └── group_0 │ └── astropy__astropy-14369.log ├── patch │ └── group_0 │ └── astropy__astropy-14369_1.patch └── statistics └── group_0 └── astropy__astropy-14369.json各目录含义:
| 目录 | 内容 | 用途 |
|---|---|---|
log | 每个实例每次选择的LLM 交互历史(JSON,由TrajectoryRecorder写入,文件名形如<instance_id>_voting_<idx>_trail_<n>.json) | 审计、调试与复盘 Agent 的推理过程 |
output | 每个实例处理过程的原始标准输出与标准错误(.log文件) | 排查运行错误、查看重试过程 |
patch | 被选中的补丁(diff 文本,文件名形如<instance_id>_<n>.patch) | 直接可用的修复补丁产物 |
statistics | 选择结果统计(JSON:instance_id、patch_id、is_success、is_all_success、is_all_failed) | 判断所选补丁是否正确、供分析脚本聚合 |
6.2 断点续跑与跳过逻辑
从 selector_evaluation.py 的实现可以看出两个值得注意的行为:
- 断点续跑:如果某实例某分组的 statistics JSON 已存在且非空,则该组会被跳过(
has already been processed. Skipping...),因此中断后重跑不会重复消耗 token; - 全对/全错跳过:如果一组候选全部正确(
all_success)或全部错误(all_failed),则无需 Agent 选择,直接取第一个候选并写入统计(is_all_success/is_all_failed标记为 true)。这也意味着statistics的need_to_select概念指的是"确实需要靠选择来区分正误"的分组。
6.3 用 analysis.py 可视化统计结果
selector.py运行过程中(或运行结束后),都可以用分析脚本实时查看中间结果:
python3 analysis.py --output_path "path/to/save/results"analysis.py 会扫描statistics目录下的所有分组,聚合出以下指标并以 rich 表格打印,同时写入analysis.csv:
| 指标 | 含义 |
|---|---|
total | 该分组已处理的实例数 |
completion_rate | 完成率(total除以总实例数,脚本中默认分母为 500,可按需调整) |
all_success/all_failed | 候选全部正确 / 全部错误而跳过的实例数 |
need_to_select | 真正需要 Agent 做出选择的实例数 |
success_selection | 选对(is_success == 1)的实例总数 |
success_selection_in_need_to_select | 在"需要选择"的实例中选对的个数 |
success_rate_in_need_to_select | 需要选择场景下的选择成功率 |
success_rate_among_all | 全量实例上的成功率 |
表格中会用下划线加粗标出success_rate_in_need_to_select与success_rate_among_all最高的分组,方便横向对比不同分组/不同投票策略的效果。也支持通过--group_id只分析某个指定分组。
七、源码级原理:Selector Agent 是怎么"选"的
7.1 系统提示词与四步工作流
selector_agent.py 中的build_system_prompt将 Agent 定义为"专家代码评估者"(expert code evaluator),并给出明确的工作流程:
- 理解 Issue 与代码库:阅读 issue 描述,必要时检查 issue 引用的代码、每个补丁修改的原始代码、同一文件未改动部分,以及与被改代码交互的相关文件、函数、模块;
- 分析候选补丁:逐个分析每个补丁的逻辑与意图,判断改动是否与 issue 描述及编码规范一致;
- 验证功能(可选但推荐):必要时编写并运行单元测试,评估每个补丁的正确性与潜在副作用;
- 选择最佳补丁:选出"以最小引入新问题风险解决 issue"的补丁。
提示词还强制规定了三条原则与输出格式:不得回避选择;不得提出新补丁;候选集中至少存在一个正确补丁。最终报告必须形如:
### Status: succeed ### Result: Patch-x ### Analysis: [Explain why Patch-x is correct.]Agent 的输入由三部分组成:上述系统提示词 + 代码库路径与 issue 描述 + 按Patch-1、Patch-2……编号的候选补丁列表(selector_agent.py)。
7.2 工具调用与答案解析
SelectorAgent 只配备两个工具(selector_agent.py):
bash:在容器内执行任意命令(底层对应 trae_selector/tools/tools/execute_bash.py);str_replace_based_edit_tool:基于字符串替换的代码编辑工具(对应 trae_selector/tools/tools/execute_str_replace_editor.py)。
在每一轮对话中(最多max_turn轮):
- LLM 返回文本或工具调用;
- 若返回的工具名合法,
parse_tool_response会把参数拼接成容器内命令,例如cd /home/swe-bench/tools/ && /home/swe-bench/py312/bin/python3 execute_str_replace_editor.py --command ...,通过沙箱会话执行并读回Tool Call Status: 0/-1与输出(selector_agent.py); - 若返回文本中匹配到
Status: success/succeed/...与Result: Patch-x的模式(正则见 selector_agent.py),则结束循环,返回对应补丁;若Patch-x编号不合法则回退到第一个候选。
每一轮交互都会被TrajectoryRecorder完整记录到log目录,供事后复盘。
7.3 沙箱:仓库级理解的"动手"基础
trae_selector/sandbox.py 负责为每个实例构建隔离环境:
- 镜像名为
swebench/sweb.eval.x86_64.<instance_id 中 "__" 替换为 "_1776_">:latest; - 启动后执行
git checkout <base_commit>,把代码库恢复到 issue 对应的基线提交; - 将
trae_selector/tools目录通过docker cp复制到容器内/home/swe-bench/,与 py312 运行时配合形成可执行的 Agent 工具环境; - 每次选择前后都会执行
git reset --hard HEAD,确保代码库状态干净。
7.4 候选预处理:回归筛选与去重
在启动 Selector Agent 之前,selector_evaluation.py 会对候选做两道预处理:
- 回归测试筛选:跳过 diff 为空串的候选;若某个候选的
regressions为空(即通过了回归测试),则优先只保留这些通过回归的候选(candidate_list_regression); - 补丁去重:用 utils.py 中的
clean_patch将每个补丁规范化为"去除注释与空白后的增删行序列",以此作为去重键,保证同一思路的多个等价补丁只保留一份。
八、常见问题与注意事项
- 运行前务必确认 py312 目录就位:未解压 Python 3.12 包是工具调用失败的最常见原因;
- 镜像缺失:Selector Agent 依赖本机已存在的
sweb.eval.x86_64.*SWE-bench 镜像,需要提前按 SWE-bench 官方流程构建对应实例的 Docker 镜像; - token 成本控制:候选越多、
--majority_voting开启、--max_turn越大,token 消耗越高。建议先用小规模候选(如--num_candidate 10 --group_size 10)跑通流程,再逐步放大; - 结果可复现:
log目录保留了全部交互历史,statistics目录支持断点续跑,出现异常时可结合output目录的原始日志定位问题; - 配置校验:确保
--config_file中的models非空且--model_name在其中,否则入口脚本会直接报错退出。
九、结语
Selector Agent 把"从候选补丁中找正确修复"建模为一次在真实代码库环境中的推理搜索,用模块化的生成—剪枝—选择流程化解了集成空间过大与仓库理解不足两大难题。结合本仓库的 selector.py、example.jsonl 与 analysis.py,你可以立即在自己的 SWE-bench 评测上复现这一流程,并将其作为 Trae Agent 各类软件工程任务评测链路中的"最后一公里"组件。
【免费下载链接】trae-agentTrae Agent is an LLM-based agent for general purpose software engineering tasks.项目地址: https://gitcode.com/gh_mirrors/tr/trae-agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考