Bundle
dsh-llm-cost
Per-turn, per-step LLM cost metering for DeepSeek Harness: a costUsage session projection, a cost line under each message, and an LLM+web price auto-maintenance tool.
- Source
- chenyinrusi
- stars
- 2 stars
- License
- MIT
- Updated
- Updated 4 hours ago
Readme
# 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 文件并即时生效 |
## 安装
```bash
# git(推荐:lib/ 已提交,免本地构建)
dsh plugin --profile web add github:chenyinrusi/dsh-llm-cost#v0.6.1
# 本地 tarball(内网 / 离线)
dsh plugin --profile web add ./dsh-llm-cost-0.6.1.tgz
```
> npm 渠道暂未发布。如需 `dsh plugin --profile web add dsh-llm-cost`,先在仓库跑 `npm login && npm publish`。
> **要求 DSH ≥ 0.1.1-rc.2**(v0.6.0 起使用 `ProjectionDefinition` 的 `stateSchema` + `wire` 契约,旧 rc 版本无此 API)。
本地验证:`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 逐步编排:
1. `ctx.web.search` 对目标模型搜索「current API price per million tokens」;
2. 用**记忆 + 最便宜优先的 fallback 链**抽取:先试 `refreshProvider`/`refreshModel`(若配置),再试**上一次成功的模型**(持久化记住),然后自动枚举 `ctx.llm.listProviders()` + `listModels()` 里所有可用模型,按单价排序(免费/最便宜在前,未标价最后),**一个失败就换下一个**;
3. 宽松校验(坏模型直接丢弃,绝不污染价格表)→ 合并进 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(仅工作日);**自 2026-08-23 起,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)
```
## 开发
```bash
npm install
npm test # node --test(纯逻辑层,无需 DSH 工具链)
npm run gen # 重新生成价格快照
npm run build # tsdown 打包 host + client + 声明文件
```
## License
MIT © 2026 Chen (Jarry) Pan
Install
dsh plugin --profile web add github:chenyinrusi/dsh-llm-cost
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-llm-cost from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.