| |
如果 当前值 == 上一个值: 增加等待时间 否则: 回到30秒轮询
这个方法表现得很差。因为这个数字只有在**你有操作**的时候(比如你发送了消息,或使用了 tokens)才会改变。但在你**没有操作**时,它也会变化——比如系统设置了5个小时的滑动窗口期限,导致过期的tokens自动失效。如果你在其他设备上也在用这项服务,数字也会在你不知情的情况下变动。
所以单靠检查数字是否变化是不够的。你需要的是**预测**它什么时候会发生变化,并以多大的信心预测。
## 卡尔曼滤波器:五分钟速成
卡尔曼滤波器是一种用来融合两种不完美信息的工具。
想象你身处一个没有窗户的房间中特别想知道室外的气温。你有两个渠道:
1. **你的心理模型**:例如 “现在是三月的下午三点,气温应该在18℃左右”。这个估计是合理的,但并不完美——可能外面刚下过雨,或者有风。
2. **一个嘈杂的廉价温度计**:你可以走到阳台测量,但这个温度计有±3℃的波动误差。
两种渠道都不完美,但卡尔曼滤波器告诉你:**把这两种信息结合起来,并在不同时刻对更可靠的信息赋予更大的权重。**
如果你刚刚10秒前查看了温度计,你的心理模型就很可靠——完全可以信任它,不用再去测量。如果你已经一个小时没测量了,你的模型就会失去可信度——这时候你得回阳台看看。
关键是**方差**:一个用来衡量“我对当前估计值有多信任”的数值。在刚看过温度计后的瞬间,方差为零;随着时间推移,方差逐渐增大。当超过某个门槛时,滤波器会告诉你:“不可信了,去获取真实数据吧。”
在我的案例里:
- **心理模型** = tokens的本地使用情况。我知道Claude Code的使用记录,所以大致可以推算出消耗的token数是多少。
- **测量数据** = Anthropic的API真实返回值。它是当前最准确的信息,但获取每一次数据都有政治代价和电力消耗。
- **方差** = 随时间增长的不确定性。如果我在浏览器或手机上使用了服务,本地模型对此一无所知——也因此预测的准确性会下降。
一个复杂的多维卡尔曼滤波器(带协方差矩阵)用来解决这个问题有点类似杀鸡用牛刀。我的方法更简单:一个单一状态(token使用量)、单一传感器(API返回值)、线性模型(成本/预算比例)。20行代码就搞定了,这是可以完美解决问题的最小实现。
翻译到我的具体需求中:
- **预测**: `使用量估计 = 上次真实值 + (本地新增消耗 / 总预算) × 100`
- **修正**: 每次服务器返回一个新的真实值,滤波器会将方差重置为零。
- **不确定性**: 方差开始按照时间线性增长。`σ = √(Q × 自上次校正起的秒数)`。
## 关键点:滤波器自动决定何时请求
这里正是过度设计显得合理的地方。卡尔曼滤波器不仅仅能估计值,它还能**决定何时需要获取真实数据**。五条规则,每个“tick”执行一次:
| 规则 | 触发条件 | 原因 |
|-------|-----------|---------|
| 窗口已重置 | `now ≥ resetsAt` | tokens过期了,之前的值失效。 |
| 高不确定性 | `σ > 5%` | 对预测值信任度低,必须确认。 |
| 范围边界触发 | 置信区间触碰到80%、95%或100% | 临近重要阈值,用户必须知道。 |
| 邻近性触发 | `使用率`接近边界8% | 有可能跨越范围,但本地估计未能察觉(比如在其他设备使用服务时)。 |
| 安全超时 | 15分钟无真实数据返回 | 预防性措施,监控软件的偏执有时是优点。 |
如果没有规则触发,卡尔曼滤波器会说:“没问题,我全都掌握”——于是应用**不会发起HTTP请求**。显示给用户的值是本地估计值。
重点来了:本地估计不需要**网络消耗、功耗或风险**。它完全基于内存中的数学运算。
## 数字对比:前后变化
小范围内token消耗稳定的一天(中度使用,较少峰值):
| 场景 | 请求/小时 | 请求/天(8小时) |
|---------|:-:|:-:|
| 固定30秒轮询 | 120 | 960 |
| 使用贝叶斯估计 | 15-30 | 120-240 |
| 估计 + 休眠 | 4-10 | 30-80 |
相比之前的960次请求,网络请求减少了**75-97%**。对于“只是偶尔请求数据”的任务来说,不算太糟吧?
...(内容会继续翻译完整)