跳到正文
dsh-market 浏览插件 GitHub EN

Six6stRINgs/dsh-thinking-token-stat

在底部 Dock 添加模型思考 token 统计信息的轻量化插件。

Star 数 ★ 1 分类 用量与计费 收录于 2026-09-07 npm dsh-thinking-token-stat

安装

在 DeepSeek Harness 里通过 dsh-market 安装

dsh plugin --profile web add dshmarket

或使用命令行

dsh plugin --profile web add dsh-thinking-token-stat

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。

截图

README

English | 中文

在输入框下方的统计行里,一眼看到整场对话的思考 token 总量。点开还能看到它占推理输出的 比例、有多少轮真正思考过,以及其中多少是推算而非上报的。再点进去,可以逐轮看,并看到每一轮 跑的是哪个模型。

输入框下方的读数,以及展开后的总览

输入框下方那一行读数,以及点开后的一级界面:整场思考总量、两个比例、多少轮真正思考过、 其中多少是推算而非上报,以及这些数字实际覆盖的范围。

逐轮明细

二级界面:逐轮表格。每一轮一行,包含该轮思考、本轮输出、数字来源、该轮跑的模型, 以及它占本轮输出的比例。

你会看到什么

在输入框下方那一行统计里,多出一个读数:

💭 37.2K · 70.7% · 4 / 6 轮
  • 整场对话的思考 token 总量;
  • 它占推理输出的比例,也就是模型在思考状态下写出的内容里,思考占了多少;
  • 有多少轮真的思考过。这一项只在会话里存在"没思考的轮次"时才出现, 所以全程使用同一个推理模型时,这一行依然简短清爽。

点一下可以看明细。

为什么不再有"每条回复"的读数

DSH 官方每条回复自带的用量面板里,已经有那一轮的推理 token 数,而且那个面板给出的该轮信息 更多。本插件早先版本在每条回复旁显示的数字,实际上只是把点开面板就能看到的东西又重复了 一遍,因此被移除了。

官方显示不出来的,是模型根本没有上报的数字。与其在每条回复旁放一个推测值,不如把它放在 会话明细里单独一行,并写明哪一部分是推算出来的。

明细里有什么

本次会话思考 token                            37.2K token
──────────────────────────────────────────────────────────
思考 / 推理输出 token (52.6K token)              70.7%
思考 / 全部 token (12.4M token)                   0.3%
推理轮次                                      4 / 6 轮
未上报推理的轮次                 2 轮 · ~5.1K token
                              估算约 5.1K token ?
统计范围:全量会话,共 6 轮,其中 1 轮没有产出消息。 ?
行 含义
思考 / 推理输出 模型在思考状态下写出的内容里,思考占多少
思考 / 全部 token 同一比例,换成这些轮次被计费的 token 总量作分母
推理轮次 多少轮思考过 / 一共多少轮
未上报推理的轮次 有多少轮只能用推算值代替上报值,以及这些推算值占总量多少
估算约 … 同一笔推算值再用文字说明一次,旁边的 ? 解释推算依据
统计范围 这些数字实际覆盖了什么(按折叠结果算,不是写死的):总轮数、没有产出消息的轮次、fork 被排除的继承历史、以及逐轮明细自身的上限;只要其中任何一项成立,就会带一个 ? 说明原因

百分比保留一位小数;数字较大时会简写,例如 24.8K。

靠推算得来的数字前面会加 ~(~37.2K、~70.7%),输入框那一行和明细里都一样。估算值 旁边的 ? 会弹出一条简短说明,讲清楚为什么会有估算值;和明细本身一样,点别处它就消失。

明细最下面有一行,可以进入逐轮视图。

逐轮明细

逐轮视图每一轮一行,最新的一轮排在最前面:

列 含义
轮次 这是第几轮
思考 这一轮的思考 token;若是推算值,会带 ~ 并用蓝色标出
本轮输出 这一轮一共写了多少,也就是最后一列的分母
思考来源 这个数字是怎么来的:提供方直接上报、按思考文本推算,或两者都有
模型 这一轮跑的是哪个模型
占输出 这一轮的思考占它自己输出的多少(带 ~ 表示是推算值)

表格上方有三个开关,决定列出哪些轮次:直接上报的、按文本推算的、以及完全没有思考数字的。 最后一类默认关闭——没思考过的轮次逐条列出来没有意义,开关上会写明被隐藏了多少条。

对话开始过的每一轮都会列出,包括失败的那些。 报错或被中断的轮次不会产生回复,因此没有 token 可统计;但它仍然会出现,每一列都是 —、来源是「未提供」——静默跳过它会让表格看起来 像少了一轮,而实际上那一轮什么也没产出。「未提供」开关上的数字里就包含这些轮次,总览的 统计范围那一行也会写明有几轮是这样,并用 ? 说明它们"没有产出消息"而不是"没有思考"。

