跳到主要内容

评测与比较结果

评测需要可复现的输入,也需要能解释的结果。EnvLoop 分别记录执行状态、verifier reward、结构化输出和评分覆盖率,帮助区分运行失败、模型得分低和测量缺失。

先运行一个小评测​

  1. 选择可读的 Dataset revision 及其固定 Runner。
  2. 选择包含 Runner 所需模型或 Agent 参数的 Profile。只有 Runner 实际读取的参数才会生效。
  3. 先提交一道题,检查日志、reward 和产物,确认流程正确后再提交完整 Dataset。
  4. 对比实验保持 Dataset、Runner、Task 集合和 attempts 一致,同时记录 Profile、模型与 request ID。
el job submit --dataset DATASET_NAME@VERSION --attempts 2 --profile team/eval@1
el job get JOB_ID
el job result JOB_ID

所有资源占位符都应替换成目录中的实际值。Attempts 是独立执行次数,会增加工作量。提交成功表示开始执行,不代表 Agent 已通过 benchmark。

按顺序读取结果​

进入 Jobs → 目标 Job → Metrics。先看已完成和已评分的 attempts 数,再看聚合指标与每个 Task 的结果。reward 缺失或异常时,打开对应 Trial。

信号回答的问题
Job/Trial 状态执行完成、失败,还是被取消?
退出码和错误报告了什么执行问题?
Verifier reward声明的评测给出多少分?
结构化结果产生了哪些额外维度或 judge 摘要?
评分覆盖率请求的评测中,有多少实际产生数字 reward?
产物持久化文件能否独立查看和下载?

completed、succeeded 描述执行结果,不代表 reward 为 1。failed Job 仍可能包含有效得分。返回 checkpoint 或 artifact 引用,本身也不能证明评测成功。

聚合指标​

字段含义
score所有有数字 reward 的 attempts 的算术平均值
pass所有已评分 reward 都为 0 或 1 时的平均值
pass@k完整评分成员中,至少一次 attempt 通过的比例
pass^k完整评分成员中,请求的每次 attempt 都通过的比例

这里的 k 是每个成员请求的 attempts 数。只有恰好派发了该数量、且每次都有分数的成员,才进入两个 k 指标的分母。没有完整评分成员时,两者均为 null。非二值 reward 会让二值指标为 null;没有任何已评分 attempt 时,所有指标均为 null。Console 显示实际 k,例如 pass@2 / pass^2,通过率显示为百分比。Job scores、逐 Task 结果与项目排行榜统一展示主分:0~1 使用百分比(0.75 → 75%、1 → 100%),超出该范围保留原始尺度。API 的 score 仍是 reward 均值,独立综合分和维度沿用自身单位。

例如每题运行两次,A 的 reward 为 [1, 0],B 为 [1, 1],C 为 [0, 缺失]。API 的平均分和 pass 都是 3/5 = 0.6,Console 显示为 60%。只有 A、B 进入 k 指标,所以 pass@2 = 1.0、pass^2 = 0.5。C 缺失的一次不会被当成零,高 pass@2 也不代表全部请求题目已经完整评测。

与 benchmark 估计量的关系​

同一题做 n 次二值评测、其中 c 次通过时,一般公式为 pass@k = 1 - C(n-c,k)/C(n,k)、pass^k = C(c,k)/C(n,k),要求 1 ≤ k ≤ n。先计算每题结果,再按题目等权平均。例如 n=5、c=3、k=2 时,结果为 90% 和 30%;将实测成功率直接代入 1-(1-p)^k 或 p^k 会得到不同的估计值。

Job 目前只提供 n=k 的特例:至少一次成功与全部成功,不提供独立选择 k 的多点曲线。参考 Terminal-Bench 使用的 Harbor pass@k 实现及 τ-bench pass^k 实现。Harbor 把缺失 verifier reward 算作失败;EnvPlatform 保留未知并报告覆盖率。只有缺失处理政策与评测协议一致时,分数才能直接比较。

报告分数时同时报告覆盖率​

API 的每个聚合结果都有 score_counts:

  • total:请求 Task 数 × 每题 attempts,包含尚未派发的槽位。
  • scored:具有数字 reward 的 attempts。
  • missing:请求中没有 reward 的 attempts,包括尚未派发、等待中或运行中的尝试。
  • invalid:已经结束但没有 reward 的 attempts。
  • total_members:选中的 Dataset 成员数。
  • complete_members:所有请求 attempts 都已评分的成员数。

建议记录“score 0.6,5/6 attempts 已评分,2/3 成员完整”,而不只写“score 0.6”。比较得分时同时检查失败与缺失数量,尤其要关注不同模型的超时比例。部分覆盖不能代表完整测试集的成绩。

结构化指标​

受支持的声明结果文件可以提供 composite、命名维度和 judge 摘要。Trial 的 Metrics 会把它们与 reward 一起展示,但 Job 排名的评分来源仍是 verifier reward。结构化提取不可用或无效时,可继续在 Artifacts 查看原始输出。

比较自定义维度时,应确认名称、量纲、优劣方向和 verifier 版本一致。两份结果都叫 accuracy,不足以证明它们测量同一件事。

查看项目内排行榜​

