编写 Evaluator
独立打分;evaluation 块与 artifacts 怎么接。
Evaluator 只负责算法与真值,不启 agent、不持宿主密钥。PASS/FAIL 只能从这里来(再写进 Result)。
让 agent 代写
npx skills add ZJU-REAL/ageval --skill ageval-config-package
npx skills add ZJU-REAL/ageval --skill ageval-sdk-harnessageval-config-package 覆盖 evaluation 段与脚本打分;evaluator.py 里还要 Agent.session(LLM-as-judge)才需要 ageval-sdk-harness。装好后把打分需求说给本机 coding agent,让它写完即可。
task.yaml 片段
artifacts:
publishable:
- id: session-output
producer: run
path: artifacts/session-output.json
media_type: application/json
evaluation:
runtime: python
entrypoint: evaluator:evaluate
network: none
# tmpfs_mb: 256 # 可选;环境内 evaluator /tmp(MiB),省略则 32。不是 limits.*
inputs:
- artifact: session-output
target: artifacts/session-output.json
# 参考答案示例:
# - package_path: evaluation/gold.json
# target: gold.json
output:
format: json| 点 | 说明 |
|---|---|
| 阶段边界 | run.py 结束并封存 solver 后才上传评测输入与参考答案 |
| 参考答案 | 放 evaluation/,evaluate 阶段才 upload |
| artifact id | 必须和 run.py 实际写出的文件对上 |
tmpfs_mb | 只改环境内 evaluator /tmp;省略 32 MiB。大 snapshot 在 task 上声明,不要写进 limits |
evaluator.py 在 parent 子进程里跑(与 run.py 同一形态)。配置可写 evaluate_host.isolated: true(Current:docker)另起评分容器;参考答案只上传至该评分环境。需要多个、安装内容不同的评分镜像时,在 task.yaml 写 evaluation.environments,用 inputs["scoring"].exec(<name>, argv) 或 Agent.session(..., environment=<name>) 指定名字;未用到的名字不启动。省略该表表示单个默认评分环境(或复用 run 环境),此时 scoring.exec 在该默认评分环境中执行。写出命名表则必须指定名字;未知名字直接报错,不启动容器。
两种评分策略
默认是确定性脚本:读产物和 evaluation/ 里的参考答案,返回 {status, score, metrics};status 只取 PASS 或 FAIL。低分是 FAIL。其它 status(含 ERROR)让这次运行记 ERROR。run 阶段触到 limit 时,裁决仍是这份返回值,result.json 的 limit 记下对应的配额键名。环境起不来、evaluator 崩了记 ERROR。不必调 Agent。没有 evaluation/observation.jsonl。可选额外键 checks(helper evaluation_check)会写成 evaluation/checks.json 给 Verifier;bind 忽略它。没有 checks 时 Verifier 仍是 result.json 与文件树。
可选 LLM-as-judge:同一份 job profiles.yaml 再写一个角色(如 judge),task.yaml 的 agent_profiles 列入同一 id。参考答案 已经 upload 之后,evaluator.py 可以 Agent.session("judge").invoke(...)。提示词归 dataset。invoke 不得改 profile_id / executor。
from ageval_sdk import evaluation_check
def evaluate(inputs):
# inputs["agent"] 在本机环境上会注入(parent socket);没有就走脚本路径
...
return {
"status": "PASS",
"score": 1.0,
"metrics": {},
"checks": [
evaluation_check(
"files",
title="artifact files",
status="PASS",
script="evaluator.py",
),
],
}checks 可省略。省略则 parent 不写 evaluation/checks.json。某一行 check 可以是 FAIL、顶层仍是 PASS——bind 只读 status / score / metrics。script 是 dataset 内路径(成员相对,或 tasks/<id>/…);Verifier 从 dataset 打开,不把脚本拷进 Attempt 归档。
约束:
| 点 | 说明 |
|---|---|
| PASS | 仍只看这次返回值(status / score / metrics) |
| 轨迹 | evaluate 阶段的步写入 evaluation/observation.jsonl(省略 user 行,避免参考答案进 evidence)。不并进根 trajectory.jsonl |
| 调用预算 | limits.agent_invocations 只计 run 阶段的 invoke。judge 的 invoke 由 limits.evaluate_seconds 封顶 |
| 环境 | SDK session 走 parent 的 Unix socket。ACP attach_stdio 打 打分 Host(缺省 = run 环境;job evaluate_host.isolated: true 时是 docker 第二实例)。有 evaluation.environments 时 ACP 必须 session(id, environment=<name>);openai-http / anthropic-http 忽略 environment=(出站仍在 parent)。不要把 Agent Service socket bind-mount 进容器 |
多 stage 打分 Host
顺序阶梯(审计 / 行为 / 编译)需要不同已装内容时,不要复用 environment/evaluate.Dockerfile。成员 yaml:
evaluation:
environments:
audit:
docker_image: python:3.12-slim # 已有 OCI 标签
verification:
dockerfile: environment/evaluate/verification/Dockerfile配方文件放 environment/evaluate/<name>/,不要放 evaluation/(那是参考答案)。写出该表则忽略 evaluate.Dockerfile / evaluation.docker_image。job 必须 evaluate_host.isolated: true 且 environment: docker。
from ageval_sdk import evaluation_check
async def evaluate(inputs):
scoring = inputs["scoring"]
audit = await scoring.exec("audit", ["python", "/attempt/evaluation/audit.py"])
if audit.exit_code != 0:
return {
"status": "FAIL",
"score": 0.0,
"metrics": {"stage": "audit"},
"checks": [
evaluation_check(
"audit",
status="FAIL",
script="evaluation/audit.py",
environment="audit",
exec_result=audit,
),
],
}
async with inputs["agent"].session("judge", environment="verification") as session:
reply = await session.invoke(inputs["parameters"]["verify_prompt"])
ok = bool(reply.get("ok"))
return {
"status": "PASS" if ok else "FAIL",
"score": 1.0 if ok else 0.0,
"checks": [
evaluation_check(
"audit",
status="PASS",
script="evaluation/audit.py",
environment="audit",
exec_result=audit,
),
],
}exec 的 argv 是列表;stdout / stderr / exit_code 来自那个容器内。第一次用到某名字才 start 并 upload 快照和参考答案。未知名、run 阶段写了名字、或表里有名字时 ACP 省略名字:一次失败,不 start。v1 只顺序 stage,不要并发 exec 与 session 打同一名字。
不调 Agent.session = 脚本路径。Verifier 是 evaluation 文件树;选中 checks.json 时在预览里渲染检查点。若同时有 evaluate 阶段的 observation.jsonl,用页签行右侧的 Trajectory / Files 切换(默认轨迹)。result.json 仍在文件树。本地查看用 ageval view。