OpenRouter 教程:如何为大模型做基准测试
How to Benchmark LLMs
- 1OpenRouter 发布大模型基准测试教程,主张用自家业务的任务和代码校验来选模型
- 2在其 60 个合成任务实测中,GPT-6.1 Sol 三轮通过 180/180,每百次响应约 $0.2449
- 3DeepSeek V4.1 Flash 成本最低,每百次约 $0.00394,通过 157/180,另有 14 次截断
- 4其实测排名与公开榜单 Artificial Analysis 相关性弱,合并 Spearman 仅 0.109
公开榜单排名与企业自身任务上的表现相关性很弱,模型选型证据应来自贴合自家业务输入输出的实测,而非榜单名次。
- 影响:同一组任务里 DeepSeek 每百次响应约 $0.00394、GPT-6.1 Sol 约 $0.2449,按所需通过率选型直接决定预算;输出格式不合规会带来无效花费,Sonnet 有 66 次格式失分;小规模自建评测试跑成本仅几美元,实测门槛在下降。
- 参考:可考虑从自家高频流程里挑 10 个左右带标准答案的样例,用随文脚本小预算试跑候选模型;值得同时记录通过率、每百次响应实付成本和截断率,再据此确定上线型号。
- 依据:数据来自 OpenRouter 于 2026 年 10 月 20 日完成的 60 任务实测,10 个模型各跑三轮;榜单对比基于其当日 Artificial Analysis 快照,作者自认样本有限,不能推出榜单整体可靠性。
利用来自你应用程序输入和输出格式的证据来选择模型。通过 OpenRouter 运行相同的任务,并比较评分准确率、计费成本和请求时间。在我们所测试的契约与设置下,GPT-6.1 Sol 在 60 个合成任务上经三次重复通过了 180/180 次试验。
TL;DR
-
代码检查衡量正确性与输出合规性。
-
Sol 在我们的合成任务集上通过了 180/180 次试验;DeepSeek 的响应成本最低,通过 157/180 次。
-
与公开排名的一致性较弱,Spearman 相关系数为 0.109。
-
在信任某个分数之前,请检查每个任务运行了多少次、返回了多少个答案,以及每笔账单是否经过核实。
先定义行为,再定义其检查。
第 1 步. 编写答案可被脚本检查的任务
一个任务需要输入、预期答案和输出契约。对于发票,需指定包含哪些行、舍入方式以及可接受的货币后缀。
我们在最终运行之前编写了全部 40 个基线任务和 20 个困难任务。
| 类别 | 示例 | 检查 |
|---|---|---|
| 发票算术 | 折扣后未付款行的总额 | 小数总额与舍入 |
| 日期与日程 | 转换时间戳或列出匹配的日期 | 精确的时刻或日期列表 |
| 电子邮件提取 | 将字段提取为 JSON | 键、类型和值 |
| Python 函数 | 针对隐藏输入实现一个函数 | 在隔离运行时中的结果 |
| 输出约束 | 在指定限制内生成文本 | 长度、词汇和格式 |
| 退款决策 | 在边界处应用书面政策 | 对每个订单的决策 |
独立计算参考答案。将提示调优案例与最终评估分开。退款案例测试书面决策,而不执行交易。
第 2 步. 用代码评分,并检查评分器
对 APPROVE 使用精确匹配,对 JSON 使用模式/值检查。仅规范化被允许的差异。当你的消费方只需要数字时,接受数字周围的文字会掩盖失败。
测试已知正确、错误和格式错误的响应。对于退款阈值,要包含恰好 $200 和 30 天的情况,以及刚好高于各边界的值。
我们的开发版检查器拒绝了有效的 Python 代码,因为它遗漏了 ord 和 type。我们在最终研究之前修正了它,指定为带资源限制的 CPython 3.12.10/WASI。否则,检查器的失败会被算作模型的失败。
完整研究运行器会隔离生成的代码,并在缺少沙箱设置时停止。教学示例不执行任何生成的代码。
第 3 步. 运行三任务 Python 示例
下载配套 ZIP。解压之前,先将其 SHA-256 校验和与以下值比较:
a38ee17a2eb7090f9f4849a605cc8214691c889ca0ae40c121259603592178e8PowerShell:
Get-FileHash .\benchmark-reader-companion.zip -Algorithm SHA256Linux 或 macOS:
# Linux
sha256sum benchmark-reader-companion.zip
# macOS
shasum -a 256 benchmark-reader-companion.zip如果两者不一致,请停止并检查下载。一致后再解压 ZIP。你需要 Python 3.12 或更高版本。基于标准库的教学运行器、JSON 示例和比较在 Windows x64 和 Linux 上通过了离线检查。macOS 尚未测试。捆绑的完整研究沙箱和原生 Ori 安装仅支持 Windows x64。
在解压出的文件夹中:
python verify_package.py
python three_tasks.py check该检查会打印 OFFLINE reference and grader checks passed; zero inference calls。完整脚本按文件顺序附后。其配套模块负责处理请求、持久化和报告。
"""Three exact contracts; run from the extracted companion (standard library)."""
import argparse
from datetime import datetime, timezone
from decimal import Decimal
import json
from pathlib import Path
import re
from reader_core import execute, reconcile, report, read, load_config, finish_grade
TASKS = [
{"id": "invoice", "prompt": "Two unpaid lines cost 3 x 12.50 USD and 2 x 4.25 USD. Return only their total with exactly two decimal places.", "expected": "46.00"},
{"id": "utc", "prompt": "Convert 2026-10-18T10:30:00+02:00 to UTC. Return only YYYY-MM-DDTHH:MM:SSZ.", "expected": "2026-10-18T08:30:00Z"},
{"id": "refund", "prompt": "Policy: approve only if amount <= 200 USD and age <= 30 days. Amount=200 USD; age=30 days. Return only APPROVE or DENY.", "expected": "APPROVE"},
]
def refund_policy(amount, days):
return "APPROVE" if Decimal(str(amount)) <= 200 and days <= 30 else "DENY"
def grade(task, text, finish):
terminal = finish_grade(finish)
if terminal:
return terminal
if not isinstance(text, str) or not text.strip():
return {"passed": False, "classification": "empty"}
text = text.strip()
patterns = {"invoice": r"\d+\.\d{2}",
"utc": r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z",
"refund": r"APPROVE|DENY"}
valid = bool(re.fullmatch(patterns.get(task["id"], r"\d+\.\d{2}"), text))
passed = valid and text == task["expected"] and finish == "stop"
return {"passed": passed, "classification": "pass" if passed else
("incorrect" if valid else "malformed")}在使用某个分数之前,请检查其参考答案与拒绝规则。这些离线测试数据覆盖边界决策、无效格式和被截断的答案,且不调用任何模型。
def offline():
money = Decimal(3) * Decimal("12.50") + Decimal(2) * Decimal("4.25")
assert format(money, ".2f") == TASKS[0]["expected"]
utc = datetime.fromisoformat("2026-10-18T10:30:00+02:00")
assert utc.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ") == TASKS[1]["expected"]
assert refund_policy(200, 30) == TASKS[2]["expected"]
for amount, days, expected in [(200.01, 30, "DENY"), (200, 31, "DENY"),
(199.99, 29, "APPROVE"), (0, 0, "APPROVE")]:
assert refund_policy(amount, days) == expected
for task in TASKS:
assert grade(task, task["expected"], "stop")["passed"]
for bad in ("wrong", None, "", '{"answer": 46}', "APPROVE please"):
assert not grade(task, bad, "stop")["passed"]
assert not grade(task, task["expected"], "length")["passed"]
assert not grade(TASKS[0], "47.00", "stop")["passed"]
assert not grade(TASKS[2], "DENY", "stop")["passed"]
print("OFFLINE reference and grader checks passed; zero inference calls.")检查与消费分开进行。命令界面默认进行离线验证,在推理之前需要显式的实时选项和额度。
def main(tasks=None, grader=grade, default_config="demo-config.json", offline_check=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("operation", nargs="?", default="check",
choices=["check", "plan", "run", "report", "reconcile"])
parser.add_argument("--config", default=default_config)
parser.add_argument("--run-dir", type=Path, default=Path("runs/demo"))
parser.add_argument("--live", action="store_true")
parser.add_argument("--max-usd", default="0")
parser.add_argument("--resume", action="store_true")
parser.add_argument("--tasks", help="Optional exact-contract custom task JSON")
args = parser.parse_args()
if args.operation == "check":
if args.tasks:
parser.error("Use an example entry point with its own offline_check; check does not accept --tasks overrides")
if offline_check is not None:
offline_check()
elif tasks is not None or grader is not grade or args.tasks:
parser.error("Custom tasks/graders require offline_check=... for their own reference and fixture checks")
else:
offline()
return
selected = read(args.tasks) if args.tasks else (tasks if tasks is not None else TASKS)
config = load_config(args.config)
if args.operation == "report":
print(json.dumps(report(args.run_dir), indent=2))
elif args.operation == "reconcile":
reconcile(args.run_dir, live=args.live)
print(json.dumps(report(args.run_dir), indent=2))
else:
execute(args.run_dir, selected, config, grader, args.max_usd,
live=args.live, resume=args.resume, plan=args.operation == "plan")
if __name__ == "__main__":
main()配置并检查计划
使用随附的 Luna 配置来设置模型、重复次数、token 额度和提供商约束:
{
"models": [
"openai/gpt-6-luna"
],
"repeats": 1,
"max_tokens": 1024,
"settings": {
"openai/gpt-6-luna": {
"provider": {
"require_parameters": true,
"allow_fallbacks": true,
"max_price": {
"prompt": 0.09999999999999999,
"completion": 0.5,
"request": 0
}
},
"reasoning": {
"effort": "low"
}
}
}
}Sol 的配置保留了重复次数/token 设置,但使用自己的价格上限:
{
"models": [
"openai/gpt-6.1-sol"
],
"repeats": 1,
"max_tokens": 1024,
"settings": {
"openai/gpt-6.1-sol": {
"provider": {
"require_parameters": true,
"allow_fallbacks": true,
"max_price": {
"prompt": 2.0,
"completion": 10.0,
"request": 0
}
},
"reasoning": {
"effort": "low"
}
}
}
}models 选择候选模型,repeats 指定每个任务的请求数,max_tokens 设置补全额度。推理可能会在可见输出之前消耗该额度。离线检查不进行任何 API 调用。付费运行需要显式的 —live 标志。因长度被截断的响应会直接失败,不会重试。
价格上限以每百万 token 的美元数计;Luna 的提示上限约为 $0.10。如果某个提供商不再支持已保存的设置,运行器必须停止,而不是静默更改它们。提供商回退不会更换模型或重新发送推理。
python three_tasks.py plan --config luna-config.json实际的离线输出:
{"planned_calls": 3, "max_tokens": 1024, "models": ["openai/gpt-6-luna"], "repeats": 1, "estimated_reservations_usd": "0.0023543749999999999565625"}预留额度是本地成本估算,不是账户冻结或保证上限。在选择额度之前请先做好计划。
| 教学选择 | 调用次数 | 预计预留额度 |
|---|---|---|
| Luna,三个任务 | 3 | $0.0023544 |
| Sol,三个任务 | 3 | $0.0470875 |
| Luna,下方的 JSON 任务 | 1 | $0.00080725 |
| Sol,下方的 JSON 任务 | 1 | $0.016145 |
更改任务、重复次数或 token 会改变估算值。如果消费超过估算值,脚本会停止发送新请求。
进行一次小额付费运行
在API 密钥设置中创建密钥,添加额度,并配置合适的密钥限额。在终端中本地设置该变量。
PowerShell:
$env:OPENROUTER_API_KEY = "YOUR_OPENROUTER_API_KEY"Bash 或 Zsh:
export OPENROUTER_API_KEY="YOUR_OPENROUTER_API_KEY"如果已配置,可复用现有变量。该软件包不会加载 .env。对于随附的三任务 Luna 配置:
python three_tasks.py run --config luna-config.json --run-dir runs/my-luna --live --max-usd 0.01
python three_tasks.py reconcile --run-dir runs/my-luna --live
python three_tasks.py report --run-dir runs/my-luna对账执行只读的生成元数据查询。报告显示响应覆盖率,即已完成的响应数除以计划的试验数,还包括通过数/评分数、失败数、已验证成本以及请求时间中位数。在账单得到验证之前,报告的成本保持未定状态。请求时间不包含评分和元数据;它不是首 token 时间。
实际运行结果会有所不同。下方的合成示例仅用于说明报告功能,并非模型测量数据。
第 4 步. 添加你自己的任务和评分器
随附的 custom-tasks.json 展示了任务格式:
[
{
"id": "custom-total",
"prompt": "Four items cost 12.50 USD each. Return only the total with exactly two decimals.",
"expected": "50.00"
}
]python custom_task.py check 用 Decimal 独立计算其参考值,并测试正确、错误和格式错误的答案。自定义金额 ID 使用两位小数的评分器。其他合约需要自己的评分器和检查。
完整的 json_extraction.py 按文件顺序分为三部分。它允许 JSON 空白符和键顺序的差异,但会拒绝缺失、多余或重复的键以及错误的类型。结构合法但值错误的对象判定为不正确。被过滤或异常结束的响应有单独的分类。
"""A complete exact-schema JSON extraction example; offline check by default."""
import json
from reader_core import finish_grade
from three_tasks import main
CUSTOMER_EMAIL = "mira@example.test"
ORDER_CODE = "A-104"
ITEM_COUNT = 3
SOURCE_TEXT = ("Customer: Mira. Email: mira@example.test. Order: A-104. "
"Items: 3. Gift wrap: no.")
# Define reference fields from the independently specified source facts.
# Do not ask a model (or the grader) to produce the reference.
EXPECTED = {"email": CUSTOMER_EMAIL, "order_id": ORDER_CODE,
"item_count": ITEM_COUNT, "gift_wrap": False}
TASKS = [{"id": "order-extraction", "grader": "exact-order-json-v1",
"prompt": "Extract email, order_id, item_count and gift_wrap from this order. "
"Return a JSON object only, with exactly those keys. email and order_id "
"are strings; item_count is an integer; gift_wrap is a boolean. " + SOURCE_TEXT,
"expected": EXPECTED}]仅有 JSON 语法检查是不够的。先拒绝重复键和无效的数值,再验证模式(schema),然后将字段与参考值进行比较。
def strict_json(text):
def pairs(items):
result = {}
for key, value in items:
if key in result:
raise ValueError("Duplicate JSON key")
result[key] = value
return result
def nonfinite(value):
raise ValueError("Nonfinite JSON number")
return json.loads(text, object_pairs_hook=pairs, parse_constant=nonfinite)
def grade(task, text, finish):
terminal = finish_grade(finish)
if terminal:
return terminal
if not isinstance(text, str) or not text.strip():
return {"passed": False, "classification": "empty"}
try:
actual = strict_json(text)
except (ValueError, TypeError):
return {"passed": False, "classification": "malformed"}
types = {"email": str, "order_id": str, "item_count": int, "gift_wrap": bool}
schema_ok = (type(actual) is dict and actual.keys() == types.keys()
and all(type(actual[key]) is kind for key, kind in types.items()))
if not schema_ok:
return {"passed": False, "classification": "malformed"}
passed = actual == task["expected"]
return {"passed": passed, "classification": "pass" if passed else "incorrect"}同时检查接受和拒绝两种情况。这些测试用例区分“合法但值错误”与“格式错误的输出”,并验证过滤或截断不能算作通过。
CORRECT = '{"order_id":"A-104","email":"mira@example.test","gift_wrap":false,"item_count":3}'
WRONG = '{"email":"other@example.test","order_id":"A-104","item_count":3,"gift_wrap":false}'
MALFORMED = ["not JSON", '```json\n' + CORRECT + '\n```',
'{"email":"mira@example.test"}', CORRECT.replace('3}', 'true}'),
CORRECT.replace('3}', '3.0}'), CORRECT.replace('3}', 'NaN}'),
CORRECT[:-1] + ',"item_count":3}', CORRECT[:-1] + ',"extra":1}']
def offline():
assert EXPECTED == {"email": "mira@example.test", "order_id": "A-104",
"item_count": 3, "gift_wrap": False}
assert f"Email: {CUSTOMER_EMAIL}." in SOURCE_TEXT
assert f"Order: {ORDER_CODE}." in SOURCE_TEXT
assert f"Items: {ITEM_COUNT}." in SOURCE_TEXT and "Gift wrap: no." in SOURCE_TEXT
task = TASKS[0]
assert grade(task, CORRECT, "stop")["passed"]
assert grade(task, json.dumps(EXPECTED, indent=2), "stop")["passed"]
assert grade(task, WRONG, "stop")["classification"] == "incorrect"
for text in MALFORMED:
assert grade(task, text, "stop")["classification"] == "malformed", text
assert grade(task, "", "stop")["classification"] == "empty"
assert grade(task, CORRECT, "content_filter")["classification"] == "content_filtered"
assert grade(task, CORRECT, "length")["classification"] == "truncated"
print("OFFLINE JSON extraction: independent source facts, schema, correct/wrong/malformed fixtures passed; zero requests.")
if __name__ == "__main__":
main(tasks=TASKS, grader=grade, offline_check=offline)最后的 main(…) 调用将任务、评分和参考检查连接到运行器。调整源事实和期望字段,然后运行:
python json_extraction.py check
python json_extraction.py plan --config luna-config.json预期的检查输出:
OFFLINE JSON extraction: independent source facts, schema, correct/wrong/malformed fixtures passed; zero requests.使用独立的文件夹。这些额度仅适用于随附的单用例计划。
python json_extraction.py run --config luna-config.json --run-dir runs/json-luna --live --max-usd 0.01
python json_extraction.py run --config sol-config.json --run-dir runs/json-sol --live --max-usd 0.03
python json_extraction.py reconcile --run-dir runs/json-luna --live
python json_extraction.py reconcile --run-dir runs/json-sol --live开始前先设置相同的重复次数。同一用例重复三次测试的是波动性,而非工作负载覆盖面。在得出更广泛的结论之前,先加入有代表性的边界用例和保留用例。
第 5 步:比较已保存的运行并处理缺失答案
对于你保存的 JSON 运行:
python compare_runs.py runs/json-luna runs/json-sol --output comparisons/json这会生成 comparison.md 和 comparison.json,不进行推理或重新评分。它会校验契约、设置和身份标识;不兼容的运行需要调查,而不是默默排名。
先离线演练一遍:
python synthetic_comparison.py runs/comparison-demo
python compare_runs.py runs/comparison-demo/luna runs/comparison-demo/sol --output comparisons/full表格包含这些合成夹具值,以缩写列名显示:
| 夹具标签 | 已完成/计划 | 通过/已评分 | 已过滤 | 已核实成本/100 | 中位数秒数 |
|---|---|---|---|---|---|
| Luna | 6/6 | 5/6 | 1 | $0.000100 | 0.150 |
| Sol | 5/6 | 5/5 | 0 | 不可用 | 0.155 |
Sol 的夹具有一个缺失答案和一笔未核实的账单。其 5/5 的成绩缺少完整覆盖。这些数字不能用来衡量任一模型。
保留不确定的试验及其预留。修复访问或速率限制问题,然后在配置、来源和配额不变的情况下恢复运行:
python json_extraction.py run --config luna-config.json --run-dir runs/json-luna --live --max-usd 0.01 --resume恢复运行只会继续从未尝试过的试验。已知账单无法找回缺失的文本。如果我们找不到某个请求的生成记录,报告中会将其保持为未解决状态。不要丢弃运行或删除尝试记录。README 说明了崩溃后出现的过期锁。
要比较所有参与者都作答的用例:
python compare_runs.py runs/comparison-demo/luna runs/comparison-demo/sol --common-completed --output comparisons/common显式交集保留原始覆盖范围并列出排除项。它可能选出更容易的用例,也不会修复缺失的账单。切勿在没有披露的情况下比较不同的子集。
可选的 60 任务运行器和运行环境设置见配套材料。其历史结果提供了一个更大的完整示例。
哪个模型在我们的基准测试中表现最好?
每个模型接受了 40 个基线任务和 20 个困难任务各三次,得到 120 个基线评分和 60 个困难评分。这些结果描述了在固定设置下于 2026 年 10 月 20 日完成的 60 个合成任务。AA 指来自我们按日期标注的公开快照的 Artificial Analysis Intelligence Index。
| 模型与 API ID | 基线 % | 困难 % | 合计通过 | 成本/100 条任务响应 | 中位数秒数 | AA 指数 |
|---|---|---|---|---|---|---|
Claude Haiku 5.5anthropic/claude-haiku-5.5 | 90.8 | 76.7 | 155/180 | $0.03434 | 3.37 | 43.4 |
Claude Sonnet 5.5anthropic/claude-sonnet-5.5 | 47.5 | 45.0 | 84/180 | $0.47273 | 2.33 | 56 |
GPT-6 Lunaopenai/gpt-6-luna | 98.3 | 73.3 | 162/180 | $0.01848 | 3.81 | 38.1 |
GPT-6.1 Solopenai/gpt-6.1-sol | 100.0 | 100.0 | 180/180 | $0.24490 | 3.52 | 51.8 |
Gemini 3.8 Flashgoogle/gemini-3.8-flash | 95.0 | 96.7 | 172/180 | $0.30412 | 3.38 | 40.9 |
DeepSeek V4.1 Flashdeepseek/deepseek-v4.1-flash | 93.3 | 75.0 | 157/180 | $0.00394 | 4.66 | 24.7 |
Grok 4.7x-ai/grok-4.7 | 99.2 | 96.7 | 177/180 | $1.03462 | 5.97 | 46.4 |
MiMo V2.6 Flashxiaomi/mimo-v2.6-flash | 89.2 | 63.3 | 145/180 | $0.03156 | 5.00 | 37.9 |
Mistral Large 4.0mistralai/mistral-large-4-0 | 90.0 | 51.7 | 139/180 | $0.58945 | 31.45 | 38.4 |
GLM 5.3z-ai/glm-5.3 | 92.5 | 73.3 | 155/180 | $0.06083 | 1.59 | 44.8 |
每 100 条任务响应的成本是 180 个已评分答案的已核实成本折算到 100 条后的数值。它不包含运营开销和未解决的账单。中位数秒数衡量本地请求的耗时。
三项发现可为在这套数据上的选择提供指引。
-
最高通过率。Sol 以每 100 条响应约 $0.2449 的成本通过了 180/180。
-
最低响应成本。DeepSeek 每 100 条成本约 $0.00394,通过 157/180,其中 14 次截断。Luna 以约 $0.01848 通过 162/180。请根据你所需的通过率和失败的后果来做选择。
-
输出合规性影响得分。Sonnet 的 66 个格式错误响应涉及 21 个发票、30 个日期和 15 个退款试验。原始答案包含了说明文字,而提示词只要求数字或 JSON。该得分衡量的是契约合规性和答案正确性,而非纯粹的推理能力。
每个模型行合计 180。最后一行合计全部 1,800 条响应。类别记录的是未通过的检查项,而非其根本原因。
| 模型 | 通过 | 错误 | 格式错误 | 截断 | 空 |
|---|---|---|---|---|---|
| Haiku | 155 | 7 | 18 | 0 | 0 |
| Sonnet | 84 | 30 | 66 | 0 | 0 |
| Luna | 162 | 18 | 0 | 0 | 0 |
| Sol | 180 | 0 | 0 | 0 | 0 |
| Gemini | 172 | 8 | 0 | 0 | 0 |
| DeepSeek | 157 | 0 | 9 | 14 | 0 |
| Grok | 177 | 3 | 0 | 0 | 0 |
| MiMo | 145 | 8 | 13 | 14 | 0 |
| Mistral | 139 | 8 | 7 | 25 | 1 |
| GLM | 155 | 18 | 7 | 0 | 0 |
| 总计 | 1526 | 100 | 120 | 53 | 1 |
全部 53 条截断响应仍然算作失败。
该研究请求了 8,192 个 token,并在支持的情况下使用低推理强度。有 16 次试验因其先前的尝试未返回答案而需要补发请求。其中一次补发也未返回答案,需要再次派发,因此 16 个选定答案共对应 17 次补发派发。对已返回的答案没有进行重试。配套资料保留了每一次尝试。
已知的研究账单为 $5.1032,另有 $0.5383 预留用于未结算账单。Reader 计划估算 Luna 的 180 次研究试验费用约为 $0.97,Sol 的约为 $19.46。路由、日期以及最初的并发/恢复调度方式限制了与串行 reader 运行器之间的比较。
公开的 LLM 基准测试与您自己的基准相比如何?
我们于 2026 年 10 月 20 日 10:03 UTC 通过我们的 基准测试 API 获取了 Artificial Analysis 的快照,并匹配了确切的规范模型版本。
Spearman 相关系数比较的是排名顺序,−1 表示排名完全相反,+1 表示排名完全一致。在十个模型上:
| 集合 | Spearman 相关系数 |
|---|---|
| 基线 | 0.115 |
| 困难 | 0.183 |
| 组合 | 0.109 |
在该样本中一致性较弱。不同的任务和设置使我们无法就基准测试的总体可靠性得出结论。可将公开分数用于初步筛选,然后再评估您自己的工作负载。
每个任务应该运行多少次?
在 600 个模型-任务对中,有 68 个出现模型在某些重复中通过、在另一些重复中失败的情况。请保留每一次重复。这些是对 60 个案例的重复观察,而非每个模型 180 个不同的案例。排名接近时需要更多留出案例和更多重复。
常见问题
我需要多少测试用例?
先从一个小集合开始,覆盖某个工作流的常见输入、边界情况和已知失败。十个经过仔细审查的示例可以支持初步探索,但并不能提供统计学上的保证。当差异很小或失败代价高昂时,可用具有代表性的留出案例进行扩充。重复运行用于评估一致性,不能取代覆盖率。
可以使用 LLM 评判吗?
可以,适用于语气或解释质量等难以精确检查的属性。请用人工标注的示例验证其评分标准,并检查不一致之处。对于可计算的答案和必需的 schema,仍应保留代码检查。我们的 LLM-as-a-judge 指南解释了这一方法。
后续步骤
使用我们的 黄金评测数据集指南,从您的应用构建有代表性的集合。比较候选方案,然后 以这些检查作为拉取请求的门禁。
来源:OpenRouter:Blog(Announcements) · openrouter.ai