WorkBuddy 用量审计
第一步:直接跑脚本
取数逻辑已经固化在 scripts/audit_usage.py,零第三方依赖,Python 3 标准库即可运行:
python scripts/audit_usage.py --top 15
python scripts/audit_usage.py --csv usage.csv
脚本会输出:三个口径小计、按模型明细(含倍率与 credit/百万token)、Top N 会话、按日趋势。
不要自己重写遍历逻辑。脚本里的口径是校准过的,手写的容易算错或漏掉缓存维度。
数据源(三处 + 一处元信息)
数据根目录由产品的 dataFolderName 决定,WorkBuddy 固定为 ~/.workbuddy,Windows / macOS / Linux 通用。脚本用 Path.home() 定位,不要写死绝对路径。
| 数据 | 位置 | 关键字段 |
|---|---|---|
| 真实 token | ~/.workbuddy/traces/*/trace_*.json |
trace.modelInfo.totalInputTokens / totalOutputTokens / totalCachedTokens / callCount,trace.sessionId,trace.startedAt |
| credit 积分 | ~/.workbuddy/workbuddy.db → session_usage |
session_id, used, size, updated_at, credit_json(JSON: {requestId: credit}) |
| 模型计费倍率 | ~/.workbuddy/cache/acc-product-config-*.json → models[] |
id, credits(字符串形如 "x0.11") |
| 会话元信息 | 同库 sessions 表 |
id, title, model |
数据库必须用只读 URI 打开,避免锁 WAL:
sqlite3.connect("file:{}?mode=ro".format(db.as_posix()), uri=True)
三个必须讲清的口径
- 表面总量 = input + output。看着吓人(亿级)。
- 实际新处理 = (input − cached) + output。通常的计费口径,实测只有表面量的 3~4%。
- 上下文占用
session_usage.used:这是"当前上下文有多满 / 窗口上限",不是累计消耗,别报成用量。
报数时必须把这三个分开说。只报表面总量会让用户误以为真的烧掉了上亿 token。
坑
- credit 和 token 没有稳定换算率。实测同样跑 deepseek-v4.1-flash 的两个会话,单位 credit 对应的 token 相差约 10 倍(重工具调用会话 vs 纯聊天会话)。credit 更接近「按用户轮次 + 复杂度」计价。不要给用户一个"1 credit = N token"的确定数字,只给全局平均并注明单会话波动大。
- 缓存命中率极高(实测 96%+)。每轮都重发完整历史 + 超长 system prompt,命中部分几乎不产生新计算。
- 倍率每次现读,不要硬编码。模型定价会随版本调整。配置里
credits是相对倍率(如x0.11),不是每 token 单价。 - 配置文件带版本号(
acc-product-config-v3.json),用 globacc-product-config-*.json取最新,不要写死 v3。 - 部分模型不在配置表里(实测
space-bunny就没列)。此时倍率列留空,可用同价位模型反推,但要标明是推算值。 - credit 归属有误差:一个会话可能混用多种模型,脚本按会话主模型归档,拆不干净。报告里要说明。
- 正在进行的会话,trace 会实时增长,两次运行差几百万 token 是正常的。报数时说明"截至某时刻"。
- 部分 trace 的
modelInfo.models为["?"]或缺失,聚合时跳过。 totalTokens字段与input+output偶而不一致(有的 trace 该字段只记了最后一次调用),用 input+output 自己算更可靠。
数据缺失时怎么办
| 情况 | 处理 |
|---|---|
~/.workbuddy 不存在 |
说明本机可能没装 WorkBuddy,或目录名由 dataFolderName 决定而不叫 .workbuddy;不要编数据 |
traces 为空 |
说明还没有产生会话,或目录被清理过 |
| 数据库打不开 | 只读模式仍失败说明文件被占用,稍后重试;不要用普通模式强开,会锁 WAL |
credit_json 为空 |
该会话用了免费模型(倍率 x0.00)或尚未结算,如实说 0,不要猜测 |
| 找不到倍率配置 | 跳过倍率列,只报 token 和 credit,说明倍率不可用 |
边界
本技能只统计已消耗量。剩余额度、套餐总量在客户端账户页,本机没有对应数据源。用户问"还能用多久"时,说明这一点并引导去账户页看,不要用已消耗量去外推剩余额度。
输出示例
## 三个口径(别混用)
| 口径 | 数值 | 含义 |
|---|---|---|
| 表面总量 | 171,030,363 | input + output,含重复发送的缓存 |
| 实际新处理 | 7,000,015 | (input − 缓存命中) + output,通常的计费口径 |
| 缓存命中率 | 96.5% | 命中部分 164,030,348/169,971,320 |
| credit 合计 | 365.97 | 64 次计费请求 |
## 按模型
| 模型 | input | 缓存命中 | 新鲜 input | output | 缓存率 | credit | credit/百万token | 倍率 |
|---|---|---|---|---|---|---|---|---|
| deepseek-v4.1-flash | 64,946,443 | 62,752,512 | 2,193,931 | 593,178 | 96.6% | 215.78 | 3.29 | x0.11 |
| hy4-preview-f | 64,354,440 | 61,675,200 | 2,679,240 | 313,366 | 95.8% | 3.82 | 0.06 | x0.00 |
| space-bunny | 40,670,437 | 39,602,636 | 1,067,801 | 152,499 | 97.4% | 146.37 | 3.59 | 未列出 |
(以上为某台机器 2026-10 的真实快照,仅示意格式,数值不可复用。)