关于 evalpair
evalpair 是用于在本地或托管模型上运行和比较 LLM 评测的命令行工具与 MCP 服务。它按题目配对结果,并衡量不确定性和重复运行噪声,帮助研究者与开发者判断变化是否显著。
主要功能
- 01对单个模型运行评测套件
- 02缓存回复并续跑中断任务
- 03以自助法区间比较配对得分
- 04测量答案变化与噪声底线
- 05用确定性检查器创建套件
适用场景
- 01比较模型、提示词或量化方案变化
- 02判断分数差距是否超出统计噪声
- 03续跑部分完成的评测
MCP 相关
向 MCP 客户端提供列出套件、运行评测、查看已保存运行和比较运行的工具。只有运行评测会调用模型;其他工具读取已保存结果。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
uvx evalpairEVALPAIR_HOMEFolder for the call cache, saved runs and your own suites (default ~/.evalpair).EVALPAIR_API_KEY密钥Bearer token for an OpenAI-compatible server, if it needs one (OPENAI_API_KEY also works).本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
5收录的工具列表 · 更新于 3 天前
此工具无需参数。
详细介绍
evalpair
针对一个模型运行 LLM 评测套件,缓存每次调用,并逐项比较两次运行:新模型、提示词或量化是否真的带来了变化,还是差异只是噪声?
大多数评测工具会把两个分数并排显示。160 道题相差 2 分,看起来像是一个结果,但通常并非如此。evalpair 会按题目配对两次运行,为差异计算自举区间,统计变差和变好的题目数量,并测量噪声底线:用同一个模型回答两遍相同的问题。在我自己的研究中,以 temperature 0 将同一提示词发送两次,最多有 3% 的答案发生变化,因此答案变化率只有高于这个水平才有意义。
它既是 CLI,也是 MCP 服务,因此 Agent 可以自行运行评测并读取结论。它只会调用你指定的模型服务,并将所有内容保存在一个本地文件夹中。
快速开始
uvx evalpair suites
uvx evalpair run gsm8k-160 -m llama3.1:8b --repeat --label llama
uvx evalpair run gsm8k-160 -m qwen3:8b --think off --label qwen3
uvx evalpair compare llama qwen3
run 会输出带有 95% 区间的分数,以及最先出现的失败项;无法解析和被截断的回复会优先显示(这些问题通常是解析器或 token 预算导致的,而非模型本身)。compare 会输出两个分数、带区间的配对差异、变差和变好的题目数量、噪声底线,最后给出通俗易懂的结论:分数差异是否显著异于零,以及答案变化是否超过同一模型回答两遍时的变化。
一个真实的对比:在 M5 Pro 笔记本上,比较 Ollama 默认的 4 位 Llama 3.1 8B 与其 2 位版本(--num-ctx 4096;两次运行总计约 40 分钟):
$ evalpair compare llama-q4 llama-q2
A llama-q4: 84.4% [79.4%, 90.0%]
B llama-q2: 60.6% [53.1%, 68.1%]
B − A -23.8 pp [-31.9 pp, -16.2 pp]
changed 40.6% [33.1%, 48.1%] of 160 items (43 worse in B, 5 better)
floor (A) 0.0% [0.0%, 0.0%]; excess +40.6 pp [+33.1 pp, +48.1 pp]
B scores lower than A: -23.8 pp [-31.9 pp, -16.2 pp], paired over 160 items. Answers changed on 40.6% of
items (43 got worse, 5 better). The noise floor (the same model asked twice) is 0.0% for A, so the change
is beyond noise.
worse in B: gsm8k-0259 '168' → '52'
...
两个分数都是量化研究在相同题目上对这些版本测得的结果。
中断运行后再次运行:每条回复都会缓存,因此程序会从中断处继续。
作为 MCP 服务运行
claude mcp add evalpair -- uvx evalpair mcp
或者在任意 MCP 客户端的配置中添加:{"command": "uvx", "args": ["evalpair", "mcp"]}。
| 工具 | 功能 |
|---|---|
list_suites | 可运行的套件:名称、项目数量、检查器、测量内容 |
run_eval | 针对一个模型运行套件并保存运行结果(会调用模型;已缓存的回复会重复使用) |
list_runs | 已保存的运行,按时间从新到旧排列 |
show_run | 某次运行的分数及其区间、噪声底线和失败回复的末尾部分 |
compare_runs | 按题目配对两次运行:带区间的差异、双向变化数量、与噪声底线的对比以及示例 |
除了 run_eval 之外,其他工具都只读取已保存的运行结果。
后端
- Ollama(默认):
--backend ollama,服务地址为http://localhost:11434。运行结果会记录模型的摘要,方便你之后准确确认测试的是哪个版本。对于具备思考能力的模型,可使用--think on|off;使用--num-ctx设置上下文窗口。 - 任何兼容 OpenAI 的服务:对于 vLLM、llama.cpp 的服务端或 LM Studio,以及托管 API,可使用
--backend openai --base-url http://localhost:8000/v1。Bearer token 会从EVALPAIR_API_KEY(或OPENAI_API_KEY)读取,且不会写入磁盘。
Temperature 默认为 0,seed 默认为 7。二者都会与服务 URL、模型、消息、token 预算和思考设置一起作为缓存键的一部分。
套件
内置了三个套件。它们来自我在 Measuring LLM Systems 研究中使用的题目集,提示词与研究中使用的完全一致,因此可以将一次运行的结果与已发布的数据进行核对:
| 套件 | 题目数 | 检查器 | 来源 |
|---|---|---|---|
gsm8k-160 | 160 | number | GSM8K 测试集(MIT) |
mmlu-hs-160 | 160 | choice,按科目分层 | MMLU,四门高中科目(MIT) |
e2e-extract-150 | 150 | json_fields | E2E NLG 餐厅记录(CC BY-SA 4.0) |
要创建自己的套件,请在 ~/.evalpair/suites/<name>/ 中创建一个包含两个文件的文件夹,也可以将文件夹放在其他位置,然后通过路径传入:
# suite.toml
description = "Capitals, answered in one word"
checker = "exact"
max_tokens = 64
system = "Answer in one word." # optional
user = "What is the capital of {country}?"
group = "region" # optional: stratify the bootstrap by this item field
{"id": "fr", "country": "France", "region": "Europe", "gold": "Paris"}
{"id": "pe", "country": "Peru", "region": "Americas", "gold": ["Lima", "Ciudad de los Reyes"]}
提示词中的 {field} 会替换为题目中的对应内容;字符串列表会转换为带字母编号的选项(A. …),其他内容则会以缩进 JSON 的形式显示。使用 {{ 和 }} 表示字面大括号。
| 检查器 | 评分方式 | 标准答案 |
|---|---|---|
number | 获取 “Answer:” 后的数字;如果没有,则获取 \boxed{} 中的内容;再不然就获取最后一个数字 | 一个数字 |
choice | 获取 “Answer:” 后的字母,并使用备用解析方式(字母由 checker_options.letters 指定) | 一个字母 |
exact | 获取 “Answer:” 后的文本,或最后一行,并进行规范化 | 一个字符串或字符串列表 |
contains | 检查标准答案字符串是否以完整单词形式出现 | 一个字符串或列表 |
regex | 获取 checker_options.pattern 的最后一次匹配(第一个捕获组) | 一个字符串或列表 |
json_fields | 计算回复中的 JSON 答对了标准答案对象多少比例的字段(null 必须为 null) | 一个对象 |
检查器是确定性代码:这里不会让大模型为另一个大模型评分。number、choice 和 json_fields 的解析器来自这些研究;用它们重新评分量化研究主运行中的全部 9,870 条回复,会得到该研究对每条回复报告的分数(scripts/check_against_studies.py)。
数值的计算方式
- 重采样单位:题目。 进行 2,000 次 Bootstrap 抽样,计算百分位区间,并设置随机种子,因此相同的运行总会得到相同的区间。如果指定了
group,则在每个组内重采样题目。 - 比较采用配对方式,针对两次运行都作答的题目,并使用各自的首次作答。如果两次运行使用了不同版本的套件(其规范和题目的哈希值不同),比较结果会注明这一点。
- 噪声下限:使用
--repeat时,每道题都会作为单独调用再发送一次(使用各自的缓存条目)。噪声下限是两轮作答之间解析结果发生变化的题目比例。只有当每次运行中,逐题计算的“运行间变化”减去“轮次间变化”的区间都大于零时,比较结果才会将变化称为“超出噪声范围”。 - 题目按文件顺序抽取,因此
--limit 50每次都会选取相同的 50 道题,受限运行之间仍能配对。
文件存放位置
$EVALPAIR_HOME,或 ~/.evalpair:
cache.sqlite every reply, keyed by request
runs/<run>/meta.json suite and its hash, model, digest, backend, options, counts, timings
runs/<run>/rows.jsonl one line per item and pass: reply, parsed answer, score, tokens
suites/<name>/ your suites
限制
- 每次运行使用一个模型、聊天式提示词和单轮对话。目前不支持工具调用、多轮对话或受限解码。
- 仅支持确定性检查器,因此开放式回答需要使用答案可由代码检查的套件。
- 噪声下限衡量的是同一服务上的运行间差异,不涵盖不同机器或服务更新的情况。
许可证
代码使用 MIT 许可证。内置套件遵循各自来源的许可证(GSM8K 和 MMLU 使用 MIT,E2E NLG 使用 CC BY-SA 4.0);每个 suite.toml 都会注明其许可证和来源。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。