DeepSeek Harness Hub
← 返回列表

请求指纹校验jwilson411/dsh-modelprint

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

固定请求配置卡片,漂移时结构化报告差异字段

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/31 · 已提供中文文档

DeepSeek Harness 插件:指纹提供方、模型 ID、采样、工具 schema 和系统提示词前缀;固定卡片并在漂移时以结构化方式失败。

综合分
28.2
GitHub 分
28.2
用户评分
★ Stars
0
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add jwilson411/dsh-modelprint
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools@deepseek-ai/cordis
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-modelprint

一个 DeepSeek Harness 函数插件,它将每个请求指纹化为一张小型卡片——提供方、模型 id、所请求的采样参数、模型实际被提供的工具 schema 的哈希,以及模型实际被赋予的系统提示前缀的哈希——并通过一个面向模型的工具 modelprint_check,将这张实时卡片与磁盘上固定的卡片进行对比。

其范围只涉及一个问题:这是否和上次是同一套配置? 当某次运行已知良好时,固定该卡片;此后该工具会以结构化匹配作答,或列出每一个发生漂移的字段。它不访问网络、不加载模型,也不需要密钥——唯一的 I/O 是读取固定文件。

它不是什么

- 不是水印。 提示中不嵌入任何内容,输出中也不恢复任何内容。卡片由 harness 组装的请求构建而成,且只会与你写入的文件进行比较。
- 不是权重替换检测器。 若提供方在稳定别名背后更换权重,会生成字节完全相同的卡片。这能捕获请求所显示的内容;它无法看穿别名背后。
- 不是模型认证产品。 没有证明、没有签名、没有质询——匹配的卡片只能证明你这一侧的调用没有变化,而非证明是什么做出了应答。

这些都不是指控。漂移的常见原因是你自己的仓库:注册了一个工具、编辑了系统提示、有人在补丁层设置了 temperature。这正是本插件使其可见的那类变更。

一旦你有意更改工具或系统提示,它就会误报——这正是重点。 从进程内部看,有意的更改和未被察觉的更改看起来完全相同,因此插件会同时报告两者,由你判断。之后重新固定,噪声就会停止。

安装

dsh plugin --profile web add github:jwilson411/dsh-modelprint

dsh plugin 会在 $DSH_HOME/profiles/web 内转发给 pnpm,然后协调 profile:由于此包的清单声明了 dsh.bundle.patch,它会被追加到 profile 清单有序的 dsh.profile.bundles 列表中,其 cordis.patch.yml 则成为一个层。移除方式相同,只需将 add 换成 remove。

固定的 DSH 候选发布版

此包是针对固定的候选发布版 0.1.1-rc.2 编写和测试的——@deepseek-ai/dsh-tools@0.1.1-rc.2 被精确固定在 devDependencies 中,以便测试针对一个已知 API 运行,而 peer 范围为 ^0.1.1-rc.2,与 harness 自身工具包的声明方式一致。

请注意,@deepseek-ai/dsh-tools 的 npm latest 标签仍指向较旧的 0.0.1-rc.1;0.1.1-rc.2 系列发布在 next 下。请显式固定,而不要依赖该标签。

它注册的内容

| | |
|---|---|
| Cordis 插件 id | modelprint(cordis.patch.yml 中的行 id) |
| 注入 | tools——硬依赖;插件会等待而非降级 |
| 工具 | modelprint_check |
| 参数 | pin(字符串,可选)、request_json(字符串,可选) |

pin 默认为已配置的 pin 路径。request_json 会为那一次调用而非实时卡片生成已保存请求的指纹,并且刻意不覆盖它——一次性检查绝不能覆盖描述测试框架实际发送内容的卡片。

每条路径都返回相同的结构,包括每一次失败:{ match, ok, pin, live, pinned, mismatches, reason, detail, plugin }。缺失的 pin 文件是 PIN_MISSING,而不是抛出的 ENOENT;无法解析的 JSON 是 PIN_INVALID;在记录任何内容之前进行检查是 NO_LIVE_CARD。匹配时 reason 为 OK,否则为按比较顺序出现的第一个不同字段——model、provider、tools、system prompt,然后是 sampling——因此诊断会先给出别名,而不是温度。

卡片

| 字段 | 来自请求 | 备注 |
|---|---|---|
| provider | provider | 当请求未指定任何 provider 时为 null |
| model | model / modelId / model_id | 实际发送的 id,而非营销名称 |
| temperature | temperature | 当未要求任何温度时为 null |
| top_p | top_p / topP | 仅在存在时记录;绝不使用默认值 |
| tools_hash | tools | 规范工具列表的 SHA-256 |
| system_prompt_prefix_hash | 见下文 | 规范化前缀的 SHA-256 |

即使 DSH 当前的 GenerateOptions 没有这样的旋钮,top_p 也会被记录:它没有成本,并且能让未来的旋钮——或另一个主机的请求——可见,而不是被静默忽略。缺失的 pin 记为 null,而 null 与 null 匹配,因此未指定任何温度的 pin 会匹配未要求任何温度的请求。pin 文件中的额外键(日期、注释、备注)会被丢弃,而不是被比较。

tools_hash 按名称排序