在 Jobs → Metrics → Project leaderboard 只读查看已保存的结果、排名、得分与覆盖率;Console 不提供添加结果的写入按钮。

排行榜比较主动提交、且冻结 Dataset revision、Runner 引用、Task 名称/digest 和 attempts 都相同的 Job,模型和 Profile 可以不同。每行包括排名、模型或 Job ID、得分、已评分数、缺失数和已有 composite 指标。点击行内链接可回到来源 Job。

失败但有部分得分的 Job 也可能上榜,所以不能忽略缺失数量。重复添加同一个 Job 会返回已保存的快照。榜单仅在项目内可见,不会自动发布到公开网站。公开提交流程见研究与排行榜。

从失败决定下一次实验​

执行错误先看 stderr 和输入兼容性;reward 为 0 时看 verifier 输出与最终产物;reward 缺失时,判断失败发生在执行、评测还是产物收集。每次只改变一个受控变量,必要时发布新 Profile 版本,再用新 request ID 提交。保留原 Job 作为比较依据。

评测训练后的模型​

训练和评测是独立的 Job。连接方式是:在训练前后,用同一份留出集评测,并按任务选择评测阶段:

阶段做法适用于
训练后检查托管 Job 已保存的 checkpoint,再用正常 inference API 评估相同的留出输入选择 checkpoint 并验证泛化;不提供交互式训练中采样
部署后用相同 prompt 和生成参数分别调用端点的 /sft 与 /base 别名(推理)用自己的评分器做前后对比
Agent benchmarkel job submit --dataset ... 搭配 Profile带 verifier 和 pass@k 的多步 Agent 任务

下面是对端点做前后对比的最小脚本。把评分函数换成你任务的 verifier,留出集不要进入训练数据:

import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api.envloop.ai/v1/job/YOUR_JOB_ID/Inference",
api_key=os.environ["ENVLOOP_API_KEY"], timeout=120)
rows = [json.loads(line) for line in open("heldout.jsonl")] # {"prompt": ..., "answer": ...}

def score(model):
correct = 0
for row in rows:
out = client.chat.completions.create(
model=model, messages=[{"role": "user", "content": row["prompt"]}],
max_tokens=256, temperature=0).choices[0].message.content or ""
correct += out.strip() == row["answer"]
return correct / len(rows)

for alias in ("YOUR_ENDPOINT_MODEL/base", "YOUR_ENDPOINT_MODEL/sft"):
print(alias, score(alias))

用 Agent benchmark 评测训练后的模型​

推理端点同时提供 Anthropic Messages API,托管的 Claude Code Agent 可以直接使用你训练的模型。先部署 checkpoint,再发布一个以该端点为模型的 Profile:

{
"schema_version": "envplatform.profile/v2",
"name": "team/eval-my-model",
"version": "1",
"secret_params": ["MODEL_API_KEY"],
"spec": {
"params": {
"AGENT_NAME": "claude-code",
"AGENT_VERSION": "2.1.285",
"MODEL_PROTOCOL": "anthropic",
"MODEL_BASE_URL": "https://api.envloop.ai/v1/job/YOUR_INFERENCE_JOB_ID/Inference",
"MODEL_NAME": "YOUR_ENDPOINT_MODEL/sft",
"MODEL_API_KEY": "YOUR_ENVLOOP_KEY",
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "4096",
"CLAUDE_CODE_EFFORT_LEVEL": "medium"
}
}
}
el profile create team/eval-my-model 1 --file eval-profile.json
el job submit --dataset DATASET_NAME@VERSION --profile team/eval-my-model@1 --attempts 2
  • 将 CLAUDE_CODE_EFFORT_LEVEL 设为模型接受的推理强度。否则 Claude Code 会请求 high,qwen38-27b@1 会以 400 “Unexpected reasoning effort” 拒绝;Qwen3.8 接受 low、medium 和 xhigh。
  • 托管 Claude Code Agent 仅在 EnvLoop 为你的项目开通后可用。若提交被拒绝,请联系 EnvLoop 支持;你也可以按上面的方式设置 ANTHROPIC_BASE_URL 和 ANTHROPIC_MODEL,自行运行 Claude Code 调用该端点。
  • MODEL_API_KEY 是有权调用该端点的 EnvLoop Key,建议使用只限该端点的推理专用 Key;它以 Secret 形式保存在 Profile 中。
  • 再发布一个 MODEL_NAME 为 YOUR_ENDPOINT_MODEL/base 的 Profile,用相同的 Dataset、Runner 和 attempts 运行,即可在项目排行榜上比较训练前后。
  • Claude Code 的指令和工具定义会占用较多上下文。CLAUDE_CODE_MAX_OUTPUT_TOKENS 要足够小,使提示词加输出不超过推理 profile 的上下文(qwen38-27b@1 与 glm53-flash@1 为 32,768 token);较长的多步任务仍可能超出。
  • 端点需要正在运行或可被唤醒,冷启动会推迟 Agent 的第一步。推理时间照常计入端点费用。

当前限制:

  • 平台不会在训练结束后自动发起评测。每一轮需自行记录:用 agent_run / agent_round 标记训练 Job(模型循环),并用同一 run 名称保存评测 Job ID 或分数。
  • 在训练用过的 prompt 上分数更高,不能证明模型进步。比较前先冻结留出集和评分器。