dsh-eval-harness:让 Agent 应用评测的每个数字可复现

前言

给 LLM/Agent 应用做评测,常见的问题不是没有数字,而是数字不敢用:判据读的是模型自己的回答措辞,而不是服务端日志;负向断言在空回答上恒真,于是”没泄漏”被误判为 PASS;评测脚本本身有 bug,但全绿。改完 RAG、工具或提示词之后,我们想知道的是”有没有退化”,而现有做法多半只能给一个”看起来对”的总分。

下面介绍的 ltj002/dsh-eval-harness 是一套面向 DeepSeek Harness(DSH)的 Agent 应用评测技能包,维护者 LTJ002,MIT 许可证,在社区目录 SkillHub 上归入 admin-security 分类。它针对上面这几类问题给出方法学和可直接运行的脚本:判据只取外部事实、双向断言、基线按条数对比、安全类零容忍、并用变异测试验证评测器本身没坏。

这是什么

一句话定位:dsh-eval-harness 是给模型读的评测方法论(SKILL.md)加上可直接运行或改写的评测实现(assets/ 下的 Python 脚本,JUnit 落盘器用 Java),打包成 DSH 技能包。

它不是宿主功能插件。仓库里 package.json 只用 dsh.bundle 把技能注册进 ctx.skills,不提供 dsh.client、不改宿主 UI 或命令、不注入运行时代码。安装后技能以 bundled provider 形式出现在 ctx.skills 中(rank 600)。

它也不是评测平台:不连你的检索服务、不连你的模型网关,只负责”按你导出的外部事实算指标并判退化”。

框架无关是它的设计前提。LangChain、LangChain4j、Spring AI、AutoGen、CrewAI、Dify 等构建的 Agent 应用,只要满足两个前提就能用同一套判据:

  1. 对话可编程访问——暴露可调用的对话接口(HTTP/SSE 均可);
  2. 副作用可查询——工具调用、写操作留有可查询记录(审计表、结构化日志或 DB)。

判据从这些外部事实读取,不读模型的自我陈述。换框架只改适配层,不改判据。

核心能力

分五块看。

1. 三层评测:离线断言 + 在线真打模型 + 基线对比。

  • eval_online.py:在线评测骨架,四套件 tool / inject / answer / multi-turn,对应的是真实调用链路上的判据;
  • eval_rag.py:检索层指标 Recall@K、MRR、nDCG@K、Precision@K;
  • eval_rag_answer.py:生成层 Faithfulness、引用准确性、完整性、矛盾检测,基于人工标注对,不用模型互评;
  • eval_baseline.py:与基线按用例对比,掉条数就红。

2. 双向判据,避免”假绿”。

判据要么正向(该答的答了),要么反向(不该答的没答、不该出现的没出现)。安全类用例反向判据尤其重要:答了敏感内容就是失败,而不是”没答对”。eval_online.py 把五条防误报纪律固化成代码:

# ① 工具是否被调用 → 查审计日志,不看回答措辞
called = tool_calls_of(conversation_id)

# ② 降级跳过:负向断言在空回答上恒真,不能算 PASS
if is_degraded(text, cost):
    continue

# ③ PII 判"未打码",不判宽禁词
UNMASKED_PHONE = re.compile(r"(?<!\d)1[3-9]\d{9}(?!\d)")

# ④ 观测不到 → None,不进分母也不判失败
called = tool_calls_of(cid)
if called is None and needs_tool:
    unobservable += 1
    continue

# ⑤ 401/402 基础设施异常单独计 errors:不因重试恢复,退出码升 2
except urllib.error.HTTPError as exc:
    if exc.code in (401, 402):
        errors += 1

第 ② 条针对的是空回答陷阱:模型没答,反向断言自然成立,看起来”没泄漏”,其实是没跑。第 ④ 条是分母纪律:观测不到的数据不进分母,避免”因为没测到而通过”。

3. 三档严格度,安全类零容忍。

kind 默认容忍波动 理由
offline 0 条 纯函数无随机性,掉 1 条就是真掉了
live-strict 0 条 安全/编造类门禁(提示词泄漏、PII、越权)
live 1 条 普通能力类,波动必须留痕

live-strict 的取舍是明确的:模型输出的随机性可以解释能力波动,解释不了泄漏。

4. 变异测试,验证评测器自己没坏。

assets/mutation_check.py 在临时副本上把实现改坏,验证断言是否真的会翻红。这是对”评测脚本在骗自己”这一风险的直接回应。assets/selftest.py 是判据与分母纪律的回归自检,改任何脚本后都要跑。npm test 还包含 EvalResults.java 的编译加运行冒烟(无 JDK 时显式跳过)。

5. 治理与可追溯。

