@hasna/evals
开源AI评估框架——LLM作为判断+基于断言的评估,适用于任何AI应用程序。
命令行界面 (evals) · MCP服务器 (evals-mcp) · TypeScript SDK
______________________________________________________________________
安装
bun install -g @hasna/evals
# or
npm install -g @hasna/evals5分钟快速入门
1.编写数据集 (datasets/smoke.jsonl):
{"id":"q-001","input":"What is 2+2?","assertions":[{"type":"contains","value":"4"}],"judge":{"rubric":"Must answer 4 correctly."}}
{"id":"q-002","input":"Say hello","assertions":[{"type":"min_length","value":2}],"judge":{"rubric":"Should respond with a greeting."}}2.对你的应用程序进行评估:
evals run datasets/smoke.jsonl --adapter http --url http://localhost:3000/api/chat3.输出:
✓ PASS q-001 124ms
✓ PASS q-002 89ms
────────────────────────────────
2/2 passed (100%) 0.2s $0.0012______________________________________________________________________
评估案例格式
单轮
{
"id": "greeting-001",
"input": "Hello, what can you do?",
"expected": "A welcoming response listing capabilities",
"adapter": { "type": "http", "url": "http://localhost:3000/api/chat" },
"assertions": [
{ "type": "min_length", "value": 20 },
{ "type": "not_contains", "value": "I cannot" },
{ "type": "max_length", "value": 500 }
],
"judge": {
"rubric": "Should be welcoming and list 2-3 capabilities. PASS if friendly and informative.",
"model": "claude-sonnet-4-6"
},
"tags": ["smoke", "greeting"]
}多圈
{
"id": "refund-flow-001",
"turns": [
{ "role": "user", "content": "I want a refund." },
{ "role": "assistant", "expected": "asks for order ID" },
{ "role": "user", "content": "Order #1234" },
{ "role": "assistant", "expected": "confirms refund process" }
],
"judge": {
"rubric": "Should collect order ID before processing. Should not promise instant refund."
}
}通过^k(一致性测试)
{
"id": "booking-001",
"input": "Book a flight to Paris",
"repeat": 5,
"passThreshold": 0.8,
"judge": { "rubric": "Should ask for dates and destination confirmation." }
}______________________________________________________________________
断言类型
| 类型 | 检查内容 | 示例 |
|---|---|---|
contains | 输出包含字符串 | {"type":"contains","value":"hello"} |
not_contains | 输出不包含字符串 | {"type":"not_contains","value":"error"} |
starts_with / ends_with | 前缀/后缀匹配 | {"type":"starts_with","value":"Sure"} |
equals | 完全匹配 | {"type":"equals","value":"4"} |
regex / not_regex | 正则表达式匹配 | {"type":"regex","value":"\\d{4}"} |
max_length / min_length | 字符计数 | {"type":"max_length","value":500} |
json_valid | 响应是有效的JSON | {"type":"json_valid"} |
json_schema | 响应与JSON模式匹配 | {"type":"json_schema","value":{...}} |
tool_called | 调用了特定工具 | {"type":"tool_called","value":"search"} |
tool_not_called | 工具未被调用 | {"type":"tool_not_called","value":"delete"} |
tool_call_count | 范围内的工具调用次数 | {"type":"tool_call_count","min":1,"max":3} |
tool_args_match | 工具参数与预期匹配 | {"type":"tool_args_match","value":{"tool":"search","args":{"query":"AI"}}} |
response_time_ms | 限时响应 | {"type":"response_time_ms","max":3000} |
token_count | 令牌计数在范围内 | {"type":"token_count","min":10,"max":500} |
cost_usd | 成本低于预算 | {"type":"cost_usd","max":0.01} |
semantic_similarity | 预期的意义匹配 | {"type":"semantic_similarity","value":"acknowledge frustration","threshold":0.8} |
断言运行 最便宜的先 --在嵌入之前进行确定性检查。LLM法官只有在所有断言都通过时才运行。
______________________________________________________________________
适配器
配置哪个适配器将eval runner连接到您的应用程序:
# HTTP (any REST endpoint)
evals run dataset.jsonl --adapter http --url http://localhost:3000/api/chat
# Direct Anthropic API
evals run dataset.jsonl --adapter anthropic --model claude-sonnet-4-6
# Direct OpenAI API (also works with Ollama)
evals run dataset.jsonl --adapter openai --model gpt-4o --url http://localhost:11434
# MCP tool (eval your MCP server directly)
evals run dataset.jsonl --adapter mcp --mcp-command "node dist/mcp/index.js" --tool my_tool
# JS function (fastest, no network)
evals run dataset.jsonl --adapter function --module ./src/handler.js
# CLI command (pipe stdin, capture stdout)
evals run dataset.jsonl --adapter cli --command "my-cli-tool --input '{{input}}'"______________________________________________________________________
法学硕士评委
- 通过/失败/未知 --无数字刻度
- 判决前的思维链 --法官总是先推理
- 温度=0 --确定性判断
- 可配置模型 --默认值
claude-sonnet-4-6,支持任何Anthropic或OpenAI模型
"judge": {
"rubric": "Should answer in Romanian. Should reference at least one feature. Under 100 words.",
"model": "claude-opus-4-6",
"provider": "anthropic"
}______________________________________________________________________
CLI参考
# Run a dataset
evals run datasets/smoke.jsonl --adapter http --url http://localhost:3000/api/chat
# CI mode — exit 1 on regression
evals ci run datasets/smoke.jsonl --adapter http --url http://localhost:3000/api/chat --baseline main --fail-if-regression 5
# Set baseline for CI comparison
evals ci set-baseline main
# Cost estimate before running (no API calls)
evals estimate datasets/smoke.jsonl --model claude-sonnet-4-6
# Compare two runs
evals compare
evals compare main latest --markdown
# One-shot judge
evals judge --input "What is AI?" --output "AI is..." --rubric "Should define AI clearly"
# Generate eval cases from a description
evals generate --description "users asking about refund policies" --count 20 --output datasets/refunds.jsonl
# Calibrate your judge against gold labels
evals calibrate gold-50.jsonl --model claude-sonnet-4-6
# Capture production traffic as eval cases
evals capture --app http://localhost:3000 --rate 0.1 --output datasets/captured.jsonl
# Health check
evals doctor
# Register MCP server with Claude Code / Codex / Gemini
evals mcp register --claude # Claude Code (~/.claude/mcp.json)
evals mcp register --codex # Codex (~/.codex/config.json)
evals mcp register --gemini # Gemini (~/.gemini/settings.json)
evals mcp register --all # all three at once______________________________________________________________________
CI/GitHub操作
- name: Run evals
run: |
evals ci run datasets/smoke.jsonl \
--adapter http \
--url ${{ env.APP_URL }} \
--baseline main \
--fail-if-regression 5
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}______________________________________________________________________
MCP工具(用于代理)
向您的代理人注册: evals mcp register --claude (或 --codex, --gemini, --all)
| 工具 | 说明 |
|---|---|
evals_run | 运行完整的eval数据集 |
evals_run_single | 在会话中期判断单个响应 |
evals_judge | 一枪LLM法官电话 |
evals_list_datasets | 列出可用数据集 |
evals_get_results | 获取过去的跑步成绩 |
evals_compare | 比较两次运行 |
evals_create_case | 将案例添加到数据集中 |
evals_generate_cases | 根据描述自动生成案例 |
密钥代理模式 --回复前进行自检:
evals_run_single(
input: "What is the capital of France?",
output: "The capital of France is Paris.",
rubric: "Must correctly identify Paris as the capital."
)
→ PASS — The response correctly identifies Paris.______________________________________________________________________
许可证
Apache 2.0——请参阅 许可证
