DeepSeek Harness 耗时拆解插件

前言

DeepSeek Harness(DSH)在模型推理、工具调用等环节的耗时往往混杂在一起,开发者难以从单次会话中判断「哪一段花了多久」。常见的做法是凭感觉调整超时、重试策略,或通过日志人工统计,效率低且容易遗漏细节。

这里介绍一个给 DSH 用的耗时统计插件:dsh-answer-timing。它不注入任何客户端代码,也不改动 UI,只旁听会话事件流,把一次回答拆成「模型」「工具」「其它」三个阶段,并给出明细。

它是什么

dsh-answer-timing 是一个纯 host 端的 DSH 插件,由维护者 liuzhihao-min 维护,分类为「模型推理」。它通过订阅 DSH 内部事件(step/start、assistant/message、tool/call、tool/result 等),计算每轮回答的耗时分布,并提供工具 timing_report 和技能 answer-timing,方便查询与落盘。

核心功能

耗时分段

对每一次回答(turn),拆成三段:

段 含义 来源
模型 思考 + 生成的总时间;内部再分「首字」和「生成」 step/start → assistant/message
工具 每个工具的实际执行时间,按工具名累加 tool/call → tool/result(按 callId 配对)
其它 总时长减去上面两项:调度、审批等待、排队 turn 起止差 − 模型 − 工具
  • 首字(ttft):从 step/start 到这个 step 第一个推理/文本 chunk 的时间(读 stream 里的 time0)。
  • 生成(decode):首个 chunk 到 assistant/message 落定的时间。
  • 总时长:这一轮第一个带 data.turn 的事件到最后一个事件的时间差。

输出示例

每次回答结束,末尾一行:

⚡ 本次 1m23s = 模型 58s(首字 1.2s · 生成 41s)+ 工具 19s(pwsh 12s · read 4s · grep 3s)+ 其它 6s

需要明细时(detail: true),给三张表:阶段构成 / 工具累计 / 逐步骤。

工具:timing_report

参数 说明
scope last(默认)/ turn / session / turns
turn 指定轮次(配合 scope: "turn")
limit scope: "turns" 取最近几条,默认 10
detail true 时给「阶段构成 / 工具累计 / 逐步骤」三张表

技能:answer-timing

配套技能 answer-timing 会让 agent 在每次回答末尾自动附上那一行。

安装与启用

前置要求

  • DSH >=0.2.1-rc.2 <0.3.0
  • Node.js >=24

最快:一条命令

推荐使用 npm 源(国内网络环境更稳定):

dsh plugin --profile <你的 profile> add dsh-answer-timing

或者直接把仓库地址给它:

dsh plugin --profile <你的 profile> add https://github.com/liuzhihao-min/dsh-answer-timing

两种写法底层都是 pnpm,装完会读取包里的 dsh.bundle 清单,自动把包写进 dsh.profile.bundles——不需要手动改 package.json,也不需要建 junction。然后完全退出 DSH 再启动。

桌面版 profile 名一般是 desktop,Web 版是 web。

从源码安装(想改代码时)

git clone https://github.com/liuzhihao-min/dsh-answer-timing
cd dsh-answer-timing
node install.mjs

脚本会做四件事(全部可重复执行,幂等):

  1. <profile>/.dsh-answer-timing-source → 本仓库(Windows 用 junction,macOS/Linux 用 symlink)
  2. <profile>/node_modules/dsh-answer-timing → 本仓库
  3. dependencies["dsh-answer-timing"] = "link:.dsh-answer-timing-source"
  4. dsh.profile.bundles 末尾追加 dsh-answer-timing

写 package.json 前会自动备份成 package.json.bak-<时间戳>。改完同样要完全退出 DSH 再启动。

常用参数:

参数 作用
--dry-run 只打印将要做什么,不写文件
--profile web 指定其它 profile(默认 desktop)
--dsh-home D:\x 指定 DSH 目录(默认 ~/.dsh 或 $DSH_HOME)
--force 目标位置是真实目录时,改名备份后继续
--uninstall 卸载:摘掉 bundles / 依赖 / 两个链接

