# meow-cachebilling

[English](./README.en.md)

难道只有我在关心怎么省钱？你们都那么有钱的吗……

## 为什么会有这个插件

dsh缓存命中率高，ds服务器缓存处理也得当，价格也便宜，导致可能很多人都忽略了——

单价再便宜，当上下文越来越长的时候，它还是会越来越贵。

到最后一算，你实际上付的钱，可能90%以上都是为了买缓存。

 

也就是说如果有更好的换窗口策略，及时换窗口，ds的费用能大幅度下降。

 

这是真的，我试了换窗口勤快的策略，试了两天，然后发现，真的便宜了。


我让GPT给我算的，算法是这样的：

缓存命中实际上都是聊过的上下文，每轮带着，所以显得多。

但未命中的输入和ai输出，才是硬梆梆不能少的实际使用，是不是？

所以或许应该用“实际使用”去衡量两天不同的工作量，并比较两天的性价比。

GPT算出来我勤换窗口时，便宜了50.1%。

<img width="404" height="260" alt="bdf3b8aafe29f33c510cedfee116ed5d" src="https://github.com/user-attachments/assets/fbe0fc75-5e91-44f3-b871-4ebb8d736767" />

所以，正确的deepseek使用姿势是：

不断开新窗口，旧窗口就再也不动了。

很长的旧窗口，每动用一次，都要为缓存付很多钱。

如果是时间久了、服务器那边缓存都删除了的旧窗口，那想必更是天价，全都按miss算啊。

所以旧窗口碰都不碰是最优解。

（所以还需要配合记忆插件来把旧窗口的有用信息带走）

 

但是，具体什么时候换窗口，你就需要衡量了。

 

换窗口的成本是：

AI需要重读代码的miss输入（可以通过fork减少这项成本）。

你需要重新介绍任务和规则的人力成本（可以通过记忆插件减少这项成本）。


换窗口的收益是：

缓存费用清零、从零开始重新累积。

 

有成本，有收益，所以你需要判断更好的换窗口时机。

 

换的太早：缓存本就不贵、收益少；重读代码miss费用虚耗、且重复说车轱辘话很累。

换的太晚：你的账单早已悄悄被冗长的上下文偷吃干净了。

 

所以我就需要这么一个插件，来告诉我，当前轮，纯粹上下文缓存的部分，到底花了我多少钱。

这样我才能心里有个底，才能判断什么时候该换窗口。

我写它之前还在dsh-plugin标签里全网找了，那么多计费插件，并没有人写这一项……真奇怪。难道只有我有这个需求吗？

可是这真的省钱啊……

## 功能

