跳转至

01 — 价格 JSON 文件(model_cost map)生命周期

概述

litellm.model_cost 是一个进程级全局 dict,存储所有已知模型的价格与能力信息。它在模块导入时同步初始化,之后作为所有计费查询的基础数据源。


初始化时机与代码路径

触发点import litellm 时,Python 解释器顺序执行 __init__.py,在第 440 行完成同步赋值。

# litellm/__init__.py:339-341
model_cost_map_url: str = os.getenv(
    "LITELLM_MODEL_COST_MAP_URL",
    "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
)

# litellm/__init__.py:438-440
from litellm.litellm_core_utils.get_model_cost_map import get_model_cost_map
model_cost = get_model_cost_map(url=model_cost_map_url)

进程内共享:同一进程的所有线程和协程引用同一个 dict 对象,任何修改(register_model、热重载)都对全局可见。


远程拉取流程

flowchart TD
    A[get_model_cost_map URL] --> B{LITELLM_LOCAL_MODEL_COST_MAP=true?}
    B -- 是 --> C[load_local_model_cost_map\n读取 backup JSON]
    B -- 否 --> D[fetch_remote_model_cost_map\nhttpx.get timeout=5s]
    D -- 成功 --> E{validate_model_cost_map}
    D -- 失败/超时 --> F[fallback: load_local_model_cost_map]
    E -- 校验通过 --> G[使用远程 dict]
    E -- 校验失败\n模型数 < 最小值 或 缩减超比例 --> F
    F --> H[litellm.model_cost]
    G --> H
    C --> H

相关文件litellm/litellm_core_utils/get_model_cost_map.py:154-200

# get_model_cost_map.py:154-169
def get_model_cost_map(url: str) -> dict:
    if os.getenv("LITELLM_LOCAL_MODEL_COST_MAP", "").lower() == "true":
        return GetModelCostMap.load_local_model_cost_map()
    try:
        content = GetModelCostMap.fetch_remote_model_cost_map(url)
    except Exception as e:
        verbose_logger.warning("Failed to fetch remote model cost map ... Falling back to local backup.")
        return GetModelCostMap.load_local_model_cost_map()
    ...

本地 backup 文件

项目 说明
文件路径 litellm/model_prices_and_context_window_backup.json
访问方式 importlib.resources.files("litellm").joinpath("model_prices_and_context_window_backup.json")
生效环境变量 LITELLM_LOCAL_MODEL_COST_MAP=true
自定义模型写法 在此文件中添加 key,格式为 "provider/model_name"

添加自定义模型的 key 格式规则(查找优先级顺序):

优先级 key 格式 示例(model=Vendor2/Claude-4.6-Opus, provider=anthropic
1 {provider}/{model} "anthropic/Vendor2/Claude-4.6-Opus"
2 {model} "Vendor2/Claude-4.6-Opus"
3 {provider}/{stripped_model} 同 1(无版本号可剥离)
4 {stripped_model} 同 2
5 {split_model} 同 2

两种格式均可命中,推荐使用格式 1("anthropic/Vendor2/Claude-4.6-Opus")最明确。


热重载端点

端点POST /reload/model_cost_map 定义litellm/proxy/proxy_server.py:12075-12147 权限:仅 PROXY_ADMIN

热重载做了什么

# proxy_server.py:12075~
@router.post("/reload/model_cost_map")
async def reload_model_cost_map(...):
    # 1. 重新拉取(或读 backup)
    new_map = get_model_cost_map(url=litellm.model_cost_map_url)
    # 2. 整体替换 dict
    litellm.model_cost = new_map
    # 3. 清空大小写 lookup cache 和 LRU cache
    _invalidate_model_cost_lowercase_map()
    # 4. 向 DB 写 force_reload=True,通知其他 Pod
    await prisma_client.db.litellm_config.upsert(...)

热重载做不到的事

sequenceDiagram
    participant Admin
    participant ProxyServer
    participant model_cost as litellm.model_cost
    participant Router

    Admin->>ProxyServer: POST /reload/model_cost_map
    ProxyServer->>model_cost: 整体替换为新 dict
    Note over model_cost: ⚠️ 所有 UUID 条目被清除!\n(UUID 不在远程 JSON 中)
    Note over Router: Router.model_list 中的 deployment\n仍然存在,但计费查不到 UUID 价格
    Note over Router: 等待 30s 轮询 add_deployment\n重新执行 _create_deployment → register_model\n才能恢复 UUID 条目

结论:热重载后约 30 秒内,使用 UUID 路径(custom_pricing=True)的模型会临时找不到自定义价格,回退到 JSON 路径。


litellm.register_model() 的作用

调用时机:每次 Router._create_deployment() 执行时,被调用两次。

定义litellm/utils.py:2782-2820(约)

# router.py:6197-6230
# 第一次:以 UUID 为 key,注册完整自定义价格
for field in CustomPricingLiteLLMParams.model_fields.keys():
    if deployment.litellm_params.get(field) is not None:
        _model_info[field] = deployment.litellm_params[field]
litellm.register_model(model_cost={model_id: _model_info})

# 第二次:以 "provider/model_name" 为 key,注册不含自定义价格字段的共享信息
_custom_pricing_fields = CustomPricingLiteLLMParams.model_fields.keys()
_shared_model_info = {k: v for k, v in _model_info.items() if k not in _custom_pricing_fields}
litellm.register_model(model_cost={_model_name: _shared_model_info})

影响的数据结构: - litellm.model_cost dict:写入/更新对应 key - _model_cost_lowercase_map:大小写不敏感 lookup 缓存,同步失效 - provider 模型集合(litellm.anthropic_models 等):按 litellm_provider 字段追加


多 Pod 场景的热重载同步

sequenceDiagram
    participant Pod1
    participant DB as PostgreSQL litellm_config
    participant Pod2

    Pod1->>Pod1: POST /reload/model_cost_map
    Pod1->>Pod1: litellm.model_cost = new_map
    Pod1->>DB: INSERT force_reload=True
    Note over Pod2: 每30秒 _check_and_reload_model_cost_map()
    Pod2->>DB: 查询 force_reload 标志
    DB-->>Pod2: force_reload=True
    Pod2->>Pod2: 重载 model_cost
    Pod2->>DB: 清零 force_reload 标志

相关代码proxy_server.py:4388-4389

if self._should_load_db_object(object_type="model_cost_map"):
    await self._check_and_reload_model_cost_map(prisma_client=prisma_client)