卸载时 DSH 必须先退出。 否则 node_modules 里的链接被占用删不掉(脚本会警告并跳过,注册信息仍会清干净,退出后再跑一次即可)。

从 npm 手动安装(不用 dsh plugin add 时)

包已发布:dsh-answer-timing。

在当前 profile 目录(桌面版一般是 ~/.dsh/profiles/desktop)里装:

cd ~/.dsh/profiles/desktop
npm install dsh-answer-timing

然后在同一个 package.json 里补两处:

{
  "dependencies": {
    "dsh-answer-timing": "^1.0.0"        // ① 依赖
  },
  "dsh": {
    "profile": {
      "bundles": [
        "dsh-answer-timing"               // ② 末尾追加这一项
      ]
    }
  }
}

从 npm 装的不用建 junction —— 包已经在 node_modules 里了。install.mjs 是给源码目录用的。改完同样要完全退出 DSH 再启动。

手动注册(不想跑脚本时)

# 1. 目录联接(换成你自己的实际路径)
cmd /c mklink /J "$env:USERPROFILE\.dsh\profiles\desktop\.dsh-answer-timing-source" "D:\plugins\dsh-answer-timing"
cmd /c mklink /J "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-answer-timing" "D:\plugins\dsh-answer-timing"
// 2. package.json → dependencies 里加一行
"dsh-answer-timing": "link:.dsh-answer-timing-source"
// 3. package.json → dsh.profile.bundles 末尾追加
"dsh-answer-timing"

然后完全退出 DSH 再启动。

验证

对话里问一句「刚才那轮花了多久」,或直接调用 timing_report。工具存在即安装成功;~/.dsh/timing/turns.jsonl 会在第一轮结束后出现。

落盘与隐私

  • 路径:$DSH_HOME/timing/turns.jsonl(未设 DSH_HOME 时用 ~/.dsh/timing/turns.jsonl)
  • 一行一个 turn,按 sessionId + turn 去重
  • 只存:时间戳、各段毫秒数、输出 tokens、工具名、模型名
  • 不存:提示词、回答正文、工具参数、任何对话内容
  • 默认保留 30 天(读取时按 retentionDays 过滤,不改写文件)

配置

键 默认 说明
dataDir 空 自定义落盘目录
retentionDays 30 历史保留天数
maxTurnsInMemory 200 每会话内存里保留多少轮

口径与限制

  • 一个 step 若产生多条 assistant/message(重试/多次 attempt),只记最后一次,其余不累加。
  • 没有 step/start 锚点的 step 不臆造耗时,只计入 untimedSteps,这样能和官方 sessionStats 的口径对上。
  • 工具审批等待发生在 tool/call 与 tool/result 之间,因此算进「工具」而不是「其它」。
  • 子代理是独立 session,各自统计;主会话里 subagent 调用的等待算在主会话的「工具」。
  • 宿主重启后,内存里的逐轮状态从零开始;历史请用 scope: "turns" 读落盘账本。
  • 这是观测插件:不改变任何调度、超时或重试行为。

适用场景与注意

  • 适合需要精细化分析模型推理耗时、工具调用成本、整体会话延时的场景。
  • 插件以当前 DSH 进程权限运行,安装前建议阅读源码与许可证。
  • 兼容性依赖 DSH 的会话事件字段(step/start、assistant/message、tool/call、tool/result、turn/end),这些是内部接口,随版本可能变动。

短结尾

通过 dsh-answer-timing,可以把「这次回答到底花了多少时间、花在哪」变成可查的数据,方便持续优化推理与工具调用的成本。目录页与 GitHub 仓库见下:

  • https://www.skillhub.cn/plugins/liuzhihao-min/dsh-answer-timing
  • https://github.com/liuzhihao-min/dsh-answer-timing
羽毛球分组比赛记分
小程序二维码

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

Xiaoye