feat: 每日消耗任务触发时点 23:00 改为 23:20
- volc_limit_sync:_maybe_trigger_daily_consume 改分钟级判断(23:20 起触发), 线程内 0-10 分钟随机抖动保留,实际执行窗口 23:20~23:30 - volc_consume:main 手动运行门卫同步 23:20 窗口(--force/--dry-run 不受限) - docs/volc-quota-notes §9:consume clamp2 余额快照滞后在最新思路(§4.2 量化 L=149,616)下确认为必改项,方向待定;消耗任务口径同步收紧标记 [x] - 全仓文档/注释 23:00 统一同步为 23:20(AGENTS/README/docker-compose/两 docs)
This commit is contained in:
+13
-13
@@ -1,7 +1,7 @@
|
||||
# 火山免费额度自动消耗:auto_consume 合入 volc_limit_sync 设计方案
|
||||
|
||||
> 日期:2026-08-11
|
||||
> 背景:`/root/workspace/huoshan-api-auto_consume/`(自动消耗脚本)与 `/root/workspace/litellm-config/`(LiteLLM 限流回调 + 火山余额同步)合并,使每日 23:00 自动消耗免费额度,防止资源包过期蒸发,避免真实扣费。
|
||||
> 背景:`/root/workspace/huoshan-api-auto_consume/`(自动消耗脚本)与 `/root/workspace/litellm-config/`(LiteLLM 限流回调 + 火山余额同步)合并,使每日 23:20 自动消耗免费额度,防止资源包过期蒸发,避免真实扣费。
|
||||
> 前置文档:《merge-volc-limit-into-newapi.md》(2026-08-05,方向相反:把 volc_limit_sync 功能迁往 new-api,未实施)。
|
||||
|
||||
---
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
```
|
||||
每天任意时刻 真实用户 + 消耗任务 的消耗 = 当日采集量(火山实时统计,每模型单独计算)
|
||||
每天 23:00 CST 消耗任务补齐缺口(可选,见 §4)
|
||||
每天 23:20 CST 消耗任务补齐缺口(可选,见 §4)
|
||||
次日 00:00 起 火山按昨日采集量发放资源包(不定时,可能延迟到上午)
|
||||
```
|
||||
|
||||
@@ -122,7 +122,7 @@ API 请求的 token 消耗不可精确控制(输入按字符估算、输出不
|
||||
**为什么均分优于一次性洗光**(在新模型下):
|
||||
1. **最小干扰真实用户**:只在额度即将死亡(进窗口)后才每天接管 1/D,其余留给真实用户 → 免费额度利用率最大化,空窗风险最小
|
||||
2. **请求负载分摊**:每天 3–5 次请求(而非 25–40 次),速率伪装自然,风控友好
|
||||
3. **余额下降平缓**:23:00 后余额仍保留大部分 → 扣费只发生在余额真正归零时,均分下脚本几乎不可能制造归零
|
||||
3. **余额下降平缓**:23:20 后余额仍保留大部分 → 扣费只发生在余额真正归零时,均分下脚本几乎不可能制造归零
|
||||
4. **FIFO 自动一致**:效期统一 30 天 → 获得早 = 过期早 → 队列头部 = 窗口内包,计划与执行不打架(分包明细仅用于定总量)
|
||||
|
||||
**与日返还循环的契合**:旧脚本本就是"每天跑一次、分 D 天烧完"的设计;自动化后每天重算(余额/天数变化 → div 递减 → 当日份额递增),节奏天然吻合。9 天窗口 + 1.1 系数 + 24h 冲刺:只要每天触发成功,任何进窗口的包都赶在过期前清空。
|
||||
@@ -149,9 +149,9 @@ daily_usage ≥ 2M → 停(采集上限,再烧不返还
|
||||
|
||||
### 3.6 触发调度
|
||||
|
||||
- 北京时间 **23:00 ± 随机抖动**(防固定时间被风控识别),Redis `consume:last_run:{日期}` 去重,当天未跑过才触发
|
||||
- 北京时间 **23:20 ± 随机抖动**(防固定时间被风控识别),Redis `consume:last_run:{日期}` 去重,当天未跑过才触发
|
||||
- 守护线程(`active_monitor_loop` 已有主循环)检测时点 → spawn daemon 线程执行,不阻塞主循环
|
||||
- 23:00 的时点语义:距 00:00 采集结算 1 小时,此时窗口内包状态已定(真实用户当天用量已发生),洗包目标最准
|
||||
- 23:20 的时点语义:距 00:00 采集结算 40 分钟,此时窗口内包状态已定(真实用户当天用量已发生),洗包目标最准
|
||||
|
||||
---
|
||||
|
||||
@@ -193,7 +193,7 @@ HARD_DAILY_LIMITS → 统一 2M(采集上限;doubao-seed-code-preview-251028
|
||||
- 返还:balance 跳涨 → 池涨 → 限额次日自动解锁(无需 RECHARGE)✓
|
||||
- 过期:balance 跳跌 → 池跌 → 限额收紧(无需 DROP)✓
|
||||
- 余额滞后(实测 20 万内不动):池虚高 ≤ 20 万 → BUFFER 30 万覆盖 ✓
|
||||
- 消耗任务 23:00 烧(usage 计入):池不变 → 滞后窗口内限额偏松 ≤ BUFFER ✓
|
||||
- 消耗任务 23:20 烧(usage 计入):池不变 → 滞后窗口内限额偏松 ≤ BUFFER ✓
|
||||
- 余额耗尽:池 − 30 万 ≤ 0 → 限额 0 → 全拦,扣费结构性杜绝 ✓
|
||||
|
||||
**fallback(stable_limit 缺失窗口)**:免费模型余额常态 < 2M(昨日采多少返多少),若 dynamic 缺失(首次同步前/新增模型/TTL 过期)时裸奔到静态 2M,余额不足的模型会被烧穿扣费。故 fallback 用保守值 `FALLBACK_LIMIT = min(static, 90万)`(env 可调),宁可短时收紧不可裸奔。
|
||||
@@ -211,7 +211,7 @@ HARD_DAILY_LIMITS → 统一 2M(采集上限;doubao-seed-code-preview-251028
|
||||
|
||||
### 4.4 空窗期防扣费闭环(消耗量计入 daily_usage 的理由)
|
||||
|
||||
23:00 消耗任务把额度洗掉后余额可能很低,此时真实用户请求必须被拦。拦截依据 = `daily_usage vs effective_limit`:
|
||||
23:20 消耗任务把额度洗掉后余额可能很低,此时真实用户请求必须被拦。拦截依据 = `daily_usage vs effective_limit`:
|
||||
|
||||
- **若消耗量不计入 daily_usage**:限额看到"真实用户才用 100k,未超限" → 放行 → **扣费**
|
||||
- **若计入**:daily_usage ≈ 真实 + 消耗任务 ≈ 2M → 超限拦截 → 空窗期安全
|
||||
@@ -266,7 +266,7 @@ effective_limit = min(HARD_DAILY_LIMITS, stable_limit)
|
||||
```
|
||||
litellm-config/
|
||||
├── volc_limit_sync.py # 现状:签名/拉取/归一化/限额/守护线程
|
||||
│ # 新增:23:00 调度钩子(检测时点 + spawn 消耗线程 + 去重)
|
||||
│ # 新增:23:20 调度钩子(检测时点 + spawn 消耗线程 + 去重)
|
||||
├── volc_consume.py # 新增:消耗任务(从 auto_consume 移植 + 改造)
|
||||
│ ├── load_base_logs / generate_dynamic_payload / _sanitize_line # 原样
|
||||
│ ├── calculate_plan # 保留 + 两个 clamp
|
||||
@@ -291,7 +291,7 @@ litellm-config/
|
||||
### 5.3 消耗任务执行流程
|
||||
|
||||
```
|
||||
23:00 触发(守护线程)
|
||||
23:20 触发(守护线程)
|
||||
→ consume:last_run:{今天} 已存在? → 跳过
|
||||
→ 遍历 MONITORED_MODELS(config.yaml 发现的 volcengine 模型)
|
||||
→ fetch_all_packages(复用)→ 按模型过滤窗口内包
|
||||
@@ -313,7 +313,7 @@ litellm-config/
|
||||
| 语料生成/脱敏/合成 | auto_consume | 原样移植 |
|
||||
| 速率伪装/退避/失败上限/6h 上限 | auto_consume | 原样移植 |
|
||||
| `_record_usage` 的 key 计算(`get_usage_key`) | volc_limit_sync | 消耗任务复用做 INCR |
|
||||
| 调度钩子 | 新增 | 守护线程 23:00 检测 + 去重 |
|
||||
| 调度钩子 | 新增 | 守护线程 23:20 检测 + 去重 |
|
||||
|
||||
---
|
||||
|
||||
@@ -324,8 +324,8 @@ litellm-config/
|
||||
| 空窗期(0:00–次日发放不定时) | **用户确认可接受**;均分策略使空窗概率最小化(余额平缓下降) |
|
||||
| 烧满 2M 的精确性 | 放弃该策略,改为过期风险驱动,结构性规避 |
|
||||
| 物理上限 | 窗口内快过期额度 > 2M 时每天最多洗 2M,极少数过期蒸发不可避(返还上限硬约束) |
|
||||
| 触发连续性 | 依赖每天 23:00 成功;连续失败 ~8 天耗尽窗口缓冲(冲刺兜底),守护线程常驻风险低 |
|
||||
| 风控 | 23:00 ± 抖动 + 15–40s 随机间隔 + 每天 3–5 次请求,接近真实行为 |
|
||||
| 触发连续性 | 依赖每天 23:20 成功;连续失败 ~8 天耗尽窗口缓冲(冲刺兜底),守护线程常驻风险低 |
|
||||
| 风控 | 23:20 ± 抖动 + 15–40s 随机间隔 + 每天 3–5 次请求,接近真实行为 |
|
||||
| 容器语料 | LiteLLM 容器内无 `/var/log` 系统日志 → 合成语料兜底(5000 行够用) |
|
||||
| 消耗任务自身扣费 | 结构性杜绝:plan ≤ 余额快照 − 缓冲,且每轮检查余额 |
|
||||
| 余额 API 滞后 | v5 恢复 v2(usage+balance−BUFFER):滞后收敛后守恒成立;滞后窗口由 BUFFER + 低余额加密同步覆盖;v4 冻结快照(balance−BUFFER)因误拦已回退 |
|
||||
@@ -345,7 +345,7 @@ litellm-config/
|
||||
|
||||
1. 移植 `auto_consume.py` 的语料/执行逻辑到 `volc_consume.py`,请求层改为直连 Ark(env key)
|
||||
2. `calculate_plan` 加两个 clamp + 停止条件;执行循环加 `daily_usage` INCR 与余额检查
|
||||
3. `volc_limit_sync.py` 守护线程加 23:00 调度钩子 + `consume:last_run` 去重
|
||||
3. `volc_limit_sync.py` 守护线程加 23:20 调度钩子 + `consume:last_run` 去重
|
||||
4. `HARD_DAILY_LIMITS` 统一为 2M;`MONITOR_TARGETS`/`config.py` 退役
|
||||
5. 用 `test_connection.py` 等价方式验证 Ark 连通 → 手动触发一次消耗任务(dry-run 模式验证 plan 计算与 clamp)→ 观察 Redis key 变化
|
||||
6. 全量回归:守护线程限额逻辑不受影响(消耗线程独立 daemon)
|
||||
|
||||
Reference in New Issue
Block a user