每次只渲染一页 100 轮。 长对话会变成一张很长的表,为了看十条而铺开一千行是没人要的开销, 所以页面里只存在当前这一页:用 更新的 / 更早的 和 第 2 / 5 页 翻页。

每一行末尾有一个跳转按钮,可以跳到对话里那一轮的回复。对话视图只渲染已加载的那段窗口, 所以目标轮在窗口之前时,按钮会让 DSH 先把历史翻页到那一轮——与官方回合导航条用的是同一个 调用——然后落到那条回复上。

明细可以从任何地方关掉。 点输入框区域的其它控件、点界面以外的任何位置,一级和二级面板 都会消失,按 Esc 也一样——和 DSH 官方那套统计面板的行为一致。

数字是从哪里来的

这个插件由两半组成。宿主半边把会话事件日志逐轮折叠一次,并把结果注册成一个 DSH 会话投影 ——和官方统计用的是同一套机制;浏览器半边只读这一个值,然后把它画出来。

这就是全部设计,也是这些数字可信的原因:

  • 折叠覆盖整条日志,而不是窗口。 DSH 把对话保存成"最近的一段窗口",压缩还会重写这个窗口, 所以任何"按屏幕上有什么来算"的数字都是局部且易变的。投影是从每一条已提交事件折出来的, 随会话一起做检查点,冷读时只补折水位之后的事件——于是这些数字天然是整场的,多长的对话都一样, 刷新后也完全一致。
  • 数字永远不靠加载和翻页。 插件不会把消息读回对话来计数。数字没有"加载更多",因为根本 没有东西要加载:宿主早就折完了。唯一的例外是跳转按钮——你明确点了要去看某一轮,它才会 让 DSH 把历史翻页到那一轮,这是一次点一下、读一轮的读取。
  • 浏览器里什么都不缓存。 没有 localStorage、没有账本、没有按会话的浏览器状态。持久化就是 投影自己的检查点,它属于会话,而不属于这个插件。
  • 每条与助手结算无关的事件都是零开销,折叠本身每轮只保留六个数字加一份模型名字典。在一场 真实的 88 轮会话上,它用约 5 毫秒折完 8 988 条事件,落盘 3 KB。

如果宿主提供不了这个投影——旧版 DSH,或者会话还没折过——读数会退回到官方的整场 token 投影, 并在界面上写明,而不是凭空编造逐轮数字。

它占多少存储

折叠的检查点是 DSH 自己那套投影缓存里的一行 (<root>/session_projcache/sessions/<sessionId>.json),和官方那些单元放在一起。一行就是每轮 六个数字加一份共享的模型名字典,所以大小只取决于轮数:

轮数 落盘状态 发给浏览器的视图
88(实测的一场真实会话) 3.0 KB 2.4 KB
1 000 ≈ 35 KB 只发最新 500 行
5 000(状态自身的上限) ≈ 175 KB 只发最新 500 行

作为对比:DSH 自己的 turnOutline 单元为同一场会话保存的逐轮记录比这更大,contextBreakdown 的状态是 54 KB。发布给客户端的视图刻意做了上限:宿主每次变化都会把整个值重发一遍,所以逐轮 行只保留最新 500 行(≈15 KB),而合计始终是整场的;超出时总览里会有一行说明。

模型列的数据来自哪里

每条结算的助手消息都自带产出它的 provider 与 model,折叠时就把这个名字记在所属的那一轮上—— 只在字典里存一次,而不是每行重复。某一轮如果重试后换了模型,两个名字都会列出。这不需要 DSH 的 Trajectory 视图,也不会为它多建一份折叠。

数字是怎么来的

能不能读到一个数字,取决于模型提供方:有的会上报推理 token 数,有的只把思考文本发过来, 还有的两者都不提供。

提供方给了什么 你会看到什么
推理 token 数 直接采用,精确
只有思考文本 按文字长度推算出来的数字
两者都没有 什么都不显示——这条回复计为没有思考

为什么有些数字必须靠推算。 并非所有提供方都会上报推理 token 数,DSH 也无法强制。 但如果一遇到没有数字就把思考文本也丢掉,就有一整类模型会显示成"完全没思考过"——可思考内容 明明就在屏幕上。所以这里改为量文字长度,而且按语种取不同密度——用一条英文规则去量别的 语种,会低估两到四倍:

文字类型 每 token 字符数 依据
中日韩文字、日文假名、韩文谚文、全角形式 1 这类文字实测约 0.6–1.7 token/字符(取决于分词器),而 DeepSeek 与 Qwen 自家的分词器处于最密的一端(约 0.6–0.8)
西里尔、希腊、阿拉伯、希伯来、亚美尼亚、印度诸文字、泰文、格鲁吉亚文 2.5 比 CJK 常见但仍不如英文;实测大致在 2–3 字符/token
拉丁字母、数字、标点、空白 4 英文的常用经验值

