chenyinrusi
dsh-llm-cost
Per-turn, per-step LLM cost metering for DeepSeek Harness - costUsage projection, per-message cost line, and an LLM+web price auto-maintenance tool.
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-llm-cost
让 DeepSeek Harness 显示每个 turn、每个 step 的 LLM 成本(美元),并在价格过期时用 LLM + 联网自动更新价格表。
DSH 已经精确记录了每个 step 的真实 token 用量(assistant/message 的 usage:输入/输出/缓存读/缓存写),但没有任何美元成本概念。dsh-llm-cost 补上缺失的那一环:把「用量 × 单价」变成 DSH 的持久事实(costUsage session projection),并在每个对话框下方的 stats 行里渲染出该 turn 的成本。
工作原理
- host 端(node):一个 session projection 单元(照
token-meter的骨架),在session/event上折叠:request/context(解析后的 provider/model 路由,post-fallback)决定每个 step 用的模型;assistant/message(或assistant/chunk的 usage chunk)报告该 step 的用量;- 单价表 →
costUsd,同一 turn/step 的重复采样做替换而非重复累计。
- client 端(浏览器):注册到
conversation.chat.turnTail扩展链,读useProjection('costUsage'),在每个完成的 assistant 消息下方渲染$0.0042 · 1.2K tok;并注册conversation.session.header.utilities在会话头右上角显示整个 session 的累计成本。 - 未定价模型:显示
unknown,绝不静默显示$0.00(避免「未知」被误读成「免费」)。
功能
| 层 | 内容 |
|---|---|
| 成本投影 | costUsage:totalCostUsd、pricedSteps/unpricedSteps、token 分桶、byModel 聚合、steps[] 每步明细 |
| 每 turn 渲染 | 对话框下方 stats 行:$0.0042 · 1.2K tok / unknown |
| 累计成本 | 会话头右上角:整个 session 的累计 $(含 + N unknown 提示) |
| 自动维护 | llm_cost_refresh 工具:联网搜索当前价格 → LLM 抽取 JSON → 写入 override 文件并即时生效 |
安装
# git(推荐:lib/ 已提交,免本地构建)
dsh plugin --profile web add github:chenyinrusi/dsh-llm-cost#v0.3.1
# 本地 tarball(内网 / 离线)
dsh plugin --profile web add ./dsh-llm-cost-0.3.1.tgz
npm 渠道暂未发布。如需
dsh plugin --profile web add dsh-llm-cost,先在仓库跑npm login && npm publish。
本地验证:pnpm dsh web --patch ./cordis.patch.yml(或 --dump-config 查看层)。
配置
cordis.patch.yml 里该行的 config 可设(全部可选):
| 键 | 默认 | 说明 |
|---|---|---|
pricing | 内置快照 | 内联的定价覆盖,合并到快照之上 |
pricingFile | ~/.dsh/llm-cost/pricing.override.json | refresh 工具写出的覆盖文件 |
refreshProvider | 无 | 价格抽取调用的 provider 路由(可选:配了则优先用) |
refreshModel | 无 | 价格抽取调用的模型 id(可选:配了则优先用) |
配置由 zod Config schema 校验(cordis 在 apply 前执行):省略 config 键 = 全默认;config: {} 合法;不要写空 config: 键——YAML 会解析成 null,被 schema 响亮拒绝(带 entry 名)。未知键被静默丢弃。
自动维护价格(llm_cost_refresh)
这个工具自己调用 LLM + 联网完成整条链路,不需要 agent 逐步编排:
ctx.web.search对目标模型搜索「current API price per million tokens」;- 用记忆 + 最便宜优先的 fallback 链抽取:先试
refreshProvider/refreshModel(若配置),再试上一次成功的模型(持久化记住),然后自动枚举ctx.llm.listProviders()+listModels()里所有可用模型,按单价排序(免费/最便宜在前,未标价最后),一个失败就换下一个; - 宽松校验(坏模型直接丢弃,绝不污染价格表)→ 合并进 registry → 写
pricingFile。
前置:DSH 里要装一个 web 搜索 provider(dsh-web-search-*)+ 至少一个可用的 LLM 路由。refreshProvider/refreshModel 不再是必须——不配也能自动挑最便宜的可用模型。抽取结果建议先人工抽查——它写的是 override 文件,不会覆盖内置快照。
定价是会过期的数据(intro 价、模型改名、峰谷调整)。把
src/config/llm_models.toml [pricing_v2]作为单一事实来源,跑npm run gen(node scripts/gen-pricing.mjs)重新生成pricing.json+src/pricing-data.ts,锁步发布。
数据
pricing.json 是内置 JSON 快照,由 scripts/gen-pricing.mjs 从 llm_models.toml [pricing_v2] 生成(默认读相邻 customized_agentic_system/src/config/llm_models.toml)。计费字段:inputPerM(cache miss)/ outputPerM / cacheReadPerM(cache hit)/ cacheWritePerM(cacheWrite1hPerM 保留,batch/storage 维度 v1 不计入显示值)。
峰谷定价:字段存的是峰值价;offPeakFactor(如 0.5)声明闲时折扣。峰时窗口 = 01:00–04:00 & 06:00–10:00 UTC,其余时段成本 × offPeakFactor。成本计算按事件时间戳判定,未声明 offPeakFactor 的模型恒按峰值价。
匹配阶梯(对齐 models.py:get_pricing)
0. provider === "ollama" → 免费
1. 模型 id 精确匹配
2. 最长 key 子串匹配(防 "gpt-5.4" 吞掉 "gpt-5.4-mini")
3. 未知 → unknown(显示 "unknown",不显示 $0.00)
开发
npm install
npm test # node --test(纯逻辑层,无需 DSH 工具链)
npm run gen # 重新生成价格快照
npm run build # tsdown 打包 host + client + 声明文件
License
MIT © 2026 Chen (Jarry) Pan