97484cb7f8
v4(stable = balance - BUFFER)把「剩余余额」当「从 0 累计的上限」, U>0 时低估初始池:15:09:51 实测 Bal=596,869(剩 59.7 万)却被 usage 1,696,135 >= 296,869 全拦。守恒反推(U+B=2,293,004)证明 v2 公式数学正确——B 滞后收敛后满足 B = B0 - U,今日消耗 1.696M < B0 2.293M 无扣费(此前「超余额 13.8 万扣费」基于滞后快照的推断 不成立)。v5 = 恢复 v2(stable = usage + balance - BUFFER), 残留风险仅同步时点 B 滞后(13:36 高估 ~50 万),由 BUFFER + 低余额 加密同步覆盖。文档同步:volc-quota-notes §7.3/§7.5、merge-auto-consume §4.5。
227 lines
12 KiB
Markdown
227 lines
12 KiB
Markdown
# 火山免费额度机制速查(VolcEngine Quota Notes)
|
||
|
||
> 日期:2026-08-12
|
||
> 用途:后续限额/防扣费设计、排障、消耗任务的事实基础,避免重复推导
|
||
> 来源:
|
||
> - `merge-auto-consume.md` §1(2026-08-11 用户确认的业务细则)
|
||
> - 2026-08-12 对话澄清(扣费口径、余额 API 滞后、限额方案演进)
|
||
> - 2026-08-12 生产日志观察(deepseek-v4-flash-ga-260731)
|
||
>
|
||
> 代码现状:v5 = 恢复 v2 骨架(`stable_limit = usage + balance − BUFFER`),2026-08-12 修正;
|
||
> v4(balance−BUFFER 冻结快照)当天实施后即发现误拦已回退,见 §7.3/§7.5。
|
||
> 工作区在 HEAD `c6c1224` 之上含 v5 修正。
|
||
|
||
---
|
||
|
||
## 1. 业务模型(细则,用户确认)
|
||
|
||
### 1.1 日返还循环
|
||
|
||
```
|
||
每天任意时刻 真实用户 + 消耗任务 的消耗 = 当日采集量(火山实时统计,每模型单独计算)
|
||
每天 23:00 CST 消耗任务补齐缺口(可选)
|
||
次日 00:00 起 火山按昨日采集量发放资源包(不定时,可能延迟到上午)
|
||
```
|
||
|
||
### 1.2 硬规则
|
||
|
||
| 规则 | 值 | 影响 |
|
||
|---|---|---|
|
||
| 采集上限 | 2M token/模型/天 | 消耗超过 2M 的部分**不返还**(白烧);所有模型统一 |
|
||
| 发放额度 | = 昨日采集量(≤2M) | 消耗 X → 次日返还 X,用多少补多少,延迟一天到账 |
|
||
| 发放时间 | 不定时 | 次日 0:00 至发放时点存在余额空窗 |
|
||
| 资源包有效期 | 30 天 | 过期额度实打实消失,失去"启动资金" |
|
||
| 消耗顺序 | FIFO(先消耗获得时间早的包) | 队列头部 = 最早获得 = 最早过期 |
|
||
| 余额耗尽 | 请求不失败,按真实价格扣费 | 全部防护的终极目标:避免扣费 |
|
||
| 首次开通 | 每模型赠送 2M | 启动资金的种子(无对应前日采集的免费午餐) |
|
||
|
||
### 1.3 账目守恒
|
||
|
||
```
|
||
余额_{N+1} = 余额_N − 消耗_N + 返还_{N+1}
|
||
= 余额_N − 消耗_N + 采集_N
|
||
= 余额_N (消耗即采集,≤2M 内全额返还)
|
||
```
|
||
|
||
推论:
|
||
- **使用不损失额度**(用多少补多少,仅延迟一天)
|
||
- **过期才损失额度**(额度蒸发 = 启动资金永久减少)
|
||
- 消耗任务的价值 = 防止"启动资金"被 30 天过期侵蚀
|
||
- 真实用量 ≥ 66.7k/天(= 2M/30 天)时,赠送包被自然消耗;低于此值必须靠消耗任务在最后 9 天窗口洗掉
|
||
|
||
---
|
||
|
||
## 2. 扣费判定(2026-08-12 用户确认口径,最重要)
|
||
|
||
> 用户原话:**是否扣费只取决于当下有多少免费额度。超出免费额度的请求,都会被扣费。采集量只决定明日发放,与今日是否扣费无关。**
|
||
|
||
```
|
||
扣费判定:消耗 ≤ 当下余额(免费额度)→ 免费,余额扣减
|
||
消耗 > 当下余额 → 超出部分按真实价格扣费(无返还、不退)
|
||
今日采集量(≤2M)→ 只决定明日返还的包大小,与今日是否扣费无关
|
||
```
|
||
|
||
推论(2026-08-12 案例):
|
||
- 当日余额 1,558,307,今日已采 1,696,135 → 超出 **137,828 tokens 已扣费**,不可挽回
|
||
- 明日返还 = 今日采集量 1,696,135 的包(免费额度回正),但今天扣的钱不退
|
||
- 因此「先采后返」**不构成透支许可**:消耗超余额的部分当场计费
|
||
|
||
---
|
||
|
||
## 3. 关键概念区分(反复踩坑处)
|
||
|
||
| 概念 | 含义 | 量级特征 | 与扣费的关系 |
|
||
|---|---|---|---|
|
||
| 采集量(今日) | 今日实时消耗统计(火山网页"今日采集量") | 单日流量,0~2M | 只决定明日返还 |
|
||
| 余额(免费额度) | 资源包 AvailableAmount 存量之和 | 累计存量,守恒 ≈2M(种子) | **扣费唯一依据** |
|
||
| 采集配额 2M | 今日最大采集量 | 每模型固定 | 超了白烧(不返还),未必当场扣费 |
|
||
| 返还(T+1) | 昨日采集量 → 新资源包 | 单日流量延迟一天 | 补回余额,不抵今日扣费 |
|
||
|
||
**核心:余额是累计存量(守恒),采集量是单日流量。限额设计必须用存量(余额),
|
||
绝不能用单日流量(昨日采集量)当上限——那会把可用性锁死在水位以下(见 §7.2 v3)。**
|
||
|
||
---
|
||
|
||
## 4. 余额 API 的滞后问题(2026-08-12)
|
||
|
||
- **非实时,延迟未知**(用户明确)。实测:2026-08-12 13:36:01 同步快照 Bal=1,558,307,
|
||
此后 usage 从 1,241,821 涨到 1,696,135(13:36→13:38)期间 Bal 纹丝不动。
|
||
- 观察结论:AvailableAmount 不随今日消耗实时递减(至少滞后 20 万级,上限未知)。
|
||
- **后果**:一切「余额随消耗实时递减」的公式(v2 的 `usage + balance` 池恒定假设)在
|
||
滞后下失效——usage 涨而 balance 不动 → 池膨胀 → 限额虚高 → 放行到扣费区。
|
||
- 对策方向:以**最近同步快照**的余额为当日免费池上限(本地 usage 实时累计撞线),
|
||
快照频率由同步间隔(30min 常规 + 低余额 5/10min + 突发阈值触发)保障;
|
||
滞后窗口内的消耗用 BUFFER 覆盖(见 §7.3)。
|
||
|
||
---
|
||
|
||
## 5. 症状对照:Today > Rem(2026-08-12 案例)
|
||
|
||
日志示例(13:36-13:38,deepseek-v4-flash-ga-260731):
|
||
|
||
```
|
||
DEBUG: Checking deepseek-v4-flash-ga-260731 (Bal: 1,558,307, Rem: 1,258,307) (余额/剩余)
|
||
DEBUG: deepseek-v4-flash-ga-260731 Pool=2,800,128 | Usage=1,241,821 | StaticLimit=2,000,000 | StableLimit=2,500,128 | EffectiveLimit=2,000,000
|
||
Set Redis limit:dynamic:volcengine:remaining:deepseek-v4-flash-ga-260731 = 1,258,307
|
||
📊 [Usage] deepseek-v4-flash-ga-260731:ba0383d3: +38083 (Today: 1,279,904 | Rem: 1,558,307 | Limit: 2,000,000)
|
||
```
|
||
|
||
字段口径:
|
||
|
||
| 字段 | 含义 | 计算 |
|
||
|---|---|---|
|
||
| Bal | 火山 API 余额(ListResourcePackages AvailableAmount 之和) | 同步快照 |
|
||
| Rem(Checking 行) | 入 Redis 的剩余 | Bal − BUFFER |
|
||
| Rem(Usage 行) | 展示用余额 | Redis remaining + BUFFER = Bal(展示与 API 一致) |
|
||
| Today | 本地今日采集量 | Redis `daily_usage` 逐请求累加 |
|
||
| Limit | 生效限额 | min(2M, stable_limit) |
|
||
| StableLimit(v2) | 动态限额 | usage + balance − BUFFER(随 usage 膨胀,见 §7.1) |
|
||
|
||
**Today > Rem 的原因**:Today 是单日流量,Rem 是存量余额快照,两套口径本就不该比较。
|
||
火山网页「今日采集量 1,696,135/2,000,000」对应 Today 与 2M 配额,与余额无关。
|
||
|
||
**扣费结论(2026-08-12 15:09 实测修正)**:14:59:51 同步 U=1,696,135 + B=596,869,
|
||
守恒反推今日初始免费池 B0 = 2,293,004 → 今日消耗 1,696,135 < B0 → **当日无扣费**。
|
||
此前「超余额 13.8 万已扣费」的推断基于 13:36 滞后快照(B=1,558,307 高估真实剩余
|
||
约 50 万),不成立。判定扣费要用「守恒初始池」(U+B 反推)而非任意时点快照。
|
||
|
||
---
|
||
|
||
## 6. Redis key 与日志口径(速查)
|
||
|
||
### 6.1 Redis key
|
||
|
||
| key | 读写方 | 说明 |
|
||
|---|---|---|
|
||
| `daily_usage:{北京日期}:{model}:{hash}` | LiteLLM 成功回调 INCR + 消耗任务 INCR | 当日采集量,TTL 48h,北京 00:00 滚动 |
|
||
| `limit:dynamic:volcengine:remaining:{model}` | 守护线程写 | 余额 − BUFFER(同步频率驱动、展示) |
|
||
| `limit:dynamic:volcengine:stable_limit:{model}` | 守护线程写 | 稳定限额(v5:usage+balance−BUFFER) |
|
||
| `consume:last_run:{日期}` | 消耗任务 | 23:00 当日去重,TTL 48h |
|
||
|
||
### 6.2 关键日志
|
||
|
||
- `🚫 [PRE-BLOCK] {model} daily limit reached ({usage}+{reserve}/{limit})`:请求前闸门 429
|
||
- `📊 [Usage] {model}:{hash}: +{tokens} (Today: X | Rem: Bal | Limit: Y)`:成功记账
|
||
|
||
---
|
||
|
||
## 7. 限额方案演进
|
||
|
||
### 7.1 v2(HEAD c6c1224 原式,v5 已恢复):`stable_limit = usage + balance − BUFFER`
|
||
|
||
- 意图:`usage + balance` = 当日初始免费池(守恒 B0),消耗中恒定 → 限额恒定
|
||
- **数学正确性(2026-08-12 15:09 实测确认)**:B 滞后收敛后确实满足 B = B0 − U
|
||
(14:59:51:U=1,696,135 + B=596,869 = B0=2,293,004,与理论剩余 597,004 几乎一致)。
|
||
同步时 stable = B0 − BUFFER,usage 累计撞线 = 用到剩 BUFFER 停止 —— 语义正确
|
||
- **残留风险(非公式错误,是快照时点问题)**:同步时 B 若滞后(13:36 高估真实剩余
|
||
约 50 万)→ stable 虚高 → 多放行滞后窗口内消耗。由 BUFFER + 低余额加密同步
|
||
(600s/300s)+ burst 触发覆盖;收敛后池回到守恒值
|
||
- 案例:13:36 快照 B=1,558,307 为滞后值(真实剩余 ≈1,051,183),并非「余额不足」;
|
||
今日无扣费(见 §5)
|
||
|
||
### 7.2 v3(尝试后否决,已回滚):昨日锚 `effective = min(2M, 昨日采集量 × 系数)`
|
||
|
||
- 思路:把「返还 = 昨日采集量」当作「今日可采上限」
|
||
- **否决理由(用户反例)**:余额 2M、昨日用量 10K → 今日最多 10K?荒谬。
|
||
错误在于把**单日流量(昨日采集量)当存量(余额)** 用;昨日少用不损余额(守恒),
|
||
今日可用 = min(2M, 余额) ≈ 2M,与昨日无关
|
||
- 附:系数 <1.0 还会引发「今日少采 → 明日返还更少」的日复一日递减陷阱(0.9 系数 5 日降至 66%)
|
||
|
||
### 7.3 v4(2026-08-12 实施后当天发现错误,已回退):冻结快照
|
||
|
||
```
|
||
stable_limit = max(0, balance − BUFFER) # ❌ 错误:把「剩余余额」当「从 0 累计的上限」
|
||
```
|
||
|
||
- 设计初衷:余额 API 滞后 → 冻结快照防池膨胀
|
||
- **错误实证(15:09:51 生产日志)**:Bal=596,869(真实剩余 59.7 万),
|
||
stable = 296,869,usage=1,696,135 ≥ 296,869 → `[PRE-BLOCK] … (1,696,135+16/296,869)` 误拦。
|
||
账上有真实免费额度却全拦 —— 因为 stable 应是「今日累计上限」(= B0 − BUFFER),
|
||
而 balance 是「剩余」(= B0 − U);U>0 时两者相差 U,直接替换导致低估、误拦
|
||
- 仅在同步时点 U=0(日初/刚返还)巧合正确(doubao 场景 stable=2.2M 无碍)
|
||
- 教训:**「剩余额度」不能当「累计限额」用**;两者通过 `usage + balance` 桥接(v5)
|
||
|
||
### 7.4 待观察项(2026-08-12)
|
||
|
||
- **BUFFER(现 30 万)**:防「同步时点 B 滞后窗口内的消耗」。13:36 实测高估约 50 万
|
||
> 30 万 BUFFER → 若滞后窗口内流量大,v2 会多放行到虚高 stable;可调大(如 50 万,env)
|
||
- **部署**:v5 已改(工作区),需重启 litellm 容器加载;重启在生产主机由用户执行
|
||
|
||
### 7.5 v5(2026-08-12 修正,当前):恢复 v2 骨架
|
||
|
||
```
|
||
stable_limit = max(0, usage + balance − BUFFER)
|
||
```
|
||
|
||
- 与 v2(§7.1)公式相同,区别在**论证与认识**:v2 数学正确(B 收敛后 = B0 − U),
|
||
不需要冻结快照;v4 的「剩余当上限」误拦由「usage + balance 桥接」天然避免
|
||
- 实测验证(14:59:51 同步 + 15:09:51 生产日志):U=1,696,135、B=596,869 →
|
||
stable=1,993,004 → 今日剩余可用 296,869(账上 59.7 万用到剩 30 万 BUFFER)✓
|
||
- 防扣费语义不变:usage 撞 stable = 剩余恰为 BUFFER 时停,扣费结构性杜绝;
|
||
balance < BUFFER(U=0)→ stable=0 → 全拦
|
||
- 保留:`get_effective_limit` 兜底链(stable → FALLBACK_LIMIT 90 万)、pre-block reserve、
|
||
软踢/恢复、低余额加密同步(600s/300s)
|
||
|
||
---
|
||
|
||
## 8. 排障速查(今日结论汇总)
|
||
|
||
1. 看到 Today > Rem 不是异常,先分清口径(§5);判扣费用「守恒初始池」(U+B 反推),
|
||
不要用任意时点快照(13:36 滞后快照曾误判「超余额扣费」,实际无扣费)
|
||
2. 余额显示不动 ≠ 余额充足,是 API 滞后;同步快照 + BUFFER 兜滞后窗口
|
||
3. 判断「还能免费采多少」:`(usage + balance − BUFFER) − 今日已采`(v5 已落地)
|
||
4. 消耗任务 23:00 直连 Ark 绕过 LiteLLM 闸门(防自杀),其自身 clamp:`plan ≤ 2M − usage`、
|
||
`plan ≤ 余额快照 − 已烧 − BUFFER`,停止条件三闭环
|
||
5. 余额滞后收敛后守恒成立(B = B0 − U);30 天过期蒸发是余额下跌的另一来源,
|
||
与消耗扣减区分(如 08-12 余额 1,558,307 → 596,869,其中约 50 万为滞后修正 + 过期)
|
||
|
||
---
|
||
|
||
## 9. 待确认/风险清单
|
||
|
||
- [ ] 余额 API 滞后上限实测(决定 BUFFER 是否调大,现 30 万;13:36 实测高估 ~50 万)
|
||
- [x] v4 误拦发现与回退(2026-08-12 15:09 生产日志实证,§7.3)
|
||
- [x] v5 恢复 v2 骨架(2026-08-12,§7.5;待生产主机重启生效)
|
||
- [ ] 消耗任务口径是否同步收紧(可选:其停止条件与闸门同一把尺子已满足)
|
||
- [ ] 空窗期(0:00–返还到账)行为观察:v5 下余额红线自动收紧,确认无异常误杀
|