- **第三方中转也认**：不限定 DeepSeek 官方路由——官方路由按刊例价精确计价；第三方中转只要报用量就照样记账，模型名命中价目表按刊例价计（峰谷或一口价），没命中就按 flash 价估算并在账单里标明，宁近似，不空转。凭空 provider 的路由不会显示。
- **价目表可视化编辑**：设置页新增独立「喵缓存账单」标签页（与「通用」「模型」平级），添加 / 修改 / 恢复预填，改完即时生效，无需重启。包根 `rates.yml` 是插件自带的预填层（provider/model 按 API 官方写法，峰谷（days × ranges 叉乘）或一口价（const）三选一，时区按计费方账单时区（IANA 名）），改它才需要重启 `dsh web`；条目写坏自动跳过并警告，绝不弄崩 DSH。
- **账单住在上下文菜单里**：点开输入框右侧的上下文圆环，弹层底部就是账单，和"上下文用了多少"同屏对看。
- **三级账单一表收**：当前每次API请求（单次调用）、当前轮（轮内多次 API 调用累加）、会话累计合并成一张无边框小表——首列「一步 / 一轮 / 会话」行标签，总价独立一列（货币单位只在表头「消耗(¥)」标一次），右边三列是缓存命中 / 缓存未命中 / 输出明细，一览即比，省地方。
- **会话累计**：整会话逐笔按各自事件时刻的峰谷费率累加，跨轮不比价。另有两个按步计数，均来自 API 返回的用量字段——「缓存失效次数」：该步 API 返回了缓存写入 token（写入即前缀变更、旧缓存作废；官方 API 不报此字段，仅部分中转可计）；「完全失效次数」：该步有输入但缓存命中为 0（由返回的命中数推导，会话首轮无缓存可命中也计入）。
- **峰谷计价自动判定**：工作日高峰时段（北京时间 09:00–12:00 / 14:00–18:00）按峰价，其余时段及周六日全天按谷半价——与系统时区无关，纯事件时刻换算。峰谷条目可勾「扣中国法定节假日」（预填条目已默认勾上）：法定节假日全天按谷价（官方定价脚注 (2) 口径），假日数据自动取自 [holiday-cn](https://github.com/NateScarlet/holiday-cn)（跟进国务院公告的开源仓，免费无 key），取不到时退回纯星期判定，绝不阻塞计费主路径。峰谷标注在模型信息行（「当前模型统计」标题下的小字）：DeepSeek 官方路由写「梁文峰/梁文谷」，其他路由写「峰价/谷价」；一口价条目不标注。
- **模型分价**：deepseek-flash（DeepSeek-V4.1-Flash）与 deepseek-v4-pro（DeepSeek-V4-Pro-0813）单价不同，按每步实际使用的模型计；官方旧模型名条目随行保留，老调用/老路由照常命中。
- **金额精度自适应**：小于 0.01 的四舍五入保留一位有效数字——0.005、0.0003 这类零头一眼可见；大于等于 0.01 的四舍五入到分。
- **平均花费曲线**：插件为每个会话留存每一步的真实花费（只存命中价目表的步，模型标签只在换模型/换峰谷时打一条），按「路由/模型/峰谷」聚合出当前模型的平均累计花费曲线（只纳入最近 30 天的会话，峰谷分开各算一条），并在同一张图里画出本会话的实际累计花费——曲线前慢后快近似二次函数，对照斜率，赶在花销起飞前换窗口或压缩上下文。历史分桶带旧数据归并：官方统一命名 `deepseek-flash` 与官方双路由（api-key / 账号登录）的旧落盘记录在读取侧自动并进规范桶，老数据免迁移继续参与平均。
- **右栏数据两节**：曲线图缩在左半边，右半边两节数据——「消耗比较」：读代码（前两轮缓存未命中与输出之和：AI 开窗头两轮集中读代码，这个数衡量新开窗口后重读代码的代价）、缓存（当前每次API请求的命中花费）、缓存失效（当前上下文全部 token 若全按 MISS 算的价钱）；「缓存」：完全失效次数、缓存时间估算与现在失效可能（占位待实现）。桌面端悬停标签各有解释，手机等触屏设备同样显示，只是没有悬停解释。

## 效果

点开输入框右侧的上下文圆环，弹层底部就是账单：

<img width="131" height="227" alt="image" src="https://github.com/user-attachments/assets/8329a70e-4e73-4892-aaf4-69c85661c186" />


数字为示意，实际按你的用量与时刻费率计算。

## 安装

```sh
dsh plugin --profile web add github:Phant0Meow/dsh-meow-cachebilling
```

一条命令装完即生效：安装时自动编译（包内含 `prepare` 脚本），自动挂载，重启 `dsh web` 后启用，无需任何配置。

> pnpm ≥10 默认会阻止安装期的构建脚本：首次 `add` 可能失败并提示 `allowBuilds`，按提示把输出的键加进 profile 的 `pnpm-workspace.yaml` 后重跑即可。

## 卸载

```sh
dsh plugin --profile web remove meow-cachebilling
```

彻底移除，重启 `dsh web` 后不再加载。

## 计价口径

| 项目 | 口径 |
|---|---|
| 缓存 | 本步 cacheRead tokens × 命中单价 |
| 未命中 | （未命中输入 + 缓存写入）× 未命中单价 |
| 输出 | 输出 tokens × 输出单价 |
| 时段 | 工作日 09:00–12:00 / 14:00–18:00 为峰，其余（含周六日与中国法定节假日全天）为谷 |

内置价目表（元 / 百万 token，2026-10-07 官方刊例）：

| 模型 | 峰（命中/未命中/输出） | 谷 |
|---|---|---|
| deepseek-flash | 0.04 / 2 / 8 | 0.02 / 1 / 4 |
| deepseek-v4-pro | 0.3 / 9 / 27 | 0.15 / 4.5 / 13.5 |

第三方中转的费率与官方不一致：模型名命中价目表按刊例价估算，未命中按 flash 价估算——都是本地估算，实际扣费以你的账单为准。完整可编辑价目表在包根 `rates.yml`，以上是内置默认值。

## 说明

- 未命中缓存的轮次会如实显示金额——全新会话第一轮没有可复用的前缀，这是正常现象。
- 价目表分两层：包根 `rates.yml` 是预填层（跟随版本更新），设置页「喵缓存账单」标签页是你的修改层（即时生效）；`rates.yml` 文件写坏会退回内置默认表并在控制台警告。
- 账目只认 `usage` 的 input / cacheRead / cacheWrite / output 四类 token。
- 每步花费历史存于 DSH 官方存储层（`meow_cachebilling.json`）；曲线随会话越攒越准，旧会话再次活动时会按当前价目表回填。
- 硬性约束：`lib/client.js` 的 `factory` 必须以 `return module.exports` 结尾，否则模块导出为 `undefined`，DSH 启动即 fail-loud。

## 致谢
感谢 [better-er](https://github.com/better-er) 的贡献！

三级账单（当前每次API请求 / 当前轮 / 会话累计）、api返回的缓存失效次数统计，来自 [better-er](https://github.com/better-er) 的大幅重写（[#2](https://github.com/Phant0Meow/dsh-meow-cachebilling/pull/2)）；
他也打开了本插件对非ds官方api的显示，我之后的确想加对其他api的支持，所以也merge了这处改动。
账单底部把原本的「峰价/谷价」改为「梁文峰/梁文谷」的彩蛋也是他的手笔，我们觉得有趣就也保留了。
感谢他给我们提的PR，感谢他的贡献！


欢迎大家提各种PR！插件还会更新，你fork了之后merge过来，之后的更新你也能接上~而且，大家一起写，才有趣嘛。

## License

MIT
