WorkBuddy Bench 的任务集能不能直接复用——新增任务要改评分入口吗?

文章导读
先给判断:把 WorkBuddy Bench 现有的任务集直接复用到新增任务上,通常不需要改评分入口。前提是两条——新任务沿用旧任务已经在用的判定字段,并且落在评分侧的任务目录扫描范围内。只有当新任务需要一种旧任务从未有过的判定方式(例如原来只看补丁是否改到某个文件,新任务要看某个输出字段是否出现)时,才需要在评分侧加检查。判断边界可以先用一条最小任务试:只改任务ID和输入,跑一遍,看评分记录能不
📋 目录
  1. Ⅰ 在任务目录里找一条现有任务,拆出输入、期望行为、判定字段
  2. Ⅱ 复制成最小新任务,只改任务ID和输入
  3. Ⅲ 用同一智能体跑新旧任务,检查评分记录是否都生成
  4. Ⅳ 如果新任务需要新判定,再在评分侧加一条可验证检查
  5. Ⅴ 回跑旧任务,确认评分侧改动没有影响原有结果
A A

先给判断:把 WorkBuddy Bench 现有的任务集直接复用到新增任务上,通常不需要改评分入口。前提是两条——新任务沿用旧任务已经在用的判定字段,并且落在评分侧的任务目录扫描范围内。只有当新任务需要一种旧任务从未有过的判定方式(例如原来只看补丁是否改到某个文件,新任务要看某个输出字段是否出现)时,才需要在评分侧加检查。判断边界可以先用一条最小任务试:只改任务ID和输入,跑一遍,看评分记录能不能生成;能生成,说明改动停在任务侧;不能生成,先查扫描范围,再决定要不要动评分逻辑。

复用 WorkBuddy Bench 任务集的关键,是把“任务定义”和“评分逻辑”当成两层分别改动。新增任务先只动任务文件里的任务ID和输入,跑一次看评分记录是否生成;生成即说明评分入口无需改动。只有新任务需要旧任务没有的判定维度时,才在评分侧加一条可验证检查,并在加完后回跑旧任务对比通过状态和扣分原因。

在任务目录里找一条现有任务,拆出输入、期望行为、判定字段

动手前先确认任务侧到底定义了什么。通常仓库里会有一个任务目录,每条任务一个文件(YAML、JSON 或 Markdown 都有可能),评分侧按目录或索引文件扫描。先定位目录,再挑一条结构最简单的旧任务拆开看:

# 定位任务目录,路径以仓库实际结构为准
find . -maxdepth 3 -type d -name '*task*'
ls tasks/            # 示例目录名
head -n 60 tasks/example_task.yaml

拆一条任务时按四件事记录,字段名以仓库实际任务文件为准,不要照抄下面这份抽象命名:

  • 任务ID:评分记录和日志里用来对齐的那一列,常见命名是 task_id、id、name。
  • 输入:交给智能体的那段内容,可能是 prompt、instruction、input 之类的字段,也可能是一个输入文件路径。
  • 期望行为:描述“应该做什么”,可能是自然语言描述,也可能是需要满足的检查项列表。
  • 判定说明:告诉评分侧怎么算通过,可能是 rubric、checks、expected_files、test_command 这类字段,也可能压根没有,判定完全写死在评分代码里。

最后这一点很关键。如果旧任务的判定说明为空、判定全靠评分侧代码里的硬编码,那新增任务能不能复用评分入口,就取决于新任务的形态是否和那条硬编码匹配。可以用 grep 粗看评分侧引用了哪些字段:

grep -rn 'task_id\|expected_behavior\|rubric\|checks' `--include`='*.py' . | head -n 40

复制成最小新任务,只改任务ID和输入

把上一步那条旧任务复制一份,作为新增任务的最小骨架。这一步刻意只改两处:任务ID换成新的、输入换成新场景要考的内容,期望行为和判定说明先原样保留。目的是把变量压到最少,让“新增任务”这件事本身不影响判定逻辑。