密集一端取 1 而不是 0.7 是有意的:对中文优化的模型来说这会略微偏高,而"偏高一点"比 "看起来像实测、实际上偏低"要好。

这是推算而不是测量,我们也是按推算来对待的:靠它得出的每个数字都带 ~,明细里写明有多少轮 需要推算、这些推算值占总量多少,旁边那个 ? 点开就是这套规则本身。

这套区分要花多少代价。 每个思考文本块两次 replace,折叠依然是插件里最快的一环:实测在 本会话 230 万字符的思考文本上,按语种折算只比"一刀切"多花 1.7 毫秒,而整个折叠是 5 毫秒—— 约合每次结算 5 微秒,由宿主一次性付出、直接进入持久投影,完全不在渲染路径上。

所有比例只统计真正思考过的那些轮次。这是有意的:当你中途切换到不思考的模型,已经显示的 数字不会因为对话变长而开始下滑。同时,"4 / 6 轮"也直接告诉你这个数字覆盖了整场对话的多少。

这个插件做什么、不做什么

做:把一场对话里的思考量汇总起来,并说明这个数字是怎么得出来的。

不做:

  • 不修改对话、不干预模型,也不向任何地方发送内容;它在宿主侧读会话自己的事件日志、以及 DSH 提供的投影,不发起网络请求;
  • 模型没有思考、或没有把思考暴露出来时,它不显示任何东西;
  • 不假装精确。提供方上报的数字是精确的;由思考文本推算出来的不是精确值,明细里会标明 它是推算出来的;
  • 不统计"窗口"而统计会话本身。这些数字属于整场会话,所以分页和压缩都改不动它们;
  • 不会在你背后读历史。宿主折的是它本来就有的日志,浏览器半边从不读取任何一条消息来计数; 它唯一能让宿主加载的,是你明确点了要跳去的那一轮;
  • 不往你的浏览器里写任何东西:没有 local storage,也没有插件自己的状态。

轻量

  • 只多一个小数字。 单条回复旁边不增加任何东西。
  • 宿主只折一次。 一个只认一种事件类型的 reducer,每轮六个数字;实测每事件 0.6 微秒,其余 事件只做一次引用比较就返回。
  • 不加载、不分页、不缓存。 数字来自一个投影值:浏览器半边不持有会话绑定、不打开对话、 不存任何东西。跳转可能在点击时把历史翻页到你要看的那一轮,一次、按需。
  • 只读。 不增加后台服务,不增加额外请求,也没有网络访问。
  • 无需配置。 没有设置项、不需要账号、不收集数据。
  • 空闲时不存在。 没有思考的对话完全不显示。
  • 有上限。 状态保留 5000 行(≈175 KB),发布给浏览器的视图保留 500 行,表格一次只渲染 一页 100 轮。
  • 自动跟随深浅色主题。
  • 自动跟随界面语言。 插件只写了 DSH 自带的两种语言(中文与英文),并按 <html lang> 切换;其它情况(包括语言包提供的第三语种)一律显示英文。

安装

从 GitHub 安装:

dsh plugin add github:Six6stRINgs/dsh-thinking-token-stat

或者通过 npm 安装已发布的包:

npm install dsh-thinking-token-stat

然后重启 dsh web 并刷新页面。模型开始思考后就会看到这个读数。

许可

MIT —— 见 LICENSE。

更新记录

每个发布版本一行:CHANGELOG_zh.md。

给开发者

仅在你打算改代码时需要。插件是两个各司其职的文件:

  • lib/index.js —— 宿主半边。注册唯一的会话投影(thinkingStats),就是一个对 assistant/message 结算做折叠的纯函数 apply(state, event)。它自带极小的 { parse } schema,因此整包没有依赖;并导出 __testProjection 供单元测试使用。
  • lib/client.js —— 浏览器半边。注册输入框统计行里的一个条目,读 useProjection("thinkingStats"),画出读数、总览与逐轮表格。它只依赖 slot 服务。

npm test 会在没有浏览器、也没有宿主的情况下跑两套测试:

  • node test/projection.mjs 驱动折叠本身:上报计数、文本推算、重试替换、fork 继承、 只按推理轮次计算的分母、两处上限,以及 schema 校验;把 DSH_TEST_LOG 指向一个 session.v3.jsonl.zstd 时,它还会重折一场真实录制的会话,并把合计与对同一批事件的独立统计 逐项核对。
  • node test/harness.mjs 用合成的投影值渲染浏览器半边:~ 标记、? 说明、统计范围与上限说明、 表格的列/筛选/翻页、模型字典、一级与二级面板的关闭方式,以及宿主不提供逐轮投影时的降级表现。

内容来自项目 README(GitHub)↗

评论

评论存放在 GitHub Discussions。用 GitHub 账号登录后可发表评论或点表情。