diff --git a/AGENTS.md b/AGENTS.md index a2ce3c0..a35d760 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ - **核心逻辑**:通过 `quota_interceptor` 拦截请求,并通过 `DailyLimitHandler` 记录用量到 Redis。后台 `active_monitor_loop` 守护线程定期从火山引擎 API 同步配额到 Redis。 - **架构**:主逻辑在 `volc_limit_sync.py`(限额 + 同步守护 + 每日消耗调度),消耗任务拆分在 `volc_consume.py`(每日北京时间 23:00 由守护线程延迟导入触发;见 `merge-auto-consume.md`)。LiteLLM 通过 `config.yaml` 中 `callbacks: ["volc_limit_sync.proxy_handler_instance"]` 加载回调,模块加载时自动启动后台同步线程。 - **关键文件**: - - `volc_limit_sync.py`: **核心文件**,包含同步守护线程(`active_monitor_loop`)、LiteLLM 回调(`DailyLimitHandler` + `quota_interceptor`)、限额计算(v4 冻结快照:`stable_limit = balance − BUFFER`,`effective_limit = min(2M 采集配额, stable_limit)`;扣费红线 = 余额,与采集量/返还无关,见 `docs/volc-quota-notes.md`)、模型屏蔽/恢复、以及每日 23:00 消耗任务调度(`_maybe_trigger_daily_consume`,SETNX 去重)。 + - `volc_limit_sync.py`: **核心文件**,包含同步守护线程(`active_monitor_loop`)、LiteLLM 回调(`DailyLimitHandler` + `quota_interceptor`)、限额计算(v5:`stable_limit = usage + balance − BUFFER`,`effective_limit = min(2M 采集配额, stable_limit)`;当日初始免费池守恒,扣费判定见 `docs/volc-quota-notes.md`)、模型屏蔽/恢复、以及每日 23:00 消耗任务调度(`_maybe_trigger_daily_consume`,SETNX 去重)。 - `volc_consume.py`: 消耗任务模块(每日 23:00 触发;手动 `python volc_consume.py --dry-run` / `--force`)。复用 volc_limit_sync 的拉包/归一化/用量记账设施,直连 Ark API 洗即将过期的免费资源包(防 30 天过期蒸发)。 - `config.yaml`: LiteLLM 配置文件,包含模型定义和回调配置。 - `docker-compose.yml`: 容器编排,仅挂载 `config.yaml`、`volc_limit_sync.py`、`volc_consume.py`。 diff --git a/README.md b/README.md index b6bb83e..ab1b681 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ python scripts/generate_keys.py ```python HARD_DAILY_LIMITS = { # 火山免费额度规则:每模型每日采集上限 2M,次日按采集量发放资源包。 - # 采集上限封顶;真正决定今日可采的是 v4 动态层: + # 采集上限封顶;真正决定今日可采的是 v5 动态层: # effective = min(2M, stable_limit),stable_limit = 余额快照 − BUFFER(见 docs/volc-quota-notes.md) "__DEFAULT__": 2_000_000, } diff --git a/docs/merge-auto-consume.md b/docs/merge-auto-consume.md index 164ca0f..f90e5e9 100644 --- a/docs/merge-auto-consume.md +++ b/docs/merge-auto-consume.md @@ -155,7 +155,7 @@ daily_usage ≥ 2M → 停(采集上限,再烧不返还 --- -## 四、限额设计(防扣费)——v2 简化逻辑(v4 修订见 §4.5,2026-08-12 已实施) +## 四、限额设计(防扣费)——v2 简化逻辑(v5 修订见 §4.5,2026-08-12 已实施) ### 4.1 为什么废弃 Peak-Buffer 峰值状态机(存量场景产物) @@ -175,8 +175,8 @@ daily_usage ≥ 2M → 停(采集上限,再烧不返还 ### 4.2 新公式 -> ⚠️ 2026-08-12 修订:本节 v2 公式「池恒定」假设(usage ↑ / balance ↓ 同步)失效, -> 已由 v4 取代(见 §4.5)。保留原文作历史论证。 +> ⚠️ 2026-08-12 修订:本节 v2 公式经实测确认**数学正确**(B 滞后收敛后守恒成立), +> 无需取代;v4 冻结快照尝试因误拦已回退(见 §4.5)。保留原文作论证。 ``` effective_limit = min(HARD_DAILY_LIMITS, max(0, usage + balance − BUFFER)) @@ -213,26 +213,36 @@ HARD_DAILY_LIMITS → 统一 2M(采集上限;doubao-seed-code-preview-251028 同步线程检测 balance 归零 → limit 收紧有 2–60min 滞后;消耗量计入让拦截在**滞后窗口内也有效**,双保险。 -### 4.5 v4 修订(2026-08-12 已实施):冻结快照,余额红线 +### 4.5 v5 修订(2026-08-12 已实施):恢复 v2 骨架,实测修正论证 -**v2 失效点**:`usage + balance = 当日初始可用池,消耗中恒定` 依赖余额 API 随消耗**实时递减**。实测余额 API 滞后(2026-08-12:快照 1,558,307 在 usage 1.24M→1.70M 期间纹丝不动,滞后上限未知),balance 不随消耗递减 → 池随 usage 膨胀(2.80M→3.26M)→「余额耗尽 → 限额 0」防线失效 → 放行到扣费区(当日超余额 13.8 万已扣费)。 +**v2 曾被误判失效**:2026-08-12 上午观察到「balance 快照 1,558,307 在 usage 1.24M→1.70M 期间 +不动」,据此推断 v2 的 `usage + balance` 池膨胀失效,改为 v4 冻结快照 `balance − BUFFER`。 -**扣费口径(用户确认,2026-08-12)**:是否扣费只取决于**当下免费额度(余额)**;超出免费额度的请求都会被扣费;采集量只决定明日发放,与今日是否扣费无关。→ 余额必须是闸门红线,且不能依赖 API 实时性。 +**v4 错误实证(15:09:51 生产日志)**:Bal=596,869(真实剩余 59.7 万),stable=296,869, +usage=1,696,135 → `[PRE-BLOCK] (1,696,135+16/296,869)` **误拦**——把「剩余余额」当 +「从 0 累计的上限」,U>0 时低估初始池,有真实免费额度却全拦。 -**v4 公式**: +**守恒反推(14:59:51 同步)**:U=1,696,135 + B=596,869 = B0=2,293,004 ≈ 理论剩余 597,004 ++ 已用 1,696,135 → **B 滞后收敛后满足 B = B0 − U,v2 公式数学正确**; +13:36 的 1,558,307 是滞后快照(高估真实剩余约 50 万),非余额不足。 +今日消耗 1,696,135 < B0 2,293,004 → **当日无扣费**。 + +**v5 公式(= v2 原式)**: ``` -stable_limit = max(0, balance − BUFFER) # 冻结快照,同步时算一次,不随 usage 膨胀 -effective_limit = min(HARD_DAILY_LIMITS, stable_limit) # 2M 防白烧;余额红线防扣费 +stable_limit = max(0, usage + balance − BUFFER) # 同步时算一次 +effective_limit = min(HARD_DAILY_LIMITS, stable_limit) ``` -- 以最近同步快照的余额为「当日免费池上限」,本地 usage 实时累计撞线即拦 → **等价于本地实时扣减余额**,不依赖 API 刷新 -- 返还:balance 跳涨 → 下次同步红线上升 → 自动解锁 ✓;过期/异常:balance 跳跌 → 红线收紧 ✓ -- 余额 < BUFFER → 限额 0 → 全拦,扣费结构性杜绝 ✓ +- `usage + balance` = 当日初始免费池(守恒),消耗中恒定(B 实时时);usage 累计撞线 + = 用到剩 BUFFER 时停 —— 防扣费语义正确 +- 残留风险仅「同步时点 B 滞后」→ stable 虚高 ≤ 滞后窗口消耗 → BUFFER + 低余额加密 + 同步(600s/300s)+ burst 触发覆盖;滞后收敛后池回守恒值 - 与消耗任务「余额快照 − 已烧 ≤ 0 停」同一把尺子(不变量:放行条件 = `balance − BUFFER ≥ 0`) -- 与昨日采集量**无关**:昨日 10K、余额 2M → 今日可用 1.7M(存量余额守恒,v3「昨日锚」因把单日流量当存量已被否决,见 volc-quota-notes.md §7.2) +- 与昨日采集量**无关**(存量余额守恒;v3「昨日锚」因把单日流量当存量已被否决) -**BUFFER 语义变化**:v2 里防「余额统计滞后 ≤ 20 万」;v4 里防「快照滞后窗口内(30min 常规同步 + burst 触发)的消耗 + 返还/过期抖动」。默认 30 万(env 可调),滞后上限未知时建议调大(如 50 万)。 +**BUFFER 语义**:防「同步时点余额滞后窗口内的消耗」。13:36 实测滞后高估 ~50 万 > 30 万, +滞后上限未实测 → 建议调大(如 50 万,env 可调)或实测后定。 ### 4.3 限额与消耗共用数据、方向相反 @@ -313,7 +323,7 @@ litellm-config/ | 风控 | 23:00 ± 抖动 + 15–40s 随机间隔 + 每天 3–5 次请求,接近真实行为 | | 容器语料 | LiteLLM 容器内无 `/var/log` 系统日志 → 合成语料兜底(5000 行够用) | | 消耗任务自身扣费 | 结构性杜绝:plan ≤ 余额快照 − 缓冲,且每轮检查余额 | -| 余额 API 滞后(v2 池膨胀根因) | v4 冻结快照:balance − BUFFER 定上限,本地 usage 实时撞线,滞后窗口由 BUFFER 覆盖 | +| 余额 API 滞后 | v5 恢复 v2(usage+balance−BUFFER):滞后收敛后守恒成立;滞后窗口由 BUFFER + 低余额加密同步覆盖;v4 冻结快照(balance−BUFFER)因误拦已回退 | --- diff --git a/docs/volc-quota-notes.md b/docs/volc-quota-notes.md index 54d6096..17647f8 100644 --- a/docs/volc-quota-notes.md +++ b/docs/volc-quota-notes.md @@ -7,8 +7,9 @@ > - 2026-08-12 对话澄清(扣费口径、余额 API 滞后、限额方案演进) > - 2026-08-12 生产日志观察(deepseek-v4-flash-ga-260731) > -> 代码现状:v4 已实施(2026-08-12,见 §7.3);工作区在 HEAD `c6c1224` 之上仅含 v4 改动。 -> v2/v3 内容保留为历史论证。 +> 代码现状:v5 = 恢复 v2 骨架(`stable_limit = usage + balance − BUFFER`),2026-08-12 修正; +> v4(balance−BUFFER 冻结快照)当天实施后即发现误拦已回退,见 §7.3/§7.5。 +> 工作区在 HEAD `c6c1224` 之上含 v5 修正。 --- @@ -117,9 +118,13 @@ Set Redis limit:dynamic:volcengine:remaining:deepseek-v4-flash-ga-260731 = 1,258 | StableLimit(v2) | 动态限额 | usage + balance − BUFFER(随 usage 膨胀,见 §7.1) | **Today > Rem 的原因**:Today 是单日流量,Rem 是存量余额快照,两套口径本就不该比较。 -今日消耗可以暂时大于余额显示值(先采后返),但按 §2 口径,**超出部分实际已扣费**。 火山网页「今日采集量 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 与日志口径(速查) @@ -130,25 +135,29 @@ Set Redis limit:dynamic:volcengine:remaining:deepseek-v4-flash-ga-260731 = 1,258 |---|---|---| | `daily_usage:{北京日期}:{model}:{hash}` | LiteLLM 成功回调 INCR + 消耗任务 INCR | 当日采集量,TTL 48h,北京 00:00 滚动 | | `limit:dynamic:volcengine:remaining:{model}` | 守护线程写 | 余额 − BUFFER(同步频率驱动、展示) | -| `limit:dynamic:volcengine:stable_limit:{model}` | 守护线程写 | 稳定限额(v2:usage+balance−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)`:成功记账 -- `📅 [Quota] ...`:每日额度汇总(v4 设计,未实施) --- ## 7. 限额方案演进 -### 7.1 v2(现状,HEAD c6c1224):`stable_limit = usage + balance − BUFFER` +### 7.1 v2(HEAD c6c1224 原式,v5 已恢复):`stable_limit = usage + balance − BUFFER` -- 意图:`usage + balance` = 当日初始可用池,消耗中恒定 → 限额恒定 -- **失效点**:该式假设 balance 随消耗实时递减;实测滞后 → usage 涨 balance 不动 → - 池膨胀(2026-08-12:2.80M → 3.26M)→ 「余额耗尽 → 限额 0」防线失效 → 放行到扣费区 -- 案例:余额 1,558,307 时 EffectiveLimit 仍取 2M,今日采到 1,696,135(超余额 13.8 万)未被拦 +- 意图:`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, 昨日采集量 × 系数)` @@ -158,53 +167,60 @@ Set Redis limit:dynamic:volcengine:remaining:deepseek-v4-flash-ga-260731 = 1,258 今日可用 = min(2M, 余额) ≈ 2M,与昨日无关 - 附:系数 <1.0 还会引发「今日少采 → 明日返还更少」的日复一日递减陷阱(0.9 系数 5 日降至 66%) -### 7.3 v4(2026-08-12 已实施):冻结快照 +### 7.3 v4(2026-08-12 实施后当天发现错误,已回退):冻结快照 ``` -stable_limit = max(0, balance − BUFFER) # 冻结快照,同步时算一次 -effective_limit = min(2M 采集配额, stable_limit) # 2M 防白烧;余额红线防扣费 +stable_limit = max(0, balance − BUFFER) # ❌ 错误:把「剩余余额」当「从 0 累计的上限」 ``` -- 唯一改动点:同步循环 stable_limit 从 `usage + balance − BUFFER` 改为 `balance − BUFFER` - (`volc_limit_sync.py` active_monitor_loop 同步段;debug 行 Pool 字段移除,改 Bal 口径) -- 数学等价于「本地实时扣减余额」:以最近快照余额为当日免费池上限, - usage 本地逐请求实时累计,撞线即拦,不再等 API -- 行为测试(2026-08-12,fake Redis 全过):冻结不膨胀 / 今日 1.696M 撞 1.258M 即拦 / - 余额 2M 可用 1.7M(与昨日无关)/ stable 缺失兜底 900K / 次日返还解锁 / 余额 < BUFFER 全拦 -- 效果对照(与 v2 现状): +- 设计初衷:余额 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) -| 场景 | v2 现状 | v4 | -|---|---|---| -| 余额 2M,昨日 10K | 可用 ≈2M | min(2M, 1.7M)=1.7M,不锁死 ✓ | -| 余额 1.558M,今日已采 1.696M | 不拦(膨胀到 3.26M) | 立即拦(1.696 ≥ 1.258)→ 止损 | -| 明日余额跳涨(返还 1.696M) | — | 红线升 1.4M,自动解锁 | +### 7.4 待观察项(2026-08-12) -- 与消耗任务防线「余额快照 − 已烧 ≤ 0 停」同一把尺子(merge-auto-consume.md §4.4) -- 连带改动:`get_effective_limit` 兜底链不变(stable → FALLBACK_LIMIT 90 万); - 文档同步(merge-auto-consume.md §4.2、AGENTS.md 限额描述) +- **BUFFER(现 30 万)**:防「同步时点 B 滞后窗口内的消耗」。13:36 实测高估约 50 万 + > 30 万 BUFFER → 若滞后窗口内流量大,v2 会多放行到虚高 stable;可调大(如 50 万,env) +- **部署**:v5 已改(工作区),需重启 litellm 容器加载;重启在生产主机由用户执行 -### 7.4 实施后待观察项(2026-08-12) +### 7.5 v5(2026-08-12 修正,当前):恢复 v2 骨架 -- **BUFFER(现 30 万,未调大)**:防「余额 API 滞后窗口内的消耗」。实测 20 万内不动 + 10 万冗余; - 滞后上限未知,若观察同步间隔内(burst 阈值 50 万)烧穿,调大(如 50 万,env 可调) -- **部署**:代码已改(工作区),需重启 litellm 容器加载(挂载文件);重启在生产主机由用户执行 +``` +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);但**按 §2 口径,超余额部分已在扣费**,应立即收闸 -2. 余额显示不动 ≠ 余额充足,是 API 滞后;以最近快照 + BUFFER 为准 -3. 判断「还能免费采多少」:`min(2M, 最近余额快照 − BUFFER) − 今日已采`(v4 已落地) +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. 扣费既成事实不可挽回(如 08-12 的 137,828);能做的只有止损(收闸)与次日恢复(返还) +5. 余额滞后收敛后守恒成立(B = B0 − U);30 天过期蒸发是余额下跌的另一来源, + 与消耗扣减区分(如 08-12 余额 1,558,307 → 596,869,其中约 50 万为滞后修正 + 过期) --- ## 9. 待确认/风险清单 -- [ ] 余额 API 滞后上限实测(决定 BUFFER 是否调大,现 30 万) -- [x] v4 方案批准与实施(2026-08-12,§7.3;待生产主机重启生效) +- [ ] 余额 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–返还到账)行为观察:v4 下余额红线自动收紧,确认无异常误杀 +- [ ] 空窗期(0:00–返还到账)行为观察:v5 下余额红线自动收紧,确认无异常误杀 diff --git a/volc_limit_sync.py b/volc_limit_sync.py index 2c53232..1527a28 100644 --- a/volc_limit_sync.py +++ b/volc_limit_sync.py @@ -1473,19 +1473,26 @@ def active_monitor_loop(): dynamic_key = f"limit:dynamic:volcengine:remaining:{target}" # ========================================== - # 📏 v4 冻结快照:stable_limit = max(0, balance − BUFFER) + # 📏 v5(恢复 v2 骨架):stable_limit = max(0, usage + balance − BUFFER) # ========================================== - # v2 的 usage + balance − BUFFER 假设「消耗中池恒定」(usage ↑ / - # balance ↓ 同步),但余额 API 实测滞后(2026-08-12 观察:快照 - # 1,558,307 在 usage 1.24M→1.70M 期间不动,滞后上限未知), - # balance 不随消耗实时递减 → 池随 usage 膨胀、限额虚高, - # 「余额耗尽 → 限额 0」防线失效 → 放行到扣费区(当日超余额 13.8 万)。 - # v4:以最近同步快照的余额为「当日免费池上限」,本地 usage 实时 - # 累计撞线即拦(等价于本地实时扣减余额),不随 usage 膨胀; - # 扣费判定 = 消耗 > 当下免费额度即扣费(与采集量/返还无关)。 - # BUFFER 覆盖快照滞后窗口内的消耗。见 docs/volc-quota-notes.md §7.3。 + # 论证(2026-08-12 实测修正): + # 1. 「usage + balance = 当日初始免费池」数学正确的前提是 balance 随 + # 消耗实时递减 —— 实测(14:59:51 同步)U=1,696,135 + B=596,869 + # = 2,293,004 ≈ 守恒初始池,B 在滞后收敛后确实等于 B0 − U, + # 与理论剩余 597,004 几乎一致 → v2 公式本身是对的。 + # 2. v4 的 balance − BUFFER 是错误:把「剩余余额」当「从 0 累计的 + # 上限」,同步时 U>0 则 stable 低估初始池 → 有真实剩余额度却误拦 + # (15:09:51 实测:Bal=596,869 剩 59.7 万却被 usage≥296,869 全拦)。 + # 3. v2 残留风险仅剩「同步时点 B 滞后」(13:36 快照 1,558,307 高估 + # 真实剩余约 50 万,池虚高)→ 由 BUFFER + 低余额加密同步(600s) + # + burst 触发覆盖;滞后收敛后(1 小时内实测)池回到守恒值。 + # 4. 扣费判定 = 消耗 > 当下免费额度即扣费;今日消耗 1,696,135 < + # 初始池 2,293,004 → 无扣费(此前"超余额 13.8 万已扣费"基于滞后 + # 快照 1,558,307 的推断不成立)。 + # 结论:stable = usage + balance − BUFFER(v2 原式),BUFFER 覆盖 + # 同步窗口内的余额滞后。见 docs/volc-quota-notes.md §7.5。 - stable_limit = int(max(0, balance - BUFFER)) + stable_limit = int(max(0, current_usage + balance - BUFFER)) stable_limit_key = ( f"limit:dynamic:volcengine:stable_limit:{target}"