# 最小任务骨架,字段名请替换成仓库里真实使用的名字
task_id: task_xxx_002          # 新的任务ID,不要和旧任务重名
input: |
  这里写新任务交给智能体的输入内容
expected_behavior: |
  沿用旧任务的期望行为描述,先不改判定维度
judge:
  checks:
    - 沿用旧任务的判定条目

存盘后先别碰评分逻辑,直接跑一次评分流程,观察两件事:控制台或日志里有没有出现新任务ID,评分记录里有没有新任务ID对应的条目。这两点只要有一个出现,就说明任务侧新增已经被评分侧识别,评分入口不需要因为“多了一条任务”而改动。如果没有出现,先跳到下一节查扫描范围,不要急着改评分代码。

用同一智能体跑新旧任务,检查评分记录是否都生成

用同一个智能体、同一套配置分别跑旧任务和新任务,把结果按下面这张表记下来。表里只写能从日志或评分记录文件里直接看到的内容,不要凭印象填写:

  • 任务ID:新旧两条各一行。
  • 补丁文件:本次运行产出的补丁路径,没有产出就写“无”。
  • 评分状态:评分记录里显示为通过、失败还是“无记录”。

新任务没有评分记录时,排查顺序建议是:先看任务文件的存放位置是否在评分侧扫描的目录内,再看文件名是否被命名规则或白名单过滤掉,最后看是否存在一个显式的任务清单文件(例如 tasks.yaml、index.json 之类)需要手动登记。前两项常见于“把文件放错子目录”,第三项常见于“目录里有文件但评分侧只读清单”。

WorkBuddy Bench 的任务集能不能直接复用——新增任务要改评分入口吗?
# 粗查扫描范围和清单
grep -rn 'tasks\|glob\|listdir\|walk' `--include`='*.py' scoring/ | head -n 30
ls tasks/ | grep -i index

如果确认文件在扫描目录内、也没被过滤,评分记录依然不生成,才需要往下看评分侧是不是对新任务形态有假设,比如必须带某个字段、必须命中某个预置检查项。

如果新任务需要新判定,再在评分侧加一条可验证检查

只有确认新任务需要旧任务没有的判定维度时,才动评分侧。做法是把改动限制成“新增一条检查”,不去改已有检查的判定条件。通用骨架分三步:读取补丁或产物、判断某个可验证行为是否出现、把结果写回评分记录。接口名、类名以仓库为准,下面只是结构性示例,不能当成真实 API:

def check_new_behavior(patch_text, record):
    # 1. 读取可验证对象:补丁内容或产物文件
    ok = '目标字符串' in patch_text
    # 2. 只新增一条检查结果,不动既有检查
    record.add_check(name='new_behavior', passed=ok,
                     reason='未命中目标字符串' if not ok else '')
    # 3. 写回评分记录
    return record

把这条检查挂在新任务上,而不是挂在所有任务上。可以给检查加一个适用条件,例如按任务ID或任务标签匹配,避免它被旧任务误触发。挂完后单独跑新任务,确认这条检查的通过或失败能在评分记录里看到具体原因,再进入下一步回跑旧任务。

回跑旧任务,确认评分侧改动没有影响原有结果

评分侧任何改动都要回跑旧任务。回跑时对比三列:任务ID、通过状态、扣分原因。重点是第三列,通过状态没变但扣分原因从“缺文件”变成“新检查未命中”,同样是回归问题。

对比方法建议直接保留改动前后的两份评分记录,按任务ID对齐后逐条看差异:

# 按任务ID对比改动前后的评分记录,字段名以实际记录为准
jq -r '.results[] | [.task_id, .status, (.reason // "")] | @tsv' before.json > before.tsv
jq -r '.results[] | [.task_id, .status, (.reason // "")] | @tsv' after.json  > after.tsv
diff before.tsv after.tsv

出现差异时,优先回退评分侧改动,保留任务侧新增,先确认“只加任务不改评分”能跑通,再把新检查用更窄的适用条件加回来。不建议在发现差异后直接调整旧任务的判定阈值来“对齐结果”,那会把任务定义和评分逻辑的边界重新搅在一起,下次新增任务又要重新判断一遍。