SuperAPI AI 工具集

llm-eval-harness

测试与质量

查看项目

更新于 10-15 14:59

技能介绍

用途

LLM Eval Harness 用于实测第三方大模型接口是否真正可用、是否快速稳定、协议是否兼容、质量是否达标,而不是信任厂商宣传的数字。它把通常散落在临时脚本中的评测工作,归纳为六个维度。

六个评测维度

  • 可用性(Availability):脚本 scripts/availability_probe.py,回答哪些模型 ID 可用,采用三态错误分类。
  • 请求保真度(Request fidelity):脚本 scripts/fidelity_probe.py,检查 system prompt / tools / 历史是否真正到达模型。
  • 速度(Speed):脚本 scripts/speed_probe.py,测量 TTFT 与持续解码 tok/s,能识别思维链。
  • 并发 / 稳定性(Concurrency / stability):脚本 scripts/concurrency_probe.py,测量成功率、p50/p90 延迟以及崩溃点。
  • 协议合规性(Protocol compliance):脚本 scripts/protocol_probe.py,检查 Anthropic thinking block 是否在请求时触发,以及后续回合历史中已存在的 thinking block 是否被接受(N≥10,两者为独立检查)。
  • 质量 / 用例回归(Quality / use-case regression):脚本 scripts/usecase_runner.py 配合盲评裁判,检查是否通过累积的用例。

如何选择维度

按用户实际需求选择,不必六个全跑:接入新模型/新网关时先做可用性与保真度;验证模型 ID 可用性看可用性;模型不遵循 system prompt 看保真度;关注速度看 Speed,关注承载看 Concurrency;验证兼容端点看协议与保真度中的 tools/auth 检查;扩展思考客户端出现 400 或会话中断时,专门运行 Protocol --check history-replay;换模型担心质量下降看质量回归;向厂商报 bug 时运行相关探测并用 --output 保存,再遵循 references/vendor_evidence_protocol.md;部署闸门、常驻监控、告警误报看 references/production_testing_patterns.md。

密钥处理(不可协商)

所有脚本通过环境变量名传入 API key(--key-env MY_KEY),绝不在命令行中出现密钥值,从而避免出现在 ps、shell 历史和保存的报告中。禁止把密钥硬编码进用例文件或包装脚本。详见 references/evaluation_disciplines.md。

私有数据应存放在本技能目录之外。用例库、模型清单和密钥属于 ~/.llm-eval/(或你存放机密的位置),不应放在本技能目录——技能是通用且公开的,测试套件属于你个人。

核心问题:请求保真度最关键

保真度探测能捕捉最隐蔽的网关故障:一切返回 200 且对话流畅,但 system prompt 从未到达模型,导致任何依赖 system prompt 规则的工具在无任何报错的情况下静默行为异常。通过路由网关的投递是概率性且随时间变化的,因此需要 --repeat(默认 10)和三态结论(delivered / intermittent k-of-N / not-delivered)。

速度与并发的陷阱

  • 速度:推理模型会在单独的 reasoning_content 字段流式输出思维内容,但 completion_tokens 会统计它。只收集 content 却除以 completion_tokens 会严重夸大数值。脚本同时捕获两者,将 TTFT 取为任一类型的首 token,并报告 completion_tokens / (total − TTFT)。真实任务吞吐低于解码上限,这是正常的。
  • 并发:脚本与任何环境代理隔离(trust_env=False)并禁用 keep-alive 池化(force_close),否则测的是代理上限或单个固定上游副本。它会打印“并发证明”,并区分 HTTP 429、TCP 断连挂起超时、5xx 等不同失败模式。

协议合规性(Anthropic)

仅适用于声称兼容 Anthropic /v1/messages 的端点。--check all(默认)同时运行两个子检查:generation(请求时 thinking 是否真正产生 thinking_delta / signature_delta SSE 事件)与 history-replay(后续回合回放时,端点是否接受已存在于先前 assistant 回合中的 type: "thinking" block)。两者测试不同代码路径,可能一过一挂。合规往往是概率性的而非二元的,因此 --repeat 默认 10,两个检查都有多态结论。它会强制每个请求使用 Connection: close,防止负载均衡器把所有样本固定到单一副本而掩盖真实分布。

质量 / 用例回归(盲评)

分两半:先收集,再独立评判。

步骤一:收集模型对用例库的回答:

uv run --with openai python scripts/usecase_runner.py --base-url <…/v1> --model <model> --key-env <ENV> --usecases ~/.llm-eval/usecases.json --output-dir ~/.llm-eval/runs/<model>

步骤二:用独立盲评裁判(内联编排,不要让模型给自己打分)。对运行目录中的每个回答,启动 3 个独立 Task agent(快速评估可更少)。每个裁判只获得:prompt、answer 和该用例的 rubric,并明确告知其在隔离状态下评判,不因其他裁判或先前评估而锚定。聚合规则:用例仅在裁判多数一致时通过。按用例 tags 计算每个类别的精确率。只统计明确判定;未返回判定的裁判不算通过(沉默不等于同意)。

评分机制(LLM-as-judge 阈值、llm-rubric)也可与 promptfoo-evaluation 技能组合使用。完整方法见 references/quality_blind_judge.md。

用例库

存放在本技能目录之外(如 ~/.llm-eval/usecases.json),以便在技能更新后保留且不进入公开仓库。它是普通 JSON 列表,建议在私有仓库中对其做版本管理以累积回归套件。示例:

[ {"id": "refund-window", "prompt": "A customer asks for a refund 20 days after purchase. Reply as support.", "rubric": "1.0 if it correctly cites the 30-day refund window; 0.0 if it refuses or invents a different window.", "tags": ["support", "policy"]}, {"id": "lru-cache", "prompt": "Implement an LRU cache in Python with O(1) get/put.", "rubric": "1.0 if get and put are both O(1) via dict + doubly linked list and the self-test passes.", "tags": ["code"]} ]

assets/example_usecases.json 是可复制的起点。只有 id 和 prompt 为必填;rubric、expected 和 tags 能让评判更精确。

运行完整评估的典型流程

  1. 识别端点形态——兼容 OpenAI(/v1/chat/completions)还是 Anthropic-Messages(/v1/messages)?查询 GET /v1/models 或阅读厂商文档,不要假设。这决定哪些探测适用(协议探测仅适用于 Anthropic)。
  2. 新端点优先做可用性与保真度。
  3. 运行用户关心的维度,把每个探测的 --output JSON 写入运行目录。
  4. 如实报告,区分实测与推断,先给出用户关心的结论。若某数字看起来不可能(如吞吐远超厂商声明,或单样本的协议结论),应视为测量伪影去调查而非结果。路由网关上的速率随时间变化,冻结任何数字前应另行采样。

限制与注意事项

  • 可用性结论为三态,不是简单的通过/失败;写“不可用”列表前应先在官方文档验证每个失败 ID 是否存在。不要探测客户端标记(如 some-model[1m],通常是 CLI 客户端本地约定,不会出现在线路上)。网关的 /v1/models 列表只是一项输入,不能作为最终结论。
  • 不要因一次跨轴比较就得出“厂商/经销商 X 坏了”的结论,也不要在第一个单轴比较确认了厂商文档参数后停下。任何单一经销商确认的结果都不能视为最终,需检查厂商自有端点或真实流量。
  • 本资料未提供明确的收费、价格信息。

以上介绍仅依据资料事实整理,未展开的部分以资料为准。