From f15b64e31f55e4076e573b8fae5af34dd25f639a Mon Sep 17 00:00:00 2001 From: vibe-code Date: Thu, 13 Aug 2026 08:31:37 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=B6=88=E8=80=97=E4=BB=BB=E5=8A=A1=20c?= =?UTF-8?q?lamp2=20=E6=94=B9=E5=AE=88=E6=81=92=E5=8F=A3=E5=BE=84,=E6=B6=88?= =?UTF-8?q?=E9=99=A4=E4=BD=99=E9=A2=9D=E5=BF=AB=E7=85=A7=E6=BB=9E=E5=90=8E?= =?UTF-8?q?=E8=B6=85=E7=83=A7=E9=A3=8E=E9=99=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - b0_est = 拉包时刻 余额+usage (= B0+L,与 v6 闸门同构) - clamp2: plan ≤ b0_est − SMALL_BUFFER − usage_now; 停止条件 2 改 usage ≥ b0_est − SMALL_BUFFER,每轮实时读共享 key,真实用户消耗 结构性计入,两方合计超烧杜绝(残余风险收敛为 §7.5 L 同款) - 数字用例验证: L=0 撞墙剩 SMALL_BUFFER(旧方案执行中用户耗 100k 超扣 100k) - docs: §8 排障 4/§9 条目翻转为已实施;新增视觉图片 reserve 估算 口径校准待确认项(LiteLLM 85/765 OpenAI 口径 vs 火山未公开公式) --- docs/merge-auto-consume.md | 2 +- docs/volc-quota-notes.md | 33 +++++++++++++++++++++------------ volc_consume.py | 30 +++++++++++++++++++----------- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/docs/merge-auto-consume.md b/docs/merge-auto-consume.md index 6a5271d..1eb9bc8 100644 --- a/docs/merge-auto-consume.md +++ b/docs/merge-auto-consume.md @@ -327,7 +327,7 @@ litellm-config/ | 触发连续性 | 依赖每天 23:20 成功;连续失败 ~8 天耗尽窗口缓冲(冲刺兜底),守护线程常驻风险低 | | 风控 | 23:20 ± 抖动 + 15–40s 随机间隔 + 每天 3–5 次请求,接近真实行为 | | 容器语料 | LiteLLM 容器内无 `/var/log` 系统日志 → 合成语料兜底(5000 行够用) | -| 消耗任务自身扣费 | 结构性杜绝:plan ≤ 余额快照 − 缓冲,且每轮检查余额 | +| 消耗任务自身扣费 | 结构性杜绝:有效墙 min(2M, b0_est − SMALL_BUFFER)(b0_est = 拉包时刻 余额+usage,守恒口径与 v6 闸门同构,2026-08-13 实施);usage 每轮实时含真实用户 → 两方合计不可超烧 | | 余额 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 4dbd4b7..7cd0396 100644 --- a/docs/volc-quota-notes.md +++ b/docs/volc-quota-notes.md @@ -396,7 +396,8 @@ reserve = 18输入 + 16声明 = 34,实际消耗 +167/+150(正文 ~16 + 思 在滞后未收敛时 = B0 + L(虚高),「实时抵消」仅覆盖同步后窗口,L 不抵消(§7.5) 3. 判断「还能免费采多少」:保守用 `网页 B0 − 今日已采`;v6 公式在滞后收敛时等价,未收敛时偏高 L 4. 消耗任务 23:20 直连 Ark 绕过 LiteLLM 闸门(防自杀),其自身 clamp:`plan ≤ 2M − usage`、 - `plan ≤ 余额快照 − SMALL_BUFFER`,停止条件三闭环 + `plan ≤ b0_est − SMALL_BUFFER − usage`(b0_est = 拉包时刻 余额+usage,守恒口径与 v6 闸门同构, + 2026-08-13 已实施),停止条件三闭环 5. 余额滞后不改变 B0 守恒;30 天过期蒸发是余额下跌的另一来源, 与消耗扣减区分(如 08-12 余额 1,558,307 → 596,869,其中约 50 万为滞后修正 + 过期) 6. 2M 采集上限可被单请求 + 并发击穿(§7.6):reserve 估算不足时已放行的请求继续消耗, @@ -417,6 +418,14 @@ reserve = 18输入 + 16声明 = 34,实际消耗 +167/+150(正文 ~16 + 思 - [x] 2M 采集上限击穿修复(2026-08-12 20:53 实测 §7.6:reserve 改用 token_counter + max_tokens, 后置 soft_evict 兜底;23:18 重启后 PRE-BLOCK 生效) - [x] 消耗任务口径同步收紧(2026-08-13 代码确认:clamp2 用 `vls.SMALL_BUFFER`,与闸门同源一致) +- [ ] consume clamp2 余额快照口径修复待观测(2026-08-13 已实施守恒口径,待 1-2 个结算周期观测 + 🔴 深夜 L 实际是否 < SMALL_BUFFER;若触发"守恒墙已耗尽"且当日有扣费疑点 → 叠加 A' 收敛重取) +- [ ] 视觉图片请求 reserve 估算口径未校准(2026-08-13 调查):LiteLLM `token_counter` 对 OpenAI 格式 + image_url 按 OpenAI 口径计(detail low/auto = 85 token/图,high = 下载图按 tile 85+170×tiles, + 失败 fallback ~255),**与火山 Ark doubao 视觉模型实际计费公式不一致**;官方仅提供 Token 计算器 + 工具(未公开公式),FAQ 只说"图片计入输入 token"。闸门调用未传 use_default_image_token_count → + high-detail 图会在 hook 内同步下载(阻塞)。偏差量级 = 每图几十~几百 token,相对 + THINKING_RESERVE_FLOOR(4096) 小;方向待实测(Token 计算器对照或发图看 usage),有图流量时关注 - [ ] 空窗期(0:00~返还到账)行为观察:v6 下 B0 自动收紧,确认无异常误杀 - [ ] 数据库泄漏:08-12 一天 deepseek-v4 消耗记录量级约 5 万条导致 Redis 内存膨胀;触发监控/清理机制 - [ ] v6 无静态 2M 兜底时的安全:08-13 幸由 B0(2,242,178) > 2M 静态墙兜底;若某日 B0 < 2M, @@ -424,16 +433,16 @@ reserve = 18输入 + 16声明 = 34,实际消耗 +167/+150(正文 ~16 + 思 - [x] reserve 精度验证(2026-08-13 短文本实证:估算 34 vs 实际 167 的根因 = 思考模型 reasoning tokens 不计入 reserve,已用 THINKING_RESERVE_FLOOR 兜底; token_counter cl100k_base 对中文偏高对输入侧仍是安全方向) -- [ ] consume clamp2 余额快照口径不同步(2026-08-13 最新思路下确认为**必改项**,推荐方向 C 守恒口径, - 待实施):`plan ≤ balance − SMALL_BUFFER` 用拉包时刻余额快照 (volc_consume.py:455),**不含 - 23:20→00:00 真实用户消耗**;clamp1 用共享 daily_usage 实时精准,但余额维度两方不同步。§4.2 已 - 实测结算滞后 Δ≈14 分钟 → 快照相对真实剩余虚高 L(随消费速度增长,实测 149,616 > SMALL_BUFFER - 5 万),深夜真实消耗大时两方合计可超烧余额。 - 修复方向(分析 2026-08-13): - - ✅ **C 守恒口径(推荐)**:`_record_consumption` 已将自身 INCR 进共享 daily_usage,每轮 - `_current_daily_usage` 即"真实用户+自身"总消耗 → `b0_est = balance + usage_now`(= B0+L,与 - v6 闸门同构),clamp2 改 `plan ≤ b0_est − SMALL_BUFFER − usage_now`、停止条件改 - `usage ≥ b0_est − SMALL_BUFFER`(与 clamp1 同构)。零 API 成本,两方不同步结构性消除; - 残余风险 = §7.5 遗留风险 1 同款(L > SMALL_BUFFER 时 b0_est 虚高)。 +- [x] consume clamp2 余额快照口径不同步(2026-08-13 已实施方向 C 守恒口径):原 `plan ≤ balance − + SMALL_BUFFER` 用拉包时刻余额快照 (volc_consume.py:455),**不含 23:20→00:00 真实用户消耗**; + clamp1 用共享 daily_usage 实时精准,但余额维度两方不同步。§4.2 已实测结算滞后 Δ≈14 分钟 → + 快照相对真实剩余虚高 L(随消费速度增长,实测 149,616 > SMALL_BUFFER 5 万),深夜真实消耗大时 + 两方合计可超烧余额。 + 实施内容(2026-08-13):`_record_consumption` 已将自身 INCR 进共享 daily_usage,每轮 + `_current_daily_usage` 即"真实用户+自身"总消耗 → `b0_est = balance + usage_now`(= B0+L,与 + v6 闸门同构),clamp2 改 `plan ≤ b0_est − SMALL_BUFFER − usage_now`、停止条件改 + `usage ≥ b0_est − SMALL_BUFFER`(与 clamp1 同构)。零 API 成本,两方不同步结构性消除。 + 数字用例验证:L=0 时撞墙剩 SMALL_BUFFER(旧方案执行中用户消耗 100k → 超扣 100k); + L>0 残余风险 = §7.5 遗留风险 1 同款(L > SMALL_BUFFER 时 b0_est 虚高,与闸门共享,非消耗任务独有)。 - 🅰 A' 可选叠加:执行前睡 ~15 分钟再拉一次取收敛 balance 算 b0_est(防 L 大,成本 8 次 API) - ❌ B 扣减 L 预估:v5 BUFFER 盲猜教训(L 实测浮动 15 倍),否决 diff --git a/volc_consume.py b/volc_consume.py index 78bdebe..0a4b8c8 100644 --- a/volc_consume.py +++ b/volc_consume.py @@ -8,7 +8,7 @@ # - 直连 Ark API(Bearer token,绕过 LiteLLM 限额,避免消耗任务自杀) # - 消耗量手动 INCR 进 daily_usage(与 LiteLLM 回调同 key): # ① 算准采集上限缺口,② 空窗期限额能正确拦截真实用户(防扣费) -# - 三条停止条件:daily_usage ≥ 2M / 余额快照 − 已烧 ≤ 0 / 已烧 ≥ plan +# - 三条停止条件:daily_usage ≥ 2M / 总用量 ≥ 守恒墙(b0_est−SMALL_BUFFER,与 v6 闸门同构) / 已烧 ≥ plan # # 手动运行: # python volc_consume.py --dry-run # 只算计划不消耗 @@ -429,8 +429,9 @@ def run_consume_model(model, source_groups, order, packages=None, dry_run=False) 对单个监控模型执行"洗过期包"消耗。 目标 = Σ窗口内包计划(均分×1.1/冲刺),clamp: - 采集上限:plan ≤ CONSUME_DAILY_CAP − 当日已消耗 - - 防扣费:plan ≤ 余额快照 − SMALL_BUFFER - 停止条件(每轮检查):daily_usage ≥ 2M / 余额快照−已烧 ≤ 0 / 已烧 ≥ plan + - 防扣费:plan ≤ b0_est − SMALL_BUFFER − 当日已消耗(b0_est = 拉包时刻 余额+usage, + 守恒口径与 v6 闸门同构,见 docs/volc-quota-notes.md §9) + 停止条件(每轮检查):daily_usage ≥ 2M / 总用量 ≥ b0_est − SMALL_BUFFER / 已烧 ≥ plan :param packages: 复用 run_consume_all 的一次拉包结果;None 时自行拉取 """ if packages is None: @@ -451,8 +452,11 @@ def run_consume_model(model, source_groups, order, packages=None, dry_run=False) usage_now = _current_daily_usage(model) # clamp 1: 采集上限(超出部分不返还,白烧) plan = min(plan, CONSUME_DAILY_CAP - usage_now) -# clamp 2: 余额快照 − SMALL_BUFFER(脚本自身不烧穿余额,防扣费) - plan = min(plan, max(0, balance - vls.SMALL_BUFFER)) + # clamp 2: 守恒墙(与 v6 闸门同构,见 docs/volc-quota-notes.md §7.5/§9) + # b0_est = 拉包时刻 余额快照 + usage = B0 + L(L = 滞后窗口未结算消耗); + # 有效墙 min(2M, b0_est − SMALL_BUFFER),usage_now 实时含真实用户 → 两方合计结构性消除 + b0_est = balance + usage_now + plan = min(plan, max(0, b0_est - vls.SMALL_BUFFER - usage_now)) plan = int(max(0, plan)) if plan < CONSUME_MIN_PLAN: @@ -460,18 +464,19 @@ def run_consume_model(model, source_groups, order, packages=None, dry_run=False) return vls.log( - f"▶️ [{model}] 目标消耗 {plan:,} | 余额 {balance:,} | 当日已用 {usage_now:.0f}" + f"▶️ [{model}] 目标消耗 {plan:,} | 守恒墙 {int(b0_est - vls.SMALL_BUFFER):,} | 当日已用 {usage_now:.0f}" ) if dry_run: vls.log(f"🔍 [dry-run] 仅计算,不发送请求") return - _run_requests(model, plan, balance, source_groups, order) + _run_requests(model, plan, b0_est, source_groups, order) -def _run_requests(model, plan, balance_snapshot, source_groups, order): +def _run_requests(model, plan, b0_est, source_groups, order): """ 循环发送消耗请求。速率:目标 1 小时内完成(23:20 触发,00:00 结算)。 + b0_est: 拉包时刻守恒池 = balance + usage(= B0 + L),有效墙 = min(2M, b0_est − SMALL_BUFFER)。 """ burned = 0 fail_count = 0 @@ -509,9 +514,12 @@ def _run_requests(model, plan, balance_snapshot, source_groups, order): if _current_daily_usage(model) >= CONSUME_DAILY_CAP: vls.log(f"🛑 [{model}] 当日采集已达上限 {CONSUME_DAILY_CAP:,},停止", level="WARNING") break - # 停止条件 2: 余额快照耗尽(防扣费) - if (balance_snapshot - burned) <= 0: - vls.log(f"🛑 [{model}] 余额快照已耗尽,停止(防扣费)", level="WARNING") + # 停止条件 2: 守恒墙耗尽(防扣费;usage 实时含真实用户+自身,两方合计结构性杜绝) + if _current_daily_usage(model) >= b0_est - vls.SMALL_BUFFER: + vls.log( + f"🛑 [{model}] 守恒墙已耗尽(b0_est−SMALL_BUFFER),停止(防扣费)", + level="WARNING", + ) break # 停止条件 3: 计划完成 if burned >= plan: