fix: dynamic 限额缺失时 fallback 保守兜底(FALLBACK_LIMIT 90万)
免费模型余额常态 <2M(昨日采多少返多少),stable_limit 缺失窗口 (首次同步前/新增模型/TTL 过期)此前 fallback 裸奔到静态 2M, 余额不足的模型会被烧穿扣费。改为 min(static, FALLBACK_LIMIT=90万)。
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
- **核心逻辑**:通过 `quota_interceptor` 拦截请求,并通过 `DailyLimitHandler` 记录用量到 Redis。后台 `active_monitor_loop` 守护线程定期从火山引擎 API 同步配额到 Redis。
|
- **核心逻辑**:通过 `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`(限额 + 同步守护 + 每日消耗调度),消耗任务拆分在 `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`)、限额计算(v2 简化:`stable_limit = usage + balance − BUFFER`)、模型屏蔽/恢复、以及每日 23:00 消耗任务调度(`_maybe_trigger_daily_consume`,SETNX 去重)。
|
- `volc_limit_sync.py`: **核心文件**,包含同步守护线程(`active_monitor_loop`)、LiteLLM 回调(`DailyLimitHandler` + `quota_interceptor`)、限额计算(v2 简化:`stable_limit = usage + balance − BUFFER`,dynamic 缺失时 fallback `FALLBACK_LIMIT` 90 万兜底)、模型屏蔽/恢复、以及每日 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 天过期蒸发)。
|
- `volc_consume.py`: 消耗任务模块(每日 23:00 触发;手动 `python volc_consume.py --dry-run` / `--force`)。复用 volc_limit_sync 的拉包/归一化/用量记账设施,直连 Ark API 洗即将过期的免费资源包(防 30 天过期蒸发)。
|
||||||
- `config.yaml`: LiteLLM 配置文件,包含模型定义和回调配置。
|
- `config.yaml`: LiteLLM 配置文件,包含模型定义和回调配置。
|
||||||
- `docker-compose.yml`: 容器编排,仅挂载 `config.yaml` 和 `volc_limit_sync.py`。
|
- `docker-compose.yml`: 容器编排,仅挂载 `config.yaml` 和 `volc_limit_sync.py`。
|
||||||
|
|||||||
@@ -188,6 +188,8 @@ HARD_DAILY_LIMITS → 统一 2M(采集上限;doubao-seed-code-preview-251028
|
|||||||
- 消耗任务 23:00 烧(usage 计入):池不变 → 滞后窗口内限额偏松 ≤ BUFFER ✓
|
- 消耗任务 23:00 烧(usage 计入):池不变 → 滞后窗口内限额偏松 ≤ BUFFER ✓
|
||||||
- 余额耗尽:池 − 30 万 ≤ 0 → 限额 0 → 全拦,扣费结构性杜绝 ✓
|
- 余额耗尽:池 − 30 万 ≤ 0 → 限额 0 → 全拦,扣费结构性杜绝 ✓
|
||||||
|
|
||||||
|
**fallback(stable_limit 缺失窗口)**:免费模型余额常态 < 2M(昨日采多少返多少),若 dynamic 缺失(首次同步前/新增模型/TTL 过期)时裸奔到静态 2M,余额不足的模型会被烧穿扣费。故 fallback 用保守值 `FALLBACK_LIMIT = min(static, 90万)`(env 可调),宁可短时收紧不可裸奔。
|
||||||
|
|
||||||
**与消耗任务同构**:限额放行条件 = `balance − BUFFER ≥ 0`;消耗任务停止条件 = `余额快照 − 已烧 ≤ 0`——同一把尺子。
|
**与消耗任务同构**:限额放行条件 = `balance − BUFFER ≥ 0`;消耗任务停止条件 = `余额快照 − 已烧 ≤ 0`——同一把尺子。
|
||||||
|
|
||||||
### 4.3 简化后保留/删除清单
|
### 4.3 简化后保留/删除清单
|
||||||
|
|||||||
+11
-3
@@ -95,6 +95,11 @@ SYNC_INTERVAL = 60
|
|||||||
CHECK_INTERVAL = 10
|
CHECK_INTERVAL = 10
|
||||||
THRESHOLD = 300000
|
THRESHOLD = 300000
|
||||||
|
|
||||||
|
# stable_limit 缺失时(首次同步前/新增模型/TTL 过期)的保守兜底限额。
|
||||||
|
# 免费模型余额常态 < 2M(昨日采多少返多少),若 fallback 裸奔到采集上限 2M,
|
||||||
|
# 余额不足的模型会被烧穿扣费。宁可短时收紧,不可裸奔。
|
||||||
|
FALLBACK_LIMIT = int(os.getenv("FALLBACK_LIMIT", "900000"))
|
||||||
|
|
||||||
# Redis Config
|
# Redis Config
|
||||||
REDIS_HOST = os.getenv(
|
REDIS_HOST = os.getenv(
|
||||||
"REDIS_HOST", "redis"
|
"REDIS_HOST", "redis"
|
||||||
@@ -437,9 +442,12 @@ def get_effective_limit(clean_model, api_base, current_usage=None):
|
|||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
effective_limit = calculate_effective_limit(static_limit, None)
|
effective_limit = calculate_effective_limit(static_limit, None)
|
||||||
else:
|
else:
|
||||||
# Fallback: If daemon hasn't calculated stable limit yet, use old logic?
|
# Fallback: 如果 daemon 尚未计算 stable limit(首次同步前/新增模型/TTL 过期),
|
||||||
# Or just use static. Safer to wait for daemon.
|
# 用保守兜底(FALLBACK_LIMIT),绝不裸奔到采集上限 —— 免费模型余额常态 < 2M,
|
||||||
effective_limit = calculate_effective_limit(static_limit, None)
|
# 裸奔 2M 会把余额不足的模型烧穿扣费。
|
||||||
|
fallback = float(static_limit) if static_limit is not None else float(FALLBACK_LIMIT)
|
||||||
|
fallback = min(fallback, float(FALLBACK_LIMIT))
|
||||||
|
effective_limit = calculate_effective_limit(fallback, None)
|
||||||
|
|
||||||
# Legacy fallback (Optional: Enable if you want immediate loose limits before first sync)
|
# Legacy fallback (Optional: Enable if you want immediate loose limits before first sync)
|
||||||
# dynamic_remaining = redis_client.get(f"limit:dynamic:volcengine:remaining:{clean_model}")
|
# dynamic_remaining = redis_client.get(f"limit:dynamic:volcengine:remaining:{clean_model}")
|
||||||
|
|||||||
Reference in New Issue
Block a user