工具列表在哈希之前被规范化为 [{ name, description, parameters }, …] 并按 name 排序。注册顺序不是关于模型表面的事实,因此它被排序消除,而不是被允许产生误报——两个以不同顺序注册相同工具的配置文件会哈希相同。函数会被丢弃:模型永远看不到 execute 主体,只看到 schema。数组(普通数组,或 OpenAI 风格的 { type: 'function', function: {…} })和 { [name]: descriptor } 映射都被接受。完全没有工具时会对空列表 [] 进行哈希。

系统前缀规范化

前缀按优先级顺序为:

1. 请求上的 system / systemPrompt / system_prompt,按文本读取;或
2. messages(或 input)中开头连续一段 role: "system" 消息,用 \n 连接,并在遇到第一个其他角色的消息时停止——在对话中途注入的系统消息不是前缀,不会被哈希。

内容从普通字符串、块数组({ type: 'text', text } 或裸字符串)或带有 text 字段的对象中读取;其他任何内容——图像、工具结果——都不贡献任何内容。然后文本在
哈希:CRLF 和 CR 折叠为 LF,并且前导和尾随空白会被
修剪。 其他内容都不会被改动,因此提示词内部更改一个词仍然会
改变哈希,而跨平台迁移的文件则不会。

没有系统文本的请求其前缀为 '',其哈希是空字符串的 SHA-256
—— e3b0c442… —— 而不是某个哨兵值。空工具列表同理:缺失和
空是同一个可观察事实,两者都会哈希为一个真实的摘要。

固定

固定(pin)是一个 JSON 文件,保存你希望将运行约束到的卡片:

{
"provider": "deepseek",
"model": "deepseek-chat",
"temperature": 0.2,
"top_p": null,
"tools_hash": "841e5f22…",
"system_prompt_prefix_hash": "d2c86f05…"
}

完整的示例见 examples/modelprint.pin.json。
编写第一个固定文件最简单的方式,是对一个不存在的路径调用一次
modelprint_check,然后从 PIN_MISSING 结果中复制出 live
卡片。

文件的读取位置,按优先级顺序:

| 来源 | |
|---|---|
| config.pinPath | 组合补丁中插件行的 config |
| DSH_MODELPRINT_PIN | 环境变量回退 |
| modelprint.pin.json | 默认值,相对于工作目录 |

无论哪种方式,路径都会被解析为绝对路径,并且补丁行优先于
环境变量:补丁行是部署所声明的意图,因此不应被环境变量
静默覆盖。

从配置文件自身的 cordis.patch.yml 中设置它——注意,以 id 为目标的
补丁会替换该行的整个 config,因此要重新声明你打算保留的每个字段:

- id: modelprint
config:
pinPath: ./modelprint.pin.json

该 bundle 自身的行故意不携带 config:一个不固定任何内容的配置文件
仍然会记录指纹,并且仍然会从工具获得结构化的
PIN_MISSING。

实时卡片如何被记录

该插件在 agent/request 上记录——即 agent 组装后的请求——并且,
对于只发出较低层级事件的主机,在 llm/stream 上记录,后者携带
等价的 GenerateOptions。两者都是可选的,将同一张卡片记录两次
是无害的。

每个监听器都是直通式的:它调用瀑布流的其余部分,记录输入和输出中
仍然看起来像请求的那一个——next 返回的值优先,因为卡片应当描述
真正将要发送的内容——并原样返回该链的值。一个不携带卡片所读取的
任何字段的值会被忽略,而不是被指纹化为谎言。

既不发出这两个事件的主机有两条途径,并且完全不需要事件:

import { recordRequest } from 'dsh-modelprint'

recordRequest(request) // returns the card it stored

或者将请求作为 request_json 传给工具以进行单次检查。

布局

package.json          manifest + dsh.bundle.patch — what makes this a bundle
cordis.patch.yml      the bundle's patch layer: one insert, one plugin row
src/fingerprint.js    纯逻辑部分:卡片、哈希、pin 文件、diff
src/index.js          插件:name、inject、apply(ctx, config)、工具
examples/             一份可供复制的 pin 文件
test/                 基于已提交 fixtures 的离线测试
package-lock.json     npm ci 在 CI 中安装的锁定依赖树

测试
sh
npm install
npm test

从构造上就是离线的。fingerprint 这一半除了 node: 和本包之外不导入任何东西,并且它的文件读取都经过注入的 readFile 接缝,因此缺失 pin 和无效 pin 的路径无需接触磁盘即可被覆盖。
apply 接收一个桩上下文,该上下文会记录注册项和事件监听器,而该工具通过与注册表调用的同一个 execute 来驱动,结果会对照锁定为 0.1.1-rc.2 的真实 @deepseek-ai/dsh-tools 进行验证。不会启动任何 profile,不会打开任何套接字,不会读取任何密钥。

CI(.github/workflows/ci.yml)会在 Node 22 和 24 上,基于已提交的 lockfile 运行 npm ci 和 npm test,且仅针对公共 registry。它不需要任何凭据,测试套件也不会访问网络。

不在范围内

- 检测权重替换。 上文已说明:相同请求,相同卡片。
- 水印或输出取证。 不嵌入任何内容,也不读取任何响应文本。
- 对提供商进行身份验证。 没有签名,没有证明,没有挑战。
- 存储历史记录。 内存中只有一张实时卡片,磁盘上只有一张固定卡片。
没有账本,没有 sidecar,也没有需要迁移的状态。
- 替你做决定。 该工具会报告不匹配;至于这是漂移还是你刚刚所做的更改,它不会尝试作出判断。

许可证

MIT — 见 LICENSE。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群