eval_governance.py 提供根因分层、数据集治理、Judge 校准三件套——Judge 一致率与 kappa 不达标就禁止进门禁。eval_manifest.py 对提示词与数据集做 sha256 指纹并记录 config diff,eval_report.py 出汇总报告但只读、不设门禁。实验口径由 eval_manifest.py 与 ci-eval.yml.example 这三处共同约束。

安装与启用

安装命令取自仓库 README,是仓库 URL 形式,不要按 dsh plugin add github:owner/repo 拼接:

dsh plugin add https://github.com/LTJ002/dsh-eval-harness

装完不需要把技能复制到项目的 .agents/skills,会话内通过技能目录或 @ai-eval-harness 引用即可。

需要说明的是,package.json 刻意不写 dsh.compatibility.dsh(宿主版本范围)。README 给出的理由是本包只依赖公开的技能注册接口,未经多版本 DSH 宿主实测,因此不声明兼容范围。engines.node >= 20 是本仓库开发与 CI 的构建期要求,不是 DSH 宿主版本要求。当前版本 1.0.0。

典型用法

第一步,建数据集。assets/datasets/*.example.jsonl 是格式样板,不是测试题库,里面的问法来自写作时的示例项目(摄影订单),与你的业务无关。按下面步骤换成自己的:

  1. 把 *.example.jsonl 复制成 eval/datasets/ 下的真实数据集,问题、期望文档、期望答案、禁词全部换成你的业务内容;
  2. 期望值(expected / mustContain / 预期工具)必须有真实出处(知识库文件、接口文档),不要凭感觉写;
  3. 正向、反向、多轮、检索标注对都要覆盖,格式不变。

不需要重写的是判据引擎:eval_rag.py 的指标数学、eval_baseline.py 的严格度、eval_online.py 的五条纪律、mutation_check.py 的门禁机制与业务无关,换项目零改动。

第二步,对接适配层。eval_online.py 是骨架,login() / chat() / tool_calls_of() 要按你的项目契约改写。assets/adapters.py 通过 EVAL_ADAPTER 指向项目侧模块,未实现的函数回退内置 base。词表也外置了:markers.py 加 markers.default.json(7 组)必须与 eval_online.py / eval_governance.py 一起复制,否则 import 会给可行动错误;换业务词表用 EVAL_MARKERS 覆盖。

第三步,跑基线对比与自检:

python skills/ai-eval-harness/assets/selftest.py          # 判据与分母纪律回归自检
python skills/ai-eval-harness/assets/mutation_check.py    # 变异测试:断言必须翻红
npm test                                                   # bundle 结构冒烟,含 Java 落盘器编译运行

退出码约定:

码 含义
0 通过
1 质量失败(真实退化、真实泄漏)
2 结果不可用(路径错、数据集缺、全降级、观测不到、分母变化、401/402)——先修 harness,别当退化

退出码 2 是这套设计里容易被忽略的一点:结果不可用和质量失败分开,避免把”环境没配好”误判成”应用退化了”。

适用场景与注意

适合这样的团队:有 LLM/Agent 应用在持续迭代(改 RAG、工具、提示词),有可查询的服务端副作用记录,希望用可复现的判据而不是模型互评来守门禁。

几处边界在动手前要清楚:

  • eval_online.py 是骨架,接口和数据集都要按项目改写,assets/datasets/*.example.jsonl 必须整体替换;
  • eval_rag.py / eval_rag_answer.py 不连接任何检索或生成服务,retrieved、supportFacts、citations、requiredPoints 等标注对由你的系统导出或人工标注;
  • 判定逻辑的回归自检 monkeypatch 模块级函数,验证的是判定纪律,不是真实网络路径,真实连通性仍需跑一次在线评测;
  • 整句语义相似度、答案是否”自然”这类判断不在工具内,需要模型互评或人工评审,按第一原则不进门禁;eval_governance.py judge 只负责校准 Judge 是否够格当辅助分;
  • 多轮套件与工具五阶段的判据设计已实现(run_multi_turn_suite / check_tool_stages),但对应数据集需按业务改写,tool_call_records() 的完整副作用记录接口需按项目审计表对接。

这个技能包以当前 DSH 进程的权限运行,注册的是方法学与脚本而非宿主能力。安装前应自己读一遍仓库源码,确认 SKILL.md 的判据设计和 assets/ 的实现与项目合规要求一致,并确认 MIT 许可证可接受。另外,仓库当前星标为 0、无 fork,属于新项目,README 里声称的四项本地验证(结构冒烟、判据自检、变异测试、Java 冒烟)以其仓库 CI 与本地运行输出为准。

相关链接

  • 目录页(社区目录,独立站点,与 DeepSeek / 幻方无官方从属关系):https://www.skillhub.cn/plugins/LTJ002/dsh-eval-harness
  • 源码与完整文档:https://github.com/LTJ002/dsh-eval-harness
  • 英文版 README:仓库内 README.en.md
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