Files
litellm-config/README.md
T
vibe-code 9423adeea6 feat: manual_evict 自动解除(余额增量阈值)
- 首次命中 manual_evict key 时惰性记录 balance_at_sync 快照
  (manual_evict:snapshot:{raw_model}),后续每次请求比较当前余额,
  上升 ≥ AUTO_RELEASE_BALANCE_MARGIN(默认 50 万)时自动 DEL key 恢复
- 小额波动不误放,余额大幅上升(=免费额度已返还)才触发
- 幂等、可 env 覆盖(AUTO_RELEASE_BALANCE_MARGIN=500000)
- 自测 9/9 passed
2026-08-13 10:24:05 +00:00

296 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VolcSync - LiteLLM 火山模型监控与限额说明
## 当前生效入口
当前 `config.yaml` 使用的回调入口是:
```yaml
callbacks: ["volc_limit_sync.proxy_handler_instance"]
```
这意味着当前 Docker 容器里真正生效的是 `volc_limit_sync.py`。
旧脚本 `archive/daily_limit.py.deprecated` 目前 **未启用**,只保留作历史参考。除非你把 `callbacks` 改回旧模块,否则改它里面的 `MODEL_QUOTAS` 不会影响当前运行行为。
---
## 术语约定
为避免再把“白名单”这种不准确的说法带进来,这个仓库统一使用下面几组名称:
- **纳入监控模型**
- 指 `config.yaml` 中启用了火山 `api_base` 的上游模型。
- 这些模型会被 `volc_limit_sync.py` 自动发现,并参与资源包同步、用量统计和限额控制。
- **监控别名**
- 指火山资源包返回的名字,经过归一化后,用来匹配“纳入监控模型”的名字。
- 例如 `doubao-seed-2-0-pro-260215` 会自动推导出监控别名 `doubao-seed-2-0-pro`。
- **手工别名覆盖**
- 指 `volc_limit_sync.py` 中 `MANUAL_MONITORED_MODEL_ALIASES` 里的特殊映射。
- 只用于两类场景:
- 资源包名和上游模型名不一致。
- 一个资源包要映射到多个上游模型。
- **硬限额**
- 指 `volc_limit_sync.py` 中的 `HARD_DAILY_LIMITS`。
- 支持三种常见粒度:
- `model:hash`
- `model`
- `__DEFAULT__`
---
## 维护入口
### 主入口:`config.yaml`
新增、删除“纳入监控模型”时,第一步永远是改 `config.yaml` 里的 `model_list`。
对大多数正常的版本号模型,做到这一步就已经足够让运行时识别它们进入监控链路了。现在的逻辑会自动把:
```text
deepseek-v3-2-251201 -> deepseek-v3-2
doubao-seed-2-0-pro-260215 -> doubao-seed-2-0-pro
glm-4-7-251222 -> glm-4-7
```
这类常规版本号模型推导成监控别名,不需要你再手工去补映射。
### 审计入口:`generate_keys.py`
每次改完 `config.yaml` 后,执行:
```bash
python scripts/generate_keys.py
```
这个脚本现在不是单纯“生成 key”,而是正式的 **监控模型审计入口**。它会输出:
- 当前从 `config.yaml` 发现了哪些“纳入监控模型”
- 每个上游模型对应哪些“监控别名”
- 每个模型当前命中的限额来源
- 自定义键
- 模型级规则
- 模糊规则
- `__DEFAULT__`
- 哪些模型当前仍在使用 `__DEFAULT__`
- 如果你想把默认限额改成单模型硬限额,应复制哪些 key 到 `HARD_DAILY_LIMITS`
### 特殊入口:`volc_limit_sync.py`
只有下面两种情况,才需要改 `volc_limit_sync.py`:
1. 资源包名和上游模型名不一致
示例:
```python
"doubao-seed-code": "doubao-seed-code-preview-251028"
```
2. 一个资源包要映射到多个上游模型
示例:
```python
"doubao-seed-1-6": ["doubao-seed-1-6-250615", "doubao-seed-1-6-251015"]
```
如果只是新增一个普通的版本号模型,例如 `xxx-260215`,通常不需要改这里。
---
## 推荐维护流程
### 新增监控模型
1. 在 `config.yaml` 的 `model_list` 里加入新的火山模型条目。
2. 运行 `python scripts/generate_keys.py`。
3. 先确认脚本输出中:
- 该模型已经出现在“监控模型审计”里。
- “监控别名”正确。
- “限额来源”符合预期。
4. 如果只是走默认限额,到这一步通常已经可以结束。
5. 如果需要单模型硬限额,把脚本输出的 key 复制到 `volc_limit_sync.py` 的 `HARD_DAILY_LIMITS`。
6. 只有当脚本显示资源包名无法靠常规版本号自动推导时,再去改 `MANUAL_MONITORED_MODEL_ALIASES`。
7. 重启 LiteLLM 容器,让新配置生效。
### 删除监控模型
1. 从 `config.yaml` 里删掉对应模型条目。
2. 运行 `python scripts/generate_keys.py`,确认它已经不在“监控模型审计”里。
3. 如果该模型曾有单独的 `HARD_DAILY_LIMITS` 项,可以按需清理。
4. 如果该模型对应的是特殊手工别名,且已经没有任何上游模型再用它,可以再清理 `MANUAL_MONITORED_MODEL_ALIASES`。
5. 重启 LiteLLM 容器。
---
## 运行时行为概览
### 1. 自动发现纳入监控模型
`volc_limit_sync.py` 启动后会扫描 `config.yaml`,找出使用火山 `api_base` 的上游模型,并记录:
- 监控的上游模型名
- `api_base` 对应的 hash
- 由上游模型自动推导出来的监控别名
### 2. 资源包名归一化
火山接口返回资源包名后,脚本会先做归一化:
- 去掉资源包后缀
- 统一小写
- `_` 和 `.` 归一化成 `-`
之后再尝试通过:
- 自动版本号推导
- 手工别名覆盖
把资源包归到实际纳入监控的上游模型。
### 3. 限额来源优先级
`HARD_DAILY_LIMITS` 的命中顺序是:
1. `model:hash`
2. `model`
3. 模糊规则
4. `__DEFAULT__`
例如(当前值,2026-08):
```python
HARD_DAILY_LIMITS = {
# 火山免费额度规则:每模型每日采集上限 2M,次日按采集量发放资源包。
# 采集上限封顶;真正决定今日可采的是 v5 动态层:
# effective = min(2M, stable_limit),stable_limit = 余额快照 − BUFFER(见 docs/volc-quota-notes.md)
"__DEFAULT__": 2_000_000,
}
```
---
## 常见坑
### 1. 改了旧脚本(`archive/daily_limit.py.deprecated`)但不生效
这是最容易踩的坑。
当前 `config.yaml` 没有启用旧模块 `daily_limit`,所以:
- 改 `archive/daily_limit.py.deprecated`
- 改 `MODEL_QUOTAS`
都不会影响当前 LiteLLM 容器的启动和监控行为。
### 2. 只补了硬限额,但没有纳入监控
`HARD_DAILY_LIMITS` 只负责限额,不负责把模型纳入监控。
模型是否被监控,首先取决于:
- `config.yaml` 是否有该火山模型条目
- 资源包名是否能被自动推导或手工别名覆盖正确归到该模型
### 3. 普通版本号模型不需要每次都手改映射
现在的运行逻辑已经支持从上游模型自动推导:
```text
xxx-251201 -> xxx
xxx-260215 -> xxx
```
所以普通版本升级时,通常只需要改 `config.yaml`,再跑一遍 `python scripts/generate_keys.py` 审计确认。
---
## 常用命令
### 审计当前纳入监控模型
```bash
python scripts/generate_keys.py
```
### 直接运行同步监控
```bash
python volc_limit_sync.py
```
### LiteLLM 调试模式
```bash
DAILY_LIMIT_LOG_LEVEL=DEBUG python volc_limit_sync.py
```
### 手动软踢某个模型(运维应急,立即 429)
模型踩采集上限/异常时,无需等脚本同步阈值,直接往 Redis 写一个 `manual_evict` key 即可将该模型**立即、持续地**软踢(恒 429,直到显式解除)。
key 格式:`manual_evict:<config.yaml 中该条目的完整 model 字段>`(**含渠道前缀,全匹配**,如 `volcengine/deepseek-v4-flash-ga-260731`;同一 clean 名但不同渠道的模型不会被误伤)。
```bash
# 软踢:立即对该模型返回 429(key 落 Redis 持久卷,重启 litellm 后仍生效)
docker exec litellm_redis redis-cli SET manual_evict:volcengine/<model> 1
# 解除软踢
docker exec litellm_redis redis-cli DEL manual_evict:volcengine/<model>
# 查看当前手动软踢的模型
docker exec litellm_redis redis-cli KEYS manual_evict:*
```
示例(软踢 deepseek-v4-flash-ga-260731):
```bash
docker exec litellm_redis redis-cli SET manual_evict:volcengine/deepseek-v4-flash-ga-260731 1
```
注意:
- 软踢只作用于**纳入监控**的火山模型(`MONITORED_MODEL_PAIRS` 内);非监控渠道不受影响。
- 幂等:key 在期间每个请求都 429,重复 SET 无副作用。
- 解除后立即恢复按正常限额判定。
- **自动解除**:当脚本检测到当前 `balance_at_sync` 比踢除时记录的余额快照**上升 ≥ 50 万**(`AUTO_RELEASE_BALANCE_MARGIN`,可调),即视为免费额度已返还,自动 DEL 该 key 并恢复请求。日常运维无需手动 DEL;仅当模型已被自动解除但你想立即恢复软踢时,重新 SET 即可。
- 自动解除阈值默认 50 万,可在 `.env` 中覆盖:`AUTO_RELEASE_BALANCE_MARGIN=1000000`。
---
## 文件职责
```text
litellm-config/
├── config.yaml # 纳入监控模型的主入口
├── docker-compose.yml # 容器编排(挂载 config.yaml / volc_limit_sync.py / volc_consume.py)
├── volc_limit_sync.py # 当前生效的监控、同步、限额脚本(v4 冻结快照限额)
├── volc_consume.py # 每日 23:20 自动消耗任务(防免费资源包过期蒸发)
├── AGENTS.md # 仓库 Agent 协议(代码风格/运行/提交规范)
├── README.md
├── docs/
│ ├── merge-auto-consume.md # 消耗任务 + 限额设计(v2 历史 / v4 修订)
│ ├── volc-quota-notes.md # 火山额度机制速查(扣费口径/方案演进/排障)
│ └── merge-volc-limit-into-newapi.md # 未实施的迁移方案(历史)
├── scripts/
│ └── generate_keys.py # 监控模型审计入口
├── debug/
│ ├── debug_volc_sync.py # 资源包调试脚本
│ └── debug_volc_sync_manual.py # 手动调试脚本
└── archive/
├── daily_limit.py.deprecated # 旧脚本,当前 config 未启用(历史参考)
└── recover.py # 一次性恢复工具(历史)
```
---
## 维护原则
- 先改 `config.yaml`,不要先改旧脚本 `archive/daily_limit.py.deprecated`
- 先跑 `python scripts/generate_keys.py` 审计,再决定要不要补 `HARD_DAILY_LIMITS`
- 普通版本号模型优先依赖自动推导,不要手工补一堆重复映射
- 只有特殊别名或一对多场景,才改 `MANUAL_MONITORED_MODEL_ALIASES`