model-compare
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseModel Compare — Blind Side-by-Side Multi-Model Testing
Model Compare — 盲态多模型并行测试
Send one prompt to multiple models simultaneously, present responses
anonymously, let the user pick a winner, then reveal which model is which.
Inspired by the Compare feature in PewDiePie's Odysseus project, adapted for
Hermes's multi-provider architecture (OpenRouter, NVIDIA, Ollama Cloud, any
OpenAI-compatible endpoint).
将同一个提示词同时发送给多个模型,匿名展示响应结果,让用户选出最优结果后,再揭晓对应模型的身份。
灵感来自PewDiePie的Odysseus项目中的对比功能,适配了Hermes的多提供商架构(OpenRouter、NVIDIA、Ollama Cloud以及任何兼容OpenAI的端点)。
When to use
适用场景
- "Compare these models on..."
- "Which model is better for [task]?"
- "A/B test [model1] vs [model2]"
- "Blind comparison of..."
- "Test how different models handle this prompt"
- User wants to evaluate models before committing to one for a workflow
- Prompt engineering — seeing how different models interpret instructions
- "Compare these models on..."
- "Which model is better for [task]?"
- "A/B test [model1] vs [model2]"
- "Blind comparison of..."
- "Test how different models handle this prompt"
- 用户希望在将模型用于工作流之前先评估模型
- 提示词工程——查看不同模型对指令的解读方式
When NOT to use
不适用场景
- Benchmarking (MMLU, GSM8K, etc.) → use skill
evaluating-llms-harness - Cost analysis → just check provider pricing pages
- Single model test → just switch model and ask directly
- Multi-source research synthesis → use skill (iterative research loop, not model comparison)
deep-research
- 基准测试(如MMLU、GSM8K等)→ 使用技能
evaluating-llms-harness - 成本分析→ 直接查看提供商定价页面即可
- 单模型测试→ 直接切换模型提问即可
- 多源研究合成→ 使用技能(迭代研究循环,而非模型对比)
deep-research
Architecture
架构
Four comparison modes, all driven by :
scripts/compare.py| Mode | Flag | What it does | API feature |
|---|---|---|---|
| simple | | One prompt → one response | Basic chat completion |
| tools | | Multi-turn tool calling with real web_search/web_extract + sandboxed run_python/read_file/write_file. 10-turn max (configurable per-test via | |
| coding | | Test bank coding prompts (LRU cache, concurrent fetch, debug merge sort, retry decorator) | Basic chat completion |
| review | | Code review prompts with planted bugs (SQL injection, clean code, race condition, float-for-money) | Basic chat completion |
User prompt + model list
→ Step 1: Resolve models to provider endpoints (free providers first)
→ Step 2: Send prompt to all models in parallel
├─ simple/coding/review: one-shot chat completion
└─ tools: multi-turn loop (Think→Search→Extract→Execute→Synthesize→Stop, max 10 turns by default, per-test configurable)
→ Step 3: Quality check responses (handle errors/empty)
→ Step 4: Present anonymously (shuffle + label A/B/C/D)
→ Step 5: Efficiency table (tokens in/out, turns, tool calls — auto for tools mode)
→ Step 6: User votes OR judge model evaluates
→ Step 7: Reveal identities + show mapping
→ Step 8 (optional): Save to JSON file四种对比模式,均由驱动:
scripts/compare.py| 模式 | 标识 | 功能 | API特性 |
|---|---|---|---|
| simple | | 一个提示词→一个响应 | 基础对话补全 |
| tools | | 多轮工具调用,支持真实web_search/web_extract + 沙箱化run_python/read_file/write_file。最多10轮(可通过TEST_BANK中的 | 请求中的 |
| coding | | 使用测试库中的编码提示词(LRU缓存、并发请求、归并排序调试、重试装饰器) | 基础对话补全 |
| review | | 包含预设问题的代码评审提示词(SQL注入、代码整洁性、竞态条件、浮点数处理金额) | 基础对话补全 |
用户提示词 + 模型列表
→ 步骤1:将模型解析为提供商端点(优先免费提供商)
→ 步骤2:并行向所有模型发送提示词
├─ simple/coding/review:单次对话补全
└─ tools:多轮循环(思考→搜索→提取→执行→合成→停止,默认最多10轮,可按测试配置)
→ 步骤3:响应质量检查(处理错误/空响应)
→ 步骤4:匿名展示(打乱顺序 + 标记为A/B/C/D)
→ 步骤5:效率表格(输入/输出token数、轮次、工具调用数——tools模式自动生成)
→ 步骤6:用户投票 或 评审模型评估
→ 步骤7:揭晓模型身份 + 展示对应关系
→ 步骤8(可选):保存到JSON文件Script: scripts/compare.py
scripts/compare.py脚本:scripts/compare.py
scripts/compare.pyThe primary interface — a standalone CLI tool (no pip dependencies, pure stdlib + urllib). See for which models support tool calling. For empirical model behavior findings from 16 head-to-head tests (GLM 5.2, MiniMax M3, HY3, Laguna), see . (Running the test suite under needs — see ; the skill itself needs nothing installed.)
references/provider-tool-support.mdreferences/model-behavior.mdtests/pytestrequirements-dev.txtTool-mode environment dependency:runs real--mode tools. That needs eitherweb_searchset to a SearXNG instance or theSEARXNG_URLCLI available onddgs(the fallback). Neither is a Python import dependency, but one of them must be present for live search; without both,PATHreturns an error result. The other three modes (web_search,simple,coding) need neither.review
bash
undefined核心交互接口——独立CLI工具(无pip依赖,纯标准库 + urllib)。查看了解哪些模型支持工具调用。关于16组一对一测试(GLM 5.2、MiniMax M3、HY3、Laguna)得出的模型行为实证结果,请查看。(运行下的测试套件需要——详见;该技能本身无需安装任何依赖。)
references/provider-tool-support.mdreferences/model-behavior.mdtests/pytestrequirements-dev.txt工具模式环境依赖:会运行真实的--mode tools。需要要么设置web_search指向SearXNG实例,要么在SEARXNG_URL中可用PATHCLI(作为备选方案)。两者都不是Python导入依赖,但必须存在其中一个才能实现实时搜索;如果两者都没有,ddgs会返回错误结果。其他三种模式(web_search、simple、coding)无需这两者。review
bash
undefinedSimple 2-model blind comparison
简单双模型盲态对比
python3 scripts/compare.py --prompt "Explain X" --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5"
python3 scripts/compare.py --prompt "Explain X" --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5"
Reasoning-effort A/B: SAME model, two effort levels (native syntax)
推理强度A/B测试:同一模型,两种强度级别(原生语法)
Registers a virtual provider per arm; judge can also take an effort suffix.
为每个分支注册虚拟提供商;评审模型也可添加强度后缀。
python3 scripts/compare.py --mode review --test H7
--models "ollama-cloud:@medium:glm-5.3-flash" "ollama-cloud:@high:glm-5.3-flash"
--judge "ollama-cloud:@medium:glm-5.3" --reveal
--models "ollama-cloud:@medium:glm-5.3-flash" "ollama-cloud:@high:glm-5.3-flash"
--judge "ollama-cloud:@medium:glm-5.3" --reveal
python3 scripts/compare.py --mode review --test H7
--models "ollama-cloud:@medium:glm-5.3-flash" "ollama-cloud:@high:glm-5.3-flash"
--judge "ollama-cloud:@medium:glm-5.3" --reveal
--models "ollama-cloud:@medium:glm-5.3-flash" "ollama-cloud:@high:glm-5.3-flash"
--judge "ollama-cloud:@medium:glm-5.3" --reveal
Tool calling with test bank prompt A + judge + reveal
使用测试库提示词A进行工具调用 + 评审模型 + 揭晓结果
python3 scripts/compare.py --mode tools --test A --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5" --judge "ollama-cloud:glm-5.2" --reveal
python3 scripts/compare.py --mode tools --test A --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5" --judge "ollama-cloud:glm-5.2" --reveal
Coding test J with efficiency table
带效率表格的编码测试J
python3 scripts/compare.py --mode coding --test J --models "ollama-cloud:glm-5.2" "ollama-cloud:qwen3-coder:480b" --efficiency
python3 scripts/compare.py --mode coding --test J --models "ollama-cloud:glm-5.2" "ollama-cloud:qwen3-coder:480b" --efficiency
Code review test O with judge
带评审模型的代码评审测试O
python3 scripts/compare.py --mode review --test O --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5" --judge "ollama-cloud:glm-5.2"
python3 scripts/compare.py --mode review --test O --models "ollama-cloud:glm-5.2" "ollama-cloud:kimi-k2.5" --judge "ollama-cloud:glm-5.2"
List available tests
列出可用测试
python3 scripts/compare.py --list-tests
python3 scripts/compare.py --list-tests
List providers
列出提供商
python3 scripts/compare.py --list-providers
Key flags: `--prompt`, `--models`, `--mode`, `--test` (test bank ID), `--judge`, `--efficiency`, `--reveal`, `--output`, `--timeout`, `--list-providers`, `--list-models`.python3 scripts/compare.py --list-providers
关键标识:`--prompt`、`--models`、`--mode`、`--test`(测试库ID)、`--judge`、`--efficiency`、`--reveal`、`--output`、`--timeout`、`--list-providers`、`--list-models`。Reasoning-effort A/B (:@effort
suffix, added 2026-08-29)
:@effort推理强度A/B测试(:@effort
后缀,2026-08-29新增)
:@effortModel specs and accept an optional effort marker , e.g.
. Each unique (provider, effort) pair registers a
virtual provider () that clones the base provider's config — same
endpoint, same env key, inherited — and injects into the
payload. This enables comparing the SAME model at two reasoning levels in one blind run;
the reveal labels the arms . Findings from the 2026-08-29
glm-5.3-flash A/B (Codex-judged, 8 tests): effort→thinking-token count is non-monotonic;
high was ~3x faster median but non-converged on a 12-turn tool-chain test that medium
completed; medium won on judged quality overall (8.6 vs 7.8 avg). See
for full traces.
--judgeprovider:@effort:model_idollama-cloud:@medium:glm-5.3-flashollama-cloud@mediummax_tokensreasoning_effortprovider@effort~/.hermes/data/glm53flash_effort_ab/ab_results.jsonlCLI override (added 2026-07-17): Pass--max-turnsto override the test bank's--max-turns Nfield at runtime without editing source. If not passed, the test bank default is used. This was added because killing a background run to patchmax_turnsin source code is fragile and disrupts parallel execution.TEST_BANK["A"]["max_turns"]
模型规格和支持可选的强度标记,例如。每个唯一的(提供商,强度)对会注册一个虚拟提供商(),克隆基础提供商的配置——相同端点、相同环境密钥、继承——并将注入请求体。这使得在一次盲态测试中可以对比同一模型的两种推理级别;揭晓时会将分支标记为。2026-08-29针对glm-5.3-flash的A/B测试结果(由Codex评审,8组测试):强度→思考token数并非单调递增;高强度版本中位速度快约3倍,但在一个12轮工具链测试中未收敛,而中强度版本完成了测试;中强度版本在评审质量上整体获胜(平均得分8.6 vs 7.8)。完整轨迹请查看。
--judgeprovider:@effort:model_idollama-cloud:@medium:glm-5.3-flashollama-cloud@mediummax_tokensreasoning_effortprovider@effort~/.hermes/data/glm53flash_effort_ab/ab_results.jsonl**CLI覆盖(2026-07-17新增):**传递--max-turns可在运行时覆盖测试库中的--max-turns N字段,无需修改源代码。如果未传递该参数,则使用测试库默认值。新增此功能是因为终止后台运行以修改源代码中max_turns的方式不够稳定,且会中断并行执行。TEST_BANK["A"]["max_turns"]
Available Providers
可用提供商
Three providers are wired in (the canonical config is in
):
PROVIDERSscripts/compare.py| Provider | Env Var | Cost | Model families | Endpoint |
|---|---|---|---|---|
| Ollama Cloud | | Free | GLM, Qwen, Kimi, Gemini, Gemma | |
| NVIDIA | | Free | Yi, Llama, Nemotron, … | |
| OpenRouter | | Paid (per-token) | Claude, GPT, Gemini, DeepSeek, Llama, Qwen, Mistral | |
Model inventories live elsewhere, on purpose. Exact model counts and IDs drift constantly, so they are deliberately kept out of this doc. For the live list run(needs that provider's key);python3 scripts/compare.py --list-models <provider>holds a curated, count-free snapshot with representative model IDs per provider.references/providers.json
已接入三个提供商(标准配置为中的):
scripts/compare.pyPROVIDERS| 提供商 | 环境变量 | 成本 | 模型系列 | 端点 |
|---|---|---|---|---|
| Ollama Cloud | | 免费 | GLM、Qwen、Kimi、Gemini、Gemma | |
| NVIDIA | | 免费 | Yi、Llama、Nemotron等 | |
| OpenRouter | | 付费(按token计费) | Claude、GPT、Gemini、DeepSeek、Llama、Qwen、Mistral | |
**模型清单存放在别处,这是有意为之。**具体模型数量和ID会不断变化,因此特意不包含在本文档中。要查看实时列表,请运行(需要对应提供商的密钥);python3 scripts/compare.py --list-models <provider>包含每个提供商的精选代表性模型ID快照,不含具体数量。references/providers.json
Cost-aware provider routing (mandatory)
成本感知型提供商路由(强制规则)
When the user does not specify a provider, route to free providers first:
- Ollama Cloud — free (GLM, Qwen, Kimi, Gemini, Gemma)
- NVIDIA — free (Yi, Llama, Nemotron)
- OpenRouter — paid (per-token cost). Only use when:
- The user explicitly requests an OpenRouter-only model (e.g. Claude, GPT-4o)
- The user explicitly says to use OpenRouter
- The free providers don't have a suitable model for the task
Before any OpenRouter call, confirm with the user:
"This comparison will use OpenRouter which has per-token costs. Estimated cost: ~$0.01–0.05 per model per call (varies by model). Proceed?"
Only proceed after explicit confirmation. When in doubt, default to free providers.
To call a model, POST to the provider's endpoint with:
/v1/chat/completionsjson
{
"model": "<model_id>",
"messages": [{"role": "user", "content": "<prompt>"}],
"max_tokens": 8192,
"temperature": 0.7
}Header:
Authorization: Bearer <API_KEY>max_tokens is set to 8192 in bothandcall_model_simple. The previous default of 4096 caused truncated code output on coding test J (LRU cache) — the model generated so much code it hit the 4096 limit before finishing the decorator section. If a model still truncates, increase the value in the payload dict.call_model_with_tools
当用户未指定提供商时,优先路由到免费提供商:
- Ollama Cloud — 免费(GLM、Qwen、Kimi、Gemini、Gemma)
- NVIDIA — 免费(Yi、Llama、Nemotron)
- OpenRouter — 付费(按token计费)。仅在以下情况使用:
- 用户明确请求仅OpenRouter提供的模型(如Claude、GPT-4o)
- 用户明确要求使用OpenRouter
- 免费提供商没有适合该任务的模型
在调用任何OpenRouter模型之前,需与用户确认:
"本次对比将使用OpenRouter,该服务按token计费。预估成本:每个模型每次调用约0.01–0.05美元(因模型而异)。是否继续?"
仅在用户明确确认后才继续执行。如有疑问,默认使用免费提供商。
调用模型时,向提供商的端点发送POST请求,请求体如下:
/v1/chat/completionsjson
{
"model": "<model_id>",
"messages": [{"role": "user", "content": "<prompt>"}],
"max_tokens": 8192,
"temperature": 0.7
}请求头:
Authorization: Bearer <API_KEY>max_tokens在和call_model_simple中均设置为8192。之前的默认值4096会导致编码测试J(LRU缓存)的代码输出被截断——模型生成的代码量太大,在完成装饰器部分之前就达到了4096的限制。如果模型仍出现截断情况,请增加请求体中的该值。call_model_with_tools
Step 1 — Resolve Models
步骤1 — 解析模型
Determine which models to compare. The user may specify:
- Explicit model names: "compare claude-sonnet-4.6 vs gpt-4o vs gemini-2.5-flash"
- Provider + model: "compare OpenRouter claude-sonnet-4.6 vs Ollama glm-5.2"
- Task-based: "which model is best for coding?" → suggest 2-4 candidates
- All from a provider: "test 3 OpenRouter models" → pick diverse ones
确定要对比的模型。用户可能会指定:
- 明确的模型名称:"compare claude-sonnet-4.6 vs gpt-4o vs gemini-2.5-flash"
- 提供商+模型:"compare OpenRouter claude-sonnet-4.6 vs Ollama glm-5.2"
- 基于任务:"which model is best for coding?" → 推荐2-4个候选模型
- 同一提供商的多个模型:"test 3 OpenRouter models" → 选择多样化的模型
Model resolution
模型解析规则
Map the user's model names to a spec. Free providers
(Ollama Cloud, NVIDIA) are preferred. OpenRouter is only used for models not
on a free provider (e.g. Claude, GPT) or when the user explicitly asks for it.
provider:model_idThe rules, not a hardcoded catalogue (which would rot):
- Free, leave the prefix off or name an Ollama/NVIDIA model → resolve on a
free provider, e.g. ,
ollama-cloud:glm-5.2,ollama-cloud:qwen3-coder:480b.nvidia:meta/llama-3.3-70b-instruct - A proprietary model (Claude, GPT, Gemini-Pro, DeepSeek-R1, …) → only
OpenRouter carries it, e.g. ,
openrouter:anthropic/claude-sonnet-4.6— paid, confirm first (see routing rule above).openrouter:openai/gpt-4o - Unsure of the exact ID? Run for the live list, or see
python3 scripts/compare.py --list-models <provider>for a curated set of representative IDs per provider. Don't hand-maintain a model table here.references/providers.json
When user doesn't specify models:
- Check if the task type maps to free models (e.g. coding → qwen3-coder, glm-5.2; general → glm-5.2, kimi-k2.5)
- Suggest 2-4 free models from Ollama Cloud and NVIDIA
- Only suggest OpenRouter models if the user asks for premium models (Claude, GPT-4o) or the free providers lack suitable options
- If suggesting any paid models, flag the cost before running
If unsure which provider has a model, check with:
bash
curl -s https://openrouter.ai/api/v1/models -H "Authorization: Bearer $OPENROUTER_API_KEY" | python3 -c "import sys,json; [print(m['id']) for m in json.load(sys.stdin)['data'] if 'KEYWORD' in m['id'].lower()]"Rules:
- 2-4 models per comparison (more = unwieldy in chat)
- If user doesn't specify, suggest a diverse set (different providers/sizes)
- Always confirm the model list with the user before running
将用户指定的模型名称映射为格式。优先选择免费提供商(Ollama Cloud、NVIDIA)。仅当模型未在免费提供商提供(如Claude、GPT)或用户明确要求时,才使用OpenRouter。
provider:model_id以下是规则(而非硬编码目录,避免过时):
- 免费模型,省略前缀或指定Ollama/NVIDIA模型 → 在免费提供商上解析,例如、
ollama-cloud:glm-5.2、ollama-cloud:qwen3-coder:480b。nvidia:meta/llama-3.3-70b-instruct - 专有模型(Claude、GPT、Gemini-Pro、DeepSeek-R1等) → 仅OpenRouter提供,例如、
openrouter:anthropic/claude-sonnet-4.6— 付费服务,需先确认(见上述路由规则)。openrouter:openai/gpt-4o - **不确定确切ID?**运行查看实时列表,或查看
python3 scripts/compare.py --list-models <provider>获取每个提供商的精选代表性ID。请勿在此手动维护模型表。references/providers.json
当用户未指定模型时:
- 检查任务类型是否对应免费模型(例如编码→qwen3-coder、glm-5.2;通用任务→glm-5.2、kimi-k2.5)
- 从Ollama Cloud和NVIDIA推荐2-4个免费模型
- 仅当用户要求使用高级模型(Claude、GPT-4o)或免费提供商没有合适选项时,才推荐OpenRouter模型
- 如果推荐任何付费模型,需在运行前告知成本
如果不确定哪个提供商有对应模型,可通过以下命令检查:
bash
curl -s https://openrouter.ai/api/v1/models -H "Authorization: Bearer $OPENROUTER_API_KEY" | python3 -c "import sys,json; [print(m['id']) for m in json.load(sys.stdin)['data'] if 'KEYWORD' in m['id'].lower()]"规则:
- 每次对比2-4个模型(数量过多会导致对话界面难以操作)
- 如果用户未指定,推荐多样化的模型组合(不同提供商/尺寸)
- 在运行前始终与用户确认模型列表
Step 2 — Send Prompt to All Models
步骤2 — 向所有模型发送提示词
Send the prompt to all models in parallel. The script handles this
automatically via — no need for
delegate_task or manual parallelism.
concurrent.futures.ThreadPoolExecutor并行向所有模型发送提示词。脚本通过自动处理此操作——无需手动并行或委托任务。
concurrent.futures.ThreadPoolExecutorSimple / coding / review modes
Simple / coding / review模式
One-shot chat completion per model. All calls fired concurrently by the script.
每个模型执行单次对话补全。所有调用由脚本并发触发。
Tool calling mode
工具调用模式
Multi-turn loop per model (also concurrent across models):
Turn 1: Send prompt + tool definitions → Model returns tool_call(s)
Turn 2: Execute real tool → inject result → Model returns tool_call(s) or answer
Turn 3: ... until final answer or max turns (10 by default, configurable per-test via `max_turns` field in TEST_BANK)Real tool execution — the script executes and
for real:
web_searchweb_extract- → SearXNG (self-hosted, via
web_search) with DDGS fallbackSEARXNG_URL - → direct HTTP fetch with HTML-to-text conversion (3000 chars/page)
web_extract
No mock tools, no fake results. Models must formulate good queries, pick the
right URLs, and synthesize from real content. A model that generates a bad
search query gets bad results and must recover.
Tool definitions passed via the OpenAI parameter:
tools- — returns titles, URLs, snippets
web_search(query, limit) - — returns page content as text
web_extract(urls)
No terminal tool — we don't have a sandbox. Terminal is not exposed to
comparison models for safety reasons.
每个模型执行多轮循环(模型间也并行执行):
第1轮:发送提示词 + 工具定义 → 模型返回tool_call(s)
第2轮:执行真实工具 → 注入结果 → 模型返回tool_call(s)或最终答案
第3轮:... 直到返回最终答案或达到最大轮次(默认10轮,可通过TEST_BANK中的`max_turns`字段按测试配置)真实工具执行——脚本真实执行和:
web_searchweb_extract- → SearXNG(自托管,通过
web_search),备选方案为DDGSSEARXNG_URL - → 直接HTTP请求,将HTML转换为文本(每页最多3000字符)
web_extract
无模拟工具,无虚假结果。模型必须制定合理的查询、选择正确的URL,并从真实内容中合成结果。如果模型生成错误的搜索查询,会得到错误结果,必须自行恢复。
工具定义通过OpenAI的参数传递:
tools- — 返回标题、URL、摘要
web_search(query, limit) - — 返回页面文本内容
web_extract(urls)
无终端工具——出于安全考虑,未向对比模型暴露终端功能。
Step 3 — Quality Check
步骤3 — 质量检查
For each response:
- Empty/error: if a model returns an error or empty response, note it and exclude from the comparison. Tell the user which model failed.
- Truncated: if response hit max_tokens, note it was truncated
- Refusal: if a model refused to answer, include it as-is (refusals are valid comparison data)
对每个响应执行以下检查:
- 空响应/错误:如果模型返回错误或空响应,记录并排除在对比之外。告知用户哪个模型失败。
- 截断:如果响应达到max_tokens限制,记录响应被截断
- 拒绝回答:如果模型拒绝回答,原样保留(拒绝回答属于有效的对比数据)
Step 4 — Present Anonymously
步骤4 — 匿名展示
Shuffle the responses and assign neutral labels. Do NOT reveal which model
is which.
Shuffle rule: Use a random permutation. Do not always put the same model
first. If the user is comparing 3 models, randomly assign A/B/C.
Present as:
🧪 Blind Model Comparison
Prompt: "[truncated to 100 chars...]"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 Model A:
[full response]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 Model B:
[full response]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 Model C:
[full response]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Vote: Reply with the letter of the best response (A, B, or C), or "tie".Formatting rules:
- Full responses, not summaries — the user needs to judge quality
- Clear visual separation between responses
- Truncate at ~3000 chars per response for chat readability (note if truncated)
- If responses are very long (>3000 chars), save full versions to files and present truncated versions in chat with a note
打乱响应顺序并分配中性标签。切勿提前揭晓模型身份。
**打乱规则:**使用随机排列。不要始终将同一模型放在第一位。如果用户对比3个模型,随机分配A/B/C标签。
展示格式如下:
🧪 盲态模型对比
提示词:"[截断至100字符...]"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 模型A:
[完整响应]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 模型B:
[完整响应]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 模型C:
[完整响应]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
投票:回复最优响应对应的字母(A、B或C),或"tie"(平局)。格式规则:
- 展示完整响应,而非摘要——用户需要完整内容来判断质量
- 响应之间有清晰的视觉分隔
- 为保证聊天可读性,每个响应最多显示约3000字符(如果截断需注明)
- 如果响应非常长(超过3000字符),将完整版本保存到文件,在聊天中展示截断版本并注明
Step 5 — User Votes
步骤5 — 用户投票
Wait for the user to vote. Accept:
- Letter: "A", "B", "C", "D"
- "tie" or "tie between A and B"
- "all bad" (valid — none won)
- Specific feedback: "A is better but B's code is cleaner"
等待用户投票。接受以下形式的投票:
- 字母:"A"、"B"、"C"、"D"
- "tie"或"tie between A and B"
- "all bad"(有效——无获胜模型)
- 具体反馈:"A更好但B的代码更整洁"
Step 6 — Reveal Identities
步骤6 — 揭晓模型身份
After the vote, reveal the mapping:
🎭 Reveal:
Model A → <actual_model_name> (<provider>)
Model B → <actual_model_name> (<provider>)
Model C → <actual_model_name> (<provider>)
🏆 Your winner: Model <letter> = <actual_model_name>投票结束后,揭晓标签与模型的对应关系:
🎭 揭晓结果:
模型A → <实际模型名称> (<提供商>)
模型B → <实际模型名称> (<提供商>)
模型C → <实际模型名称> (<提供商>)
🏆 您选出的获胜者:模型<字母> = <实际模型名称>Step 7 — Synthesis (optional)
步骤7 — 结果合成(可选)
If the user wants the best possible answer, synthesize across all responses:
"Want me to synthesize the best parts of all responses into one?"If yes, take the strongest elements from each response and produce a unified
answer. Note which model contributed each part:
undefined如果用户想要最优的综合答案,可将所有响应的内容进行合成:
"需要我将所有响应的精华内容合成为一个答案吗?"如果用户同意,提取每个响应的核心内容生成统一答案,并注明每个部分来自哪个模型:
undefinedSynthesized Answer
合成答案
[merged response]
[合并后的响应]
Contributions
内容来源
- Section X: primarily from <model_name>
- Section Y: primarily from <model_name>
undefined- 章节X:主要来自<模型名称>
- 章节Y:主要来自<模型名称>
undefinedStep 8 — Vote History (optional)
步骤8 — 投票历史记录(可选)
For recurring comparisons, log results to a file:
~/.hermes/data/model_compare_history.jsonlFormat:
json
{"timestamp": "2026-06-27T12:00:00", "prompt": "...", "models": ["model_a", "model_b"], "winner": "model_a", "is_blind": true, "feedback": "..."}This builds up a picture of which models win for which task types over time.
对于重复进行的对比,可将结果记录到文件:
~/.hermes/data/model_compare_history.jsonl记录格式:
json
{"timestamp": "2026-06-27T12:00:00", "prompt": "...", "models": ["model_a", "model_b"], "winner": "model_a", "is_blind": true, "feedback": "..."}通过长期记录,可以了解不同模型在各类任务中的获胜情况。
Test Bank (24 tests)
测试库(24组测试)
Use to run a pre-built test prompt. The mode is auto-set based on the test domain.
--test <ID>| ID | Domain | Prompt summary | Tools? |
|---|---|---|---|
| A | tool_calling | Latest Python version + top 2 features | 🔧 |
| B | tool_calling | Find Odysseus GitHub repo star count | 🔧 |
| C | tool_calling | Best reverse proxy for homelab, then find key feature | 🔧 |
| E | tool_calling | Search LRU cache implementations, then write a better one | 🔧 |
| H1 | tool_calling | Python 3.14 free-threaded status — find 3 sources, identify authoritative | 🔧 |
| H2 | tool_calling | Node.js stable version + EOL date, verify against official source | 🔧 |
| S1 | tool_calling | Write IPv4 validator, run with test cases, report pass/fail | 🔧 📦 |
| S2 | tool_calling | Write CSV to file, analyze averages, run script, report results | 🔧 📦 |
| S3 | tool_calling | Generate Fibonacci, save as JSON, read back and verify | 🔧 📦 |
| S4 | tool_calling | Reverse a linked list, run test, verify output, debug if wrong | 🔧 📦 |
| S5 | tool_calling | Caesar cipher encrypt/decrypt, run and verify round-trip | 🔧 📦 |
| J | coding | Implement LRU cache, O(1), type hints + docstring | |
| K | coding | Concurrent URL fetch with per-URL timeout, preserve order | |
| L | coding | Fix buggy merge sort (off-by-one in merge step) | |
| M | coding | Retry decorator, 3x, 1s delay, preserve metadata | |
| H3 | coding | Thread-safe cache with TTL + LRU eviction | |
| H4 | coding | Token bucket rate limiter, thread-safe, injectable clock | |
| O | code_review | SQL injection + unreliable rowcount loop | |
| P | code_review | Clean code (no bugs) — test false positive rate | |
| Q | code_review | Thread-unsafe cache in production service | |
| R | code_review | Float for money + missing transfer validation | |
| H5 | code_review | Asyncio connection pool — inflight leak, missing lock, no timeout | |
| H6 | code_review | Auth service — MD5, timing-unsafe, forgeable token, no expiry check | |
| H7 | code_review | Logging service — fetchone() called twice per loop iteration |
🔧 = uses web_search/web_extract tools. 📦 = uses sandbox tools (run_python/read_file/write_file).
Each test includes evaluation criteria used by the judge. Tool-calling tests also include a field (default 10) that controls the turn cap for that specific test — edit the TEST_BANK entry in to change it for an individual test. Code review tests include planted issues for objective scoring.
max_turnsscripts/compare.py使用运行预构建的测试提示词。模式会根据测试领域自动设置。
--test <ID>| ID | 领域 | 提示词摘要 | 是否使用工具? |
|---|---|---|---|
| A | tool_calling | 最新Python版本 + 两大核心特性 | 🔧 |
| B | tool_calling | 查询Odysseus GitHub仓库的星标数量 | 🔧 |
| C | tool_calling | 适合家庭实验室的最佳反向代理,然后查找其关键特性 | 🔧 |
| E | tool_calling | 搜索LRU缓存实现,然后编写更优版本 | 🔧 |
| H1 | tool_calling | Python 3.14自由线程状态——查找3个来源,确定权威信息 | 🔧 |
| H2 | tool_calling | Node.js稳定版本 + EOL日期,通过官方来源验证 | 🔧 |
| S1 | tool_calling | 编写IPv4验证器,运行测试用例,报告通过/失败情况 | 🔧 📦 |
| S2 | tool_calling | 将数据写入CSV文件,分析平均值,运行脚本,报告结果 | 🔧 📦 |
| S3 | tool_calling | 生成斐波那契数列,保存为JSON,读取并验证 | 🔧 📦 |
| S4 | tool_calling | 反转链表,运行测试,验证输出,如有错误进行调试 | 🔧 📦 |
| S5 | tool_calling | 凯撒密码加密/解密,运行并验证往返结果 | 🔧 📦 |
| J | coding | 实现LRU缓存,O(1)时间复杂度,包含类型提示 + 文档字符串 | |
| K | coding | 带单URL超时的并发URL请求,保留顺序 | |
| L | coding | 修复有bug的归并排序(合并步骤中的偏移错误) | |
| M | coding | 重试装饰器,最多3次,1秒延迟,保留元数据 | |
| H3 | coding | 带TTL + LRU淘汰的线程安全缓存 | |
| H4 | coding | 线程安全的令牌桶限流器,支持可注入时钟 | |
| O | code_review | SQL注入 + 不可靠的行计数循环 | |
| P | code_review | 整洁代码(无bug)——测试误报率 | |
| Q | code_review | 生产服务中的线程不安全缓存 | |
| R | code_review | 浮点数处理金额 + 缺少转账验证 | |
| H5 | code_review | Asyncio连接池—— inflight泄漏、缺少锁、无超时 | |
| H6 | code_review | 认证服务——MD5、时序不安全、可伪造令牌、无过期检查 | |
| H7 | code_review | 日志服务——循环中重复调用fetchone() |
🔧 = 使用web_search/web_extract工具。📦 = 使用沙箱工具(run_python/read_file/write_file)。
每组测试包含评审模型使用的评估标准。工具调用测试还包含字段(默认10),控制该测试的最大轮次——可修改中的TEST_BANK条目来调整单个测试的该值。代码评审测试包含预设问题,用于客观评分。
max_turnsscripts/compare.pyTool Calling Mode — How It Works
工具调用模式——工作原理
The flag enables multi-turn tool calling with real tools (not mocks):
--mode tools- Script defines 5 tools as OpenAI function tools: ,
web_search,web_extract,run_python,read_filewrite_file - Sends prompt + tool defs to each model in parallel
- When a model returns , the script executes the real call:
tool_calls- → SearXNG (self-hosted, via
web_search) with DDGS fallbackSEARXNG_URL - → direct HTTP fetch, HTML stripped to text, truncated to 3000 chars/page
web_extract - → executes Python code in a per-model sandbox (temp dir, 10s timeout, no network)
run_python - → reads a file from the sandbox directory (path traversal blocked)
read_file - → writes a file to the sandbox directory (path traversal blocked)
write_file
- Feeds the real result back as a role message
tool - Repeats until final answer or max turns (10 default, configurable per-test via in TEST_BANK)
max_turns - Tracks all turns, tool calls, tokens per turn, convergence status
Sandbox security: Each model gets its own temp directory (). Path traversal () and absolute paths are rejected. Python execution has a 10-second timeout. No network access from within the sandbox subprocess. Sandbox is cleaned up after each model's run (in a block).
tempfile.mkdtemp../finallyTools exposed: , , , , . See for which models support tool calling.
web_searchweb_extractrun_pythonread_filewrite_filereferences/provider-tool-support.mdJudge sees the full tool call trace — what was searched, what was extracted, what code was run and its output, how many turns, whether it converged. This lets the judge evaluate tool selection strategy, not just the final answer.
--mode tools- 脚本将5个工具定义为OpenAI函数工具:、
web_search、web_extract、run_python、read_filewrite_file - 并行向每个模型发送提示词 + 工具定义
- 当模型返回时,脚本执行真实调用:
tool_calls- → SearXNG(自托管,通过
web_search),备选方案为DDGSSEARXNG_URL - → 直接HTTP请求,剥离HTML转为文本,每页最多3000字符
web_extract - → 在每个模型专属的沙箱(临时目录,10秒超时,无网络)中执行Python代码
run_python - → 读取沙箱目录中的文件(阻止路径遍历)
read_file - → 写入文件到沙箱目录(阻止路径遍历)
write_file
- 将真实结果作为角色消息反馈给模型
tool - 重复执行直到模型返回最终答案或达到最大轮次(默认10轮,可通过TEST_BANK中的按测试配置)
max_turns - 追踪所有轮次、工具调用、每轮token数、收敛状态
**沙箱安全:**每个模型拥有独立的临时目录()。拒绝路径遍历()和绝对路径。Python执行有10秒超时。沙箱子进程无网络访问权限。每个模型运行结束后,沙箱会被清理(在块中执行)。
tempfile.mkdtemp../finally暴露的工具:、、、、。查看了解哪些模型支持工具调用。
web_searchweb_extractrun_pythonread_filewrite_filereferences/provider-tool-support.md评审模型可查看完整工具调用轨迹——包括搜索内容、提取内容、运行的代码及输出、轮次数量、是否收敛。这使得评审模型可以评估工具选择策略,而不仅仅是最终答案。
Efficiency Analysis
效率分析
The flag (auto-enabled for tools mode) prints a token comparison table:
--efficiency📊 Efficiency Comparison
Turns Tools Tok In Tok Out Ratio Time
✅ ollama-cloud:glm-5.2 5 5 7806 777 0.10 15.3s
✅ ollama-cloud:kimi-k2.5 5 4 5434 1051 0.19 14.8s
✅ ollama-cloud:gemma4:31b 2 1 949 248 0.26 6.5sKey metrics: turns, tool calls, tokens in (context consumed), tokens out (generated), efficiency ratio (out/in), time. Efficiency without accuracy is waste — a model that uses few tokens but gets the wrong answer is not efficient, it's just wrong fast.
--efficiency📊 效率对比
轮次 工具调用数 输入token数 输出token数 比率 耗时
✅ ollama-cloud:glm-5.2 5 5 7806 777 0.10 15.3s
✅ ollama-cloud:kimi-k2.5 5 4 5434 1051 0.19 14.8s
✅ ollama-cloud:gemma4:31b 2 1 949 248 0.26 6.5s关键指标:轮次、工具调用数、输入token数(消耗的上下文)、输出token数(生成内容)、效率比率(输出/输入)、耗时。没有准确性的效率毫无意义——一个使用少量token但答案错误的模型不是高效,只是快速出错。
Use Cases
使用案例
Model selection for a workflow
为工作流选择模型
"I need a model for summarizing legal documents. Compare claude-sonnet-4.6, gpt-4o, and gemini-2.5-flash on this prompt: [legal text]"
"我需要一个用于法律文档摘要的模型。对比claude-sonnet-4.6、gpt-4o和gemini-2.5-flash在以下提示词上的表现:[法律文本]"
Cost vs quality tradeoff
成本与质量权衡
"Compare glm-5.2 (free) vs claude-sonnet-4.6 (paid) on this coding prompt. Is the paid one worth it?"
"对比glm-5.2(免费)和claude-sonnet-4.6(付费)在以下编码提示词上的表现。付费模型是否值得?"
Prompt robustness testing
提示词鲁棒性测试
"Test this prompt on 3 models — I want to see which ones follow my formatting instructions"
"在3个模型上测试这个提示词——我想看看哪些模型能遵循我的格式要求"
Provider comparison
提供商对比
"Compare the same model (llama-4-maverick) on OpenRouter vs NVIDIA — is there a difference?"
"对比同一模型(llama-4-maverick)在OpenRouter和NVIDIA上的表现——是否有差异?"
Provider Health Tracking
提供商健康状态追踪
The module tracks provider endpoint health and
implements dead-host cooldown — when a provider fails consecutively, it's
marked dead for a cooldown period and subsequent calls skip it automatically.
scripts/provider_health.pyscripts/provider_health.pyHow it works
工作原理
- 2 consecutive failures → provider marked dead
- Cooldown: 15s (Ollama Cloud), 30s (NVIDIA), 20s (OpenRouter)
- Any success → resets failure counter immediately
- Cooldown expiry → provider gets another chance
- State persists to across runs
~/.hermes/data/provider_health.json
- 连续2次失败 → 提供商标记为故障
- 冷却时间:Ollama Cloud为15秒,NVIDIA为30秒,OpenRouter为20秒
- 任何一次成功 → 立即重置失败计数器
- 冷却期结束 → 提供商恢复可用
- 状态持久化到,跨运行会话保留
~/.hermes/data/provider_health.json
CLI
CLI命令
bash
undefinedbash
undefinedCheck provider health
检查提供商健康状态
python3 scripts/provider_health.py --status
python3 scripts/provider_health.py --status
Reset all providers
重置所有提供商
python3 scripts/provider_health.py --reset all
python3 scripts/provider_health.py --reset all
Reset a specific provider
重置指定提供商
python3 scripts/provider_health.py --reset ollama-cloud
undefinedpython3 scripts/provider_health.py --reset ollama-cloud
undefinedIntegration in compare.py
在compare.py中的集成
Both and check provider health
before making API calls. If a provider is in cooldown, the call is skipped
with a message instead
of waiting for a timeout. Successes and failures are recorded automatically.
call_model_simplecall_model_with_tools[Provider X in cooldown (Ns remaining) — skipping]call_model_simplecall_model_with_tools[Provider X in cooldown (Ns remaining) — skipping]When it matters
重要性
- Running comparisons across multiple providers — one flaky provider won't slow down the whole comparison
- Tool calling mode (10 turns per model) — a dead provider is skipped in seconds instead of waiting 60s × 10 turns = 10 minutes of timeouts
- Back-to-back comparisons — if a provider went down in a previous run, the next run knows to skip it
- 在多个提供商间运行对比时——一个不稳定的提供商不会拖慢整个对比过程
- 工具调用模式(每个模型10轮)——故障提供商在数秒内被跳过,而非等待60秒×10轮=10分钟的超时
- 连续对比时——如果提供商在上一次运行中故障,下一次运行会自动跳过
Hybrid Mode — CLI Models Alongside API Models
混合模式——CLI模型与API模型并行
The compare script only supports API-based providers (OpenRouter, Ollama
Cloud, NVIDIA). When the user wants to include models only accessible via
CLI tools (Codex CLI, Cursor CLI), use this hybrid pattern:
对比脚本仅支持基于API的提供商(OpenRouter、Ollama Cloud、NVIDIA)。当用户希望包含仅通过CLI工具访问的模型(如Codex CLI、Cursor CLI)时,可使用以下混合模式:
When to use hybrid mode
何时使用混合模式
- Cost savings — user says "use codex cli for gpt5.6" to avoid OpenRouter per-token costs. Codex ($20/mo) and Cursor Pro+ ($60/mo) include model access without per-token charges.
- Model availability — some models (e.g. ) are only available through Cursor CLI, not on any API provider.
cursor-grok-4.5-high
- 成本节约——用户说"use codex cli for gpt5.6"以避免OpenRouter的按token计费。Codex(20美元/月)和Cursor Pro+(60美元/月)包含模型访问权限,无需额外按token付费。
- 模型可用性——部分模型(如)仅通过Cursor CLI提供,无法通过任何API提供商访问。
cursor-grok-4.5-high
How to run hybrid comparisons
如何运行混合对比
- API models → run through as normal (background)
scripts/compare.py - CLI models → run each separately via terminal in parallel:\n - Codex CLI (GPT-5.6): \n - Cursor CLI (Grok 4.5):
codex exec --skip-git-repo-check -m gpt-5.5 "<prompt>" > /tmp/codex_result.json 2>&1export PATH="$HOME/.local/bin:$PATH" && export $(grep 'CURSOR_API_KEY=' ~/.hermes/.env | xargs) && agent -p --force --model "cursor-grok-4.5-high" --sandbox disabled "<prompt>" > /tmp/cursor_result.json 2>&1 - Merge results — collect API script output + CLI outputs, present all responses anonymously (shuffle together), let user vote, then reveal.
- API模型 → 正常通过运行(后台执行)
scripts/compare.py - CLI模型 → 分别在终端并行运行:\n - Codex CLI(GPT-5.6):\n - Cursor CLI(Grok 4.5):
codex exec --skip-git-repo-check -m gpt-5.5 "<prompt>" > /tmp/codex_result.json 2>&1export PATH="$HOME/.local/bin:$PATH" && export $(grep 'CURSOR_API_KEY=' ~/.hermes/.env | xargs) && agent -p --force --model "cursor-grok-4.5-high" --sandbox disabled "<prompt>" > /tmp/cursor_result.json 2>&1 - 合并结果——收集API脚本输出 + CLI输出,将所有响应匿名展示(打乱顺序),让用户投票,然后揭晓结果。
CLI model specifics
CLI模型细节
| CLI | Binary | Model flag | Auth | Cost |
|---|---|---|---|---|
| Codex | | | OAuth (hermes auth) | $20/mo included |
| Cursor | | | | $60/mo included |
Always run CLI models in background (+background=true) — they can take 1-5 minutes. Run them in the same tool batch as the API script launch for true parallelism.notify_on_complete=true
Cursor Grok 4.5 High is the heaviest internal tier. For lighter tasks use. See thecursor-grok-4.5-mediumskill for full model selection guidance.cursor-cli
| CLI工具 | 二进制文件 | 模型标识 | 认证方式 | 成本 |
|---|---|---|---|---|
| Codex | | | OAuth(hermes认证) | 包含在20美元/月订阅中 |
| Cursor | | | .env中的 | 包含在60美元/月订阅中 |
始终在后台运行CLI模型(+background=true)——可能需要1-5分钟。将其与API脚本启动放在同一工具批次中,实现真正的并行执行。notify_on_complete=true
Cursor Grok 4.5 High是内部最高级别。对于轻量任务,使用。查看cursor-grok-4.5-medium技能获取完整的模型选择指南。cursor-cli
Pitfalls
注意事项
- Revealing identities too early — never let model names leak into the anonymous presentation. Double-check before sending.
- Always same order — shuffle every time. If model A is always first, the user may develop position bias.
- Not parallel — send all API calls in the same tool block. Sequential calls waste time.
- Ignoring failures — if a model errors, tell the user. Don't silently exclude it.
- Truncating too aggressively — the user needs enough text to judge quality. 3000 chars minimum, full if shorter.
- Forgetting to reveal — always reveal after the vote. The whole point is knowing which model won.
- Not confirming model list — always confirm which models before spending API calls. Models cost money.
- Spending paid API calls without confirmation — OpenRouter is per-token paid. Always confirm with the user before calling OpenRouter models. Default to free providers (Ollama Cloud, NVIDIA) when no provider is specified. Only escalate to OpenRouter when the user explicitly requests a premium model or confirms cost.
- Using max_tokens too low — 8192 is the current default in compare.py. The previous 4096 caused truncated code on test J (LRU cache decorator cut off mid-function). If a model still truncates, raise the value in the payload dict.
- Temperature mismatch — use the same temperature (0.7 default) for all models. Different temperatures = unfair comparison.
- API key leakage — never print API keys in output. Always use env var references in curl commands.
- Rate limits — OpenRouter and NVIDIA have rate limits. If comparing 4+ models, add a small delay between calls if needed. OpenRouter free-tier models (with suffix) are especially prone to HTTP 429 rate-limiting after just 1-2 calls.
:free - OpenRouter free-tier models (suffix) and the cost gate — the script conservatively treats ALL OpenRouter models as paid, even
:freesuffix models that cost $0. Set:freeenv var to bypass the cost confirmation gate. Example:COMPARE_CONFIRM_PAID=1. No additional cost confirmation needed since the user has already chosen free-tier models.COMPARE_CONFIRM_PAID=1 python3 scripts/compare.py --models "openrouter:tencent/hy3:free" ... - NVIDIA NIM model IDs include the prefix — when using NIM via compare.py, pass the full model ID including the org prefix:
nvidia/(provider colon, then full model ID). Passingnvidia:nvidia/nemotron-3.5-lightning-30b-a3b(without thenvidia:nemotron-3.5-lightning-30b-a3bprefix) returns HTTP 404 "page not found" — NIM requires the fullnvidia/model ID in the API payload.nvidia/... - Nemotron 3.5 Lightning free tier tool calling — only the OpenRouter suffix and NIM direct support
:free. The OpenRouter paid tier (toolswithoutnvidia/nemotron-3.5-lightning, CoreWeave-hosted) returns HTTP 404 on:free. Usetools(NIM, free, stable) ornvidia:nvidia/nemotron-3.5-lightning-30b-a3b(free, but prone to 502s).openrouter:nvidia/nemotron-3.5-lightning:free - NVIDIA model list is stale — the endpoint lists many models but most return 404/410 when called. Only
/v1/models,meta/llama-3.1-70b-instruct, andmeta/llama-3.3-70b-instructwere alive as of June 2026. Always verify a model is alive with a simple chat completion before using it in a comparison. Seemistralai/mixtral-8x7b-instruct-v0.1for the current alive list.references/provider-tool-support.md - Assuming tool calling support — not all models support the API parameter. Test with a simple tool-call request first. Models that mention "search" in text but don't emit
toolsdo NOT support tool calling. Seetool_callsfor the tested matrix.references/provider-tool-support.md - Not all models support tool calling — (Ollama Cloud) mentions "search" in text but does NOT emit
deepseek-v3.2.tool_calls(NVIDIA) returns HTTP 400 on themistralai/mixtral-8x7b-instruct-v0.1parameter. Test tool support per model before runningtools. See--mode tools.references/provider-tool-support.md - Efficiency without accuracy is waste — a model that uses few tokens but gets the wrong answer is not efficient. Always cross-reference efficiency stats with the judge score. gemma4:31b used 949 tokens and 2 turns but said Python 3.13 (wrong); kimi-k2.5 used 5434 tokens and 5 turns but got the correct answer with authoritative sources.
- Tool calling loop can hit max turns — some models keep searching without synthesizing. The 10-turn default cap (configurable per-test via in TEST_BANK) prevents infinite loops, but the result is marked "did not converge." Check the
max_turnsfield in the trace. Increasingconvergedcan help models that need more turns to synthesize, but watch for models that loop on the same URLs without converging — more turns won't fix a model that can't synthesize.max_turns - No CLI override (fixed 2026-07-17) — the script used to only support per-test
--max-turnsin the TEST_BANK dict, requiring source edits to change the turn cap. This forced killing background runs to patch source. Nowmax_turnsoverrides at runtime. If the flag doesn't work, check that--max-turns Nhas thecompare.pyargument parser entry.--max-turns - User prefers CLI models to cut costs — when the user says "use codex cli for gpt5.6" or "use cursor-grok-4.5-high", they want to avoid OpenRouter per-token charges. Route GPT-5.6 through Codex CLI and Grok 4.5 through Cursor CLI instead of OpenRouter. See the Hybrid Mode section above. This is a cost preference, not just a one-off request.\n- Codex CLI model version limits — fails with "requires a newer version of Codex" on v0.135. Test with a trivial prompt first (
codex exec -m gpt-5.6-sol). Fall back tocodex exec --skip-git-repo-check -m <model> "say hello"if the newer model is unsupported.\n- Codex CLI needsgpt-5.5— without it, Codex refuses to run outside a git repo. Always include this flag.\n- Cursor CLI--skip-git-repo-checkrequired for web access —--forcealone does NOT enable web search in headless mode. Web requests are still blocked. Use--trust --sandbox disabled(which implies--force) to enable web access. Confirmed across 3 attempts:--trust→ blocked,--trust→ blocked,--trust --sandbox disabled→ works.\n- OpenRouter geofenced models — some models (e.g.--force) return HTTP 403 "This model is only available in the United States" when called from outside the US. No workaround without a US proxy. Exclude from comparisons run from non-US locations.meta/muse-spark-1.1 - SearXNG default engines may return 0 results — Google, DuckDuckGo, Brave, Startpage, and Mojeek engines frequently fail on self-hosted SearXNG (rate limits, CAPTCHAs). Only Bing and Yandex reliably return results. The script's now passes
execute_web_searchexplicitly. If search returns 43-char&engines=bing,yandex,duckduckgo,googleon every query, check SearXNG engine health with{"results": [], "note": "No results found"}and update the engines list incurl -s "http://$SEARXNG_URL/search?q=test&format=json&engines=bing".scripts/compare.py - DDGS CLI syntax changed — the old syntax no longer works. The new CLI uses
ddgs --json -q ... -m ...(outputs to file, not stdout). The script's DDGS fallback has been updated to use the new syntax. Verify withddgs text -q ... -m ... -o <file>if fallback fails.ddgs text --help - SEARXNG_URL not exported to background processes — the env var is loaded from by the script's
~/.hermes/.envfunction, but if you passload_env()to a background process (e.g. via--mode tools), make sure toterminal(background=true)explicitly in the command. Theexport SEARXNG_URL=http://...function only sets vars that are NOT already inload_env(), but background shells start with a minimal environment.os.environ - compare.py requires 2+ models — the script exits with "Error: need at least 2 models to compare" if you pass only one. To retry a single model after rate limiting, use a direct curl API call instead of the script.
- Comparing reasoning-effort levels is now native (v1.2.0) — use the syntax on
provider:@effort:model_idand--models(see the "Reasoning-effort A/B" section above). The old wrapper-harness pattern (--judge, virtual providers registered in a loader script) still works for multi-test batteries with per-test ground-truth judging; the native syntax covers single-run comparisons. For CLI judges (e.g. Codex gpt-5.6-sol): write the rubric + anonymized responses to a temp file, run/root/.hermes/cache/ab_effort_run.py, parse JSON from stdout+stderr, shuffle the Response 1/2 order per test. Ground truth for code_review tests comes from TEST_BANKcodex exec --skip-git-repo-check -m gpt-5.6-sol "Read the file <path> and follow the instructions inside"+evaluationkeys (NOTplanted_issues). Known findings (glm-5.3-flash, 2026-08-29): effort→reasoning-token count is NON-monotonic (high ≠ more thinking); high effort hit a 12-turn non-convergence on long tool chains while medium converged; medium won 4-2-2 on quality (8.6 vs 7.8 avg), high was ~3x faster median.evaluation_criteria - Kimi K3 rate limiting on OpenRouter — hits HTTP 429 on the shared OpenRouter pool, especially when running multiple tests in parallel. Wait 15-30s and retry, or add a Moonshot API key to OpenRouter (BYOK) for dedicated rate limits.
moonshotai/kimi-k3 - Sandbox tests (S1-S5) need models that support 5 tools — the sandbox tests pass all 5 tool definitions (web_search, web_extract, run_python, read_file, write_file) to the model. Some models may not support tool calling with 5 tools, or may only support 1-2 tools at a time. If a model fails on sandbox tests but passes research tests (A/B/C), it may be overwhelmed by the number of tool definitions. Test with a simpler sandbox prompt first.
- Sandbox Python execution is not network-isolated — the tool runs
run_pythonwhich can make network calls if the code importssubprocess.run([sys.executable, script])orurllib. The 10-second timeout limits damage but is not a true sandbox. For production hardening, consider running in a container or seccomp filter. For model comparison purposes, the timeout is sufficient.socket - Sandbox temp files are cleaned up after each model — the function creates a temp dir per model and cleans it up in a
run_tool_loopblock. If a model writes a file and then needs to read it back in a later turn, that works (same sandbox dir persists across turns). But if the script crashes mid-run, thefinallyblock still cleans up.finally - Sandbox output truncated to 2000 chars — returns stdout and stderr truncated to 2000 chars each. If a model generates a lot of output (e.g. printing a large list), the truncated output may confuse it. Models that format output concisely will perform better on sandbox tests.
run_python
- 过早揭晓模型身份——切勿让模型名称在匿名展示中泄露。发送前务必检查。
- 始终保持同一顺序——每次都要打乱顺序。如果模型A始终排在第一位,用户可能会产生位置偏见。
- 未并行执行——在同一工具块中发送所有API调用。顺序调用会浪费时间。
- 忽略失败情况——如果模型出错,告知用户。不要默默排除。
- 过度截断——用户需要足够的文本内容来判断质量。最少保留3000字符,若内容更短则完整展示。
- 忘记揭晓结果——投票后务必揭晓身份。整个对比的核心就是了解哪个模型获胜。
- 未确认模型列表——在消耗API调用前始终确认模型列表。模型调用会产生成本。
- 未确认就使用付费API调用——OpenRouter按token付费。在调用OpenRouter模型前始终与用户确认。未指定提供商时默认使用免费提供商(Ollama Cloud、NVIDIA)。仅当用户明确要求高级模型或确认成本时,才使用OpenRouter。
- max_tokens设置过低——当前compare.py中的默认值为8192。之前的4096会导致测试J(LRU缓存装饰器)的代码被截断。如果模型仍出现截断情况,增加请求体中的该值。
- 温度设置不一致——所有模型使用相同的温度(默认0.7)。不同的温度会导致不公平对比。
- API密钥泄露——切勿在输出中打印API密钥。在curl命令中始终使用环境变量引用。
- 速率限制——OpenRouter和NVIDIA有速率限制。如果对比4个以上模型,必要时在调用间添加短暂延迟。OpenRouter免费层模型(带后缀)在仅1-2次调用后就容易出现HTTP 429速率限制。
:free - OpenRouter免费层模型(后缀)与成本确认——脚本保守地将所有OpenRouter模型视为付费,即使带
:free后缀的模型成本为0。设置环境变量:free可绕过成本确认。示例:COMPARE_CONFIRM_PAID=1。由于用户已选择免费层模型,无需额外成本确认。COMPARE_CONFIRM_PAID=1 python3 scripts/compare.py --models "openrouter:tencent/hy3:free" ... - NVIDIA NIM模型ID包含前缀——在compare.py中使用NIM时,需传递完整模型ID,包括组织前缀:
nvidia/(提供商冒号,然后是完整模型ID)。传递nvidia:nvidia/nemotron-3.5-lightning-30b-a3b(不带nvidia:nemotron-3.5-lightning-30b-a3b前缀)会返回HTTP 404“页面未找到”——NIM要求API请求体中使用完整的nvidia/模型ID。nvidia/... - Nemotron 3.5 Lightning免费层工具调用——仅OpenRouter带后缀的版本和NIM直接调用支持
:free。OpenRouter付费层(不带tools的:free,由CoreWeave托管)在使用nvidia/nemotron-3.5-lightning时返回HTTP 404。使用tools(NIM,免费,稳定)或nvidia:nvidia/nemotron-3.5-lightning-30b-a3b(免费,但容易出现502错误)。openrouter:nvidia/nemotron-3.5-lightning:free - NVIDIA模型列表过时——端点列出了许多模型,但大多数调用时会返回404/410错误。截至2026年6月,只有
/v1/models、meta/llama-3.1-70b-instruct和meta/llama-3.3-70b-instruct可用。在将模型用于对比前,始终通过简单的对话补全验证模型是否可用。查看mistralai/mixtral-8x7b-instruct-v0.1获取当前可用模型列表。references/provider-tool-support.md - 假设模型支持工具调用——并非所有模型都支持API参数。先通过简单的工具调用请求测试。在文本中提到“搜索”但不返回
tools的模型不支持工具调用。查看tool_calls获取已测试的模型矩阵。references/provider-tool-support.md - 并非所有模型都支持工具调用——(Ollama Cloud)在文本中提到“搜索”但不返回
deepseek-v3.2。tool_calls(NVIDIA)在使用mistralai/mixtral-8x7b-instruct-v0.1参数时返回HTTP 400错误。在运行tools前测试每个模型的工具支持情况。查看--mode tools。references/provider-tool-support.md - 没有准确性的效率毫无意义——一个使用少量token但答案错误的模型不是高效。始终将效率统计与评审得分交叉验证。gemma4:31b使用了949个token和2轮次,但给出的Python版本是3.13(错误);kimi-k2.5使用了5434个token和5轮次,但得到了正确答案并引用了权威来源。
- 工具调用循环可能达到最大轮次——部分模型会持续搜索而不进行合成。默认的10轮次上限(可通过TEST_BANK中的按测试配置)可防止无限循环,但结果会标记为“未收敛”。查看轨迹中的
max_turns字段。增加converged可帮助需要更多轮次合成的模型,但注意部分模型会在相同URL上循环而不收敛——更多轮次无法解决模型无法合成的问题。max_turns - 无CLI覆盖(2026-07-17已修复)——脚本之前仅支持在TEST_BANK字典中按测试设置
--max-turns,需要修改源代码来调整轮次上限。这会导致必须终止后台运行来修改源代码。现在max_turns可在运行时覆盖该值。如果该标识无效,检查--max-turns N是否包含compare.py参数解析项。--max-turns - 用户偏好使用CLI模型降低成本——当用户说"use codex cli for gpt5.6"或"use cursor-grok-4.5-high"时,他们希望避免OpenRouter的按token计费。将GPT-5.6路由到Codex CLI,Grok 4.5路由到Cursor CLI,而非OpenRouter。查看上述混合模式部分。这是成本偏好,而非一次性请求。\n- Codex CLI模型版本限制——在v0.135版本会失败,提示"requires a newer version of Codex"。先通过简单提示词测试(
codex exec -m gpt-5.6-sol)。如果新版本模型不支持,回退到codex exec --skip-git-repo-check -m <model> "say hello"。\n- Codex CLI需要gpt-5.5——如果没有该标识,Codex会拒绝在git仓库外运行。始终包含该标识。\n- Cursor CLI需要--skip-git-repo-check才能启用网络访问——仅--force在无头模式下无法启用网页搜索。网络请求仍会被阻止。使用--trust --sandbox disabled(隐含--force)启用网络访问。经过3次尝试确认:--trust→被阻止,--trust→被阻止,--trust --sandbox disabled→可用。\n- OpenRouter地域限制模型——部分模型(如--force)在非美国地区调用时会返回HTTP 403"This model is only available in the United States"。没有美国代理的话无法解决。非美国地区的对比请排除这些模型。meta/muse-spark-1.1 - SearXNG默认引擎可能返回0结果——Google、DuckDuckGo、Brave、Startpage和Mojeek引擎在自托管SearXNG上经常失败(速率限制、验证码)。只有Bing和Yandex能可靠返回结果。脚本的现在会显式传递
execute_web_search。如果每次查询都返回43字符的&engines=bing,yandex,duckduckgo,google,使用{"results": [], "note": "No results found"}检查SearXNG引擎健康状态,并更新curl -s "http://$SEARXNG_URL/search?q=test&format=json&engines=bing"中的引擎列表。scripts/compare.py - DDGS CLI语法变更——旧的语法不再生效。新CLI使用
ddgs --json -q ... -m ...(输出到文件,而非标准输出)。脚本的DDGS备选方案已更新为使用新语法。如果备选方案失败,使用ddgs text -q ... -m ... -o <file>验证。ddgs text --help - SEARXNG_URL未导出到后台进程——脚本的函数从
load_env()加载环境变量,但如果将~/.hermes/.env传递给后台进程(如通过--mode tools),请确保在命令中显式terminal(background=true)。export SEARXNG_URL=http://...函数仅设置load_env()中不存在的变量,但后台shell启动时环境变量很少。os.environ - compare.py需要2个及以上模型——如果仅传递一个模型,脚本会退出并提示"Error: need at least 2 models to compare"。如果因速率限制需要重试单个模型,直接使用curl API调用,而非脚本。
- 推理强度级别对比现已原生支持(v1.2.0)——在和
--models上使用--judge语法(见上述“推理强度A/B测试”部分)。旧的包装器工具模式(provider:@effort:model_id,在加载脚本中注册虚拟提供商)仍适用于带每测试基准评审的多测试组;原生语法适用于单次运行对比。对于CLI评审模型(如Codex gpt-5.6-sol):将评分标准 + 匿名响应写入临时文件,运行/root/.hermes/cache/ab_effort_run.py,解析标准输出+标准错误中的JSON,每组测试打乱响应1/2的顺序。代码评审测试的基准来自TEST_BANK的codex exec --skip-git-repo-check -m gpt-5.6-sol "Read the file <path> and follow the instructions inside"+evaluation键(而非planted_issues)。已知结果(glm-5.3-flash,2026-08-29):强度→思考token数非单调(高强度≠更多思考);高强度版本在长工具链测试中12轮未收敛,而中强度版本完成了测试;中强度版本在质量上以4-2-2获胜(平均得分8.6 vs 7.8),高强度版本中位速度快约3倍。evaluation_criteria - Kimi K3在OpenRouter上的速率限制——在OpenRouter共享池中容易触发HTTP 429错误,尤其是在并行运行多个测试时。等待15-30秒后重试,或向OpenRouter添加Moonshot API密钥(BYOK)以获得专属速率限制。
moonshotai/kimi-k3 - 沙箱测试(S1-S5)需要支持5个工具的模型——沙箱测试会向模型传递所有5个工具定义(web_search、web_extract、run_python、read_file、write_file)。部分模型可能不支持同时调用5个工具,或一次仅支持1-2个工具。如果模型在沙箱测试中失败但在研究测试(A/B/C)中通过,可能是因为工具定义过多导致模型负担过重。先使用简单的沙箱提示词测试。
- 沙箱Python执行未完全隔离网络——工具运行
run_python,如果代码导入subprocess.run([sys.executable, script])或urllib,可能会发起网络请求。10秒超时限制了风险,但并非真正的沙箱。对于生产环境加固,考虑在容器或seccomp过滤器中运行。对于模型对比目的,超时已足够。socket - 沙箱临时文件在每个模型运行后清理——函数为每个模型创建临时目录,并在
run_tool_loop块中清理。如果模型在某一轮写入文件,后续轮次需要读取该文件,这是可行的(同一沙箱目录在多轮次中保留)。但如果脚本中途崩溃,finally块仍会清理目录。finally - 沙箱输出截断至2000字符——返回的标准输出和标准错误会截断至2000字符。如果模型生成大量输出(如打印大型列表),截断的输出可能会让模型困惑。输出简洁的模型在沙箱测试中表现更好。
run_python
Related Work
相关工作
Odysseus — PewDiePie's self-hosted AI workspace — includes a "Compare" feature for blind side-by-side model testing with conceptually similar goals (anonymous presentation, evaluation, reveal). This skill takes a different approach: pure-prompt + stdlib scripts with no UI, designed to run inside any agent's tool loop rather than as a standalone web app. Odysseus also reported a fine-tuned Qwen 32B model scoring 39% on the Aider Polyglot benchmark — a useful data point for model comparison calibration.
Odysseus — PewDiePie的自托管AI工作区——包含“Compare”功能,用于盲态并行模型测试,目标与本技能类似(匿名展示、评估、揭晓结果)。本技能采用不同的方法:纯提示词 + 标准库脚本,无UI,设计用于在任何代理的工具循环中运行,而非作为独立Web应用。Odysseus还报告称微调后的Qwen 32B模型在Aider Polyglot基准测试中得分为39%——这是模型对比校准的有用数据点。