Skip to main content

EvalHub:LLM 与 Agent 评测平台

项目信息

GitHubNEDONION/evalhub

Python 3.11+ FastAPI React 19 SQLite Ollama Docker Local-first

EvalHub 评测配置界面

1 项目定位

一句话:把公开数据集、本地模型、持久化工作流、样本证据和六维能力报告放进同一条可复现评测链路。

它要解决的痛点很具体——大多数评测工具只给你一个最终分数,但真正需要回答的问题是:

  • 这个分数是怎么来的?哪些样本失败了?
  • 换个模型重跑,配置真的一样吗?
  • 0 分是「模型答错了」还是「根本没跑起来」?

所以 EvalHub 的核心设计目标是留证据:每次运行都保留样本结果、节点状态、资源指标和审计事件。

能力提供的行为
模型 Benchmark运行真实公开数据集,通过 Ollama 调本地模型,保留样本级结果和聚合得分
Agent 评测通过受控 Registry 运行 Pi CLI 或 MiniClaw 完整 Agent,共用同一套任务和隐藏 Verifier
可复现工作流持久化 DAG 记录节点状态、检查点、重试、资源指标和审计事件
六维能力画像分维度展示,不把未评测维度算作 0 分

2 整体架构

分层原则是领域核心不依赖具体基础设施:核心层不直接依赖 FastAPI、Celery、PostgreSQL 或 MinIO,所以 MVP 可以先用 SQLite + 子进程跑通,之后替换成 Scheduler + PostgreSQL + Celery Worker 时,EvaluationRunner 和任务 API 的语义都不用改。

3 核心设计一:持久化评测 DAG

评测任务不是一个黑盒进程,而是一张有状态的节点图:

节点状态为 pending / running / success / failed / blocked / canceled。三条关键规则:

1. 成功节点不重复执行。 服务异常重启时,中断节点恢复为待执行,并跳过已有评分结果的样本检查点——注意是「已有评分结果」而不是「已通过」,所以不会因为答案得分低就重新推理。这个区分很关键:

status=failed 且 result_json 存在  → 已评分,答案未通过,不重跑
status=failed 且 result_json 为空 → 未完成评分,需要重跑

2. 数据变了就阻塞,不静默复用。 资产节点记录真实文件或目录内容的 SHA-256,Benchmark 执行前后再次校验;期间发生变化就清空该节点样本检查点并明确阻塞,禁止跨数据 revision 复用结果。

3. 事件表是追加式的。 状态变化、自动重试、人工重试和服务恢复都产生事件,旧事件不覆盖。出问题时能完整回放。

评测工作流与资源指标

4 核心设计二:空回答阻塞,而不是记零分

这是整个项目最重要的一条判断:

Ollama 返回空文本时,generation_incompleteempty_model_response阻塞节点;非空但答错的回答仍按统一标准记零分。

为什么这条重要:如果把「模型没输出」和「模型答错了」都记成 0 分,最后的排行榜就是垃圾——你分不清模型能力差还是评测环境挂了。基础设施不可用必须阻塞任务,而不是被记录为模型零分。

同样的逻辑贯穿 Agent 评测:0 分被进一步区分为运行失败 / 未修改工作区 / 修改了但没通过校验,靠的是过程证据而不是 Agent 的自然语言自述。

5 核心设计三:协议轴分离

Hexagon 1.2 把「模型怎么生成」和「答案怎么评分」拆成两条互不放宽的协议轴:

协议轴决定什么
ModelGenerationProfileOllama 顶层 think 行为(思考模型显式 think=false
BenchmarkSpec回答协议和 num_predict 预算

七项 Benchmark 的生成预算依次固定为 256 / 1024 / 512 / 512 / 1024 / 256 / 256 tokens,选择题、数值、BBH、IFEval 和 HumanEval 各走自己的评分边界。组合后的有效配置、模型协议版本和答案协议版本全部写入节点输入、可复现性账本和比较指纹

三个生成协议组(普通 Ollama、显式 think=false 的思考模型、OpenAI-compatible API)使用同一套样本和评分器,但跨协议组排名仅供观察——这个限定写在报告里,避免结论被误用。

6 实测报告:11 个模型的六维画像

2026-08-05 在 evalhub-hexagon-v1 1.2.0 固定套件上的快照:9 个本地 Ollama 模型 + 2 个线上 DeepSeek 模型均完成 30/30 样本,共 330 次模型评测。

11 个模型的六维能力对比

排名模型运行方式通过样本综合分
1deepseek-v4-proDeepSeek API25 / 3083.33%
2gemma4:12bOllama21 / 3070.00%
3granite4.1:3bOllama20 / 3066.67%
3qwen3:14bOllama20 / 3066.67%
3deepseek-v4-flashDeepSeek API20 / 3066.67%
6granite3.3:8bOllama16 / 3053.33%
7qwen2.5-coder:7bOllama15 / 3050.00%
8qwen2.5:1.5bOllama12 / 3040.00%
9deepseek-r1:1.5bOllama10 / 3033.33%
10qwen2.5:0.5bOllama8 / 3026.67%
11qwen3:4bOllama6 / 3020.00%

几个可以复述的观察:

  • 指令遵循在多数中大型模型上已经饱和(普遍 100 分),区分度基本消失。
  • 代码与综合推理最能拉开差距,是当前更有信息量的维度。
  • deepseek-v4-flash 呈现明显的代码强、数学弱特征(代码 100 / 数学 0),说明单看综合分会丢失重要信息。

这是一组 Mini Suite 能力画像,不是上游 Benchmark 的完整官方成绩,不能当作论文或排行榜成绩复述。

7 Agent 评测:把完整 Agent 当作被测对象

模型评测评的是模型,Agent 评测评的是**「模型 + 外壳」的整体**。EvalHub 的做法是让不同 Agent 跑同一套 coding-mini-v3(6 道分级编码任务)+ 同一个隐藏 Verifier:

三条纪律:

  1. 评分只采用最终工作区的隐藏校验结果,不看 Agent 自述。
  2. 时间线只保存白名单外部事件,不保存内部思维链,也不在 Agent 完成前暴露隐藏断言。
  3. 基础设施不可用则阻塞任务,不会被记录为模型零分。

Agent 失败样本审计

实测:同样是 0 分,原因完全不同

10 个模型的 Agent 六维对比

排名模型协议预检通过样例工具调用工具错误平均耗时/题
1deepseek-v4-procompatible6 / 6641061.78 s
2moonshotai/Kimi-K2.7-Codecompatible5 / 6591183.00 s
2zai-org/GLM-5.2compatible5 / 6629122.41 s
2deepseek-ai/DeepSeek-V4-Flashcompatible5 / 67519133.97 s
5qwen3:14bcompatible1 / 672175.23 s
5qwen3:4bcompatible1 / 6131169.05 s
7gemma4:12bcompatible0 / 6190155.52 s
7granite4.1:3bcompatible0 / 612811.73 s
7granite3.3:8bincompatible0 / 60017.42 s
7deepseek-r1:1.5bincompatible0 / 60030.11 s

同样是 0 分,过程证据把它们分成了两类

  • gemma4:12b / granite4.1:3b:通过协议预检、实际调用了工具,但最终工作区没通过隐藏校验 → 能力不足
  • granite3.3:8b / deepseek-r1:1.5b:未完成结构化工具协议 → 协议不兼容,压根没开始干活

这就是为什么必须记录过程指标。只看分数,这四个模型看起来一样差。

排除运行也要留档

Job ID模型观测排除原因
job_4507d33dac62DeepSeek-V4-Flash0 / 6修复前 Provider 解析器拒绝 SiliconFlow SSE 中空 function.name 的续传片段,属于框架 bug 而非模型能力

排除运行只保留为协议边界证据,不进入正式结果或排名。每个模型只采用首个完成全部 6 题、且没有任务级基础设施故障的正式任务;不按分数重跑或挑选最佳值。

模型与数据集资产管理

8 凭据安全

远程模型服务商的凭据处理,是一个很容易做错的地方:

  • 公开配置和 Fernet 密文独立保存到 .runtime/model_providers.sqlite3
  • 主密钥优先来自 EVALHUB_CREDENTIAL_KEY,否则用权限 0600 的本地密钥文件;
  • 浏览器只获得「是否已配置」和末四位提示,没有读取明文凭据的 HTTP 接口;
  • 任务只冻结 provider_id、模型 ID 与 Base URL,不保存 API Key——Worker 运行时再按 ID 解析最新凭据,因此密钥轮换不要求改写已排队任务;
  • 边界拒绝含用户信息、查询或 fragment 的地址;远程服务只允许 HTTPS,HTTP 仅允许回环主机;
  • 错误进入任务记录前精确移除当前 API Key

最后这条尤其容易被忽略:异常堆栈里带着 Authorization header 直接写进数据库,是最常见的凭据泄漏路径。

9 沉淀下来的经验

1. 评测系统的价值在证据,不在分数。 一个数字回答不了「为什么」。样本级结果 + 节点状态 + 过程指标 + 审计事件,才能让评测结果可被质疑、可被复现。

2. 「跑失败」和「答错了」必须分开。 把基础设施故障记成 0 分,会污染整个排行榜。空回答阻塞节点,是这个原则最直接的落地。

3. 可复现性要靠指纹,不靠约定。 把 suite 版本、数据 SHA-256、提示模板版本、generation config 全部写进比较指纹。只有指纹一致的结果才允许放在一张表里比。

4. 断点续跑的判据是「有没有结果」,不是「结果好不好」。result_json 是否存在判断,而不是用 status=failed。这个细节做错了,就会出现"低分样本被反复重跑刷分"的严重问题。

5. 评 Agent 要评最终工作区,不评自述。 Agent 会说自己完成了。隐藏 Verifier 检查最终工作区,是唯一可信的判据。

6. 小样本单次运行不足以推断因果。 Pi 与 MiniClaw 的对照实验里,三组 6 题结果显示 MiniClaw 工具调用更少、耗时更低,但不足以证明外壳本身有普遍优势。把这个限定写进报告,比给出一个爽快的结论更负责任。

参考