Files
taiji-AI-PAD/plans/模型供应商与租户模型使用设计方案.md
T
2026-01-07 10:46:55 +00:00

14 KiB
Raw Blame History

模型供应商与租户模型使用设计方案(最终版 v5.0)

版本: v5.0.0 创建时间: 2026-01-07 状态: 待评审


1. 核心职责分工

1.1 职责划分表

职责 负责方 说明
决定租户能用哪些模型 mcp-server 业务规则制定者
决定 RPM/TPM/Budget 数值 mcp-server 配额分配
真正拦截超额请求 litellm-gateway 规则执行者
管理 Agent 生命周期 mcp-server + Agent Manager 与 litellm 解耦
用量统计和计费 litellm-gateway 原生能力

1.2 概念映射

平台概念 LiteLLM 对应 说明
渠道 team 一个渠道 = 一个 team
租户 team 下的 key 或子 team 租户归属于渠道
模型供应商 model/provider litellm 配置
平台 Agent 不进 LiteLLM mcp-server 自己管理

1.3 LiteLLM 不关心的事情

  • ❌ Agent 是什么
  • ❌ Agent 从哪来
  • ❌ Agent 跑在 AKS 还是别的地方
  • ❌ Agent 生命周期

LiteLLM 只看请求里的:

  • ✅ api_key
  • ✅ team
  • ✅ model

2. 整体架构

2.1 架构图

graph TB
    subgraph mcp-server[mcp-server 业务规则制定者]
        A1[管理员创建渠道]
        A2[分配模型供应商给渠道]
        A3[渠道分配模型给租户]
        A4[设置 RPM/TPM/Budget]
        A5[用户充值更新额度]
    end
    
    subgraph litellm[litellm-gateway 规则执行者]
        B1[team 管理]
        B2[key 管理]
        B3[rate_limit 检查]
        B4[budget 检查]
        B5[用量统计]
    end
    
    subgraph agent[Agent 运行层 - 与 litellm 解耦]
        C1[Agent Manager]
        C2[AKS Pod]
        C3[调用模型]
    end
    
    A1 --> |创建 team| B1
    A3 --> |创建 key + 配额| B2
    A4 --> |设置 rate_limit| B3
    A5 --> |更新 budget| B4
    
    C2 --> |带 api_key 请求| litellm
    litellm --> |检查配额| B3
    litellm --> |检查余额| B4
    litellm --> |转发| Provider[Azure/Gemini]

2.2 核心流程

sequenceDiagram
    participant Admin as 管理员
    participant MCP as mcp-server
    participant LiteLLM as litellm-gateway
    participant Agent as Agent Pod
    participant Azure as Azure/Gemini
    
    Note over Admin,Azure: 1️⃣ 创建渠道
    Admin->>MCP: 创建渠道
    MCP->>LiteLLM: POST /team/new
    Note over MCP,LiteLLM: team_alias: channel-xxx
    
    Note over Admin,Azure: 2️⃣ 分配模型给渠道
    Admin->>MCP: 分配模型 azure/gpt-4
    MCP->>MCP: 记录到 ResourceAllocation
    
    Note over Admin,Azure: 3️⃣ 渠道分配模型给租户
    MCP->>LiteLLM: POST /key/generate
    Note over MCP,LiteLLM: team_id, models, rpm_limit, tpm_limit, max_budget
    LiteLLM-->>MCP: 返回 api_key
    MCP->>MCP: 保存 key 到数据库
    
    Note over Admin,Azure: 4️⃣ 租户创建 Agent
    MCP->>MCP: 查询租户的 api_key
    MCP->>Agent: 启动 Pod,注入 api_key
    
    Note over Admin,Azure: 5️⃣ Agent 调用模型
    Agent->>LiteLLM: POST /chat/completions
    Note over Agent,LiteLLM: Authorization: Bearer api_key
    LiteLLM->>LiteLLM: 检查 RPM/TPM
    LiteLLM->>LiteLLM: 检查 Budget
    
    alt 配额/余额不足
        LiteLLM-->>Agent: 429/403 拒绝
    else 配额充足
        LiteLLM->>Azure: 转发请求
        Azure-->>LiteLLM: 返回结果
        LiteLLM->>LiteLLM: 记录用量
        LiteLLM-->>Agent: 返回结果
    end
    
    Note over Admin,Azure: 6️⃣ 用户充值
    MCP->>LiteLLM: POST /key/update
    Note over MCP,LiteLLM: 更新 max_budget
    Note over MCP,LiteLLM: 下一次请求立刻放行,无需重启

3. 详细设计

3.1 创建渠道(对应 LiteLLM team)

mcp-server 操作:

async def create_channel(channel_name: str, db: AsyncSession):
    # 1. 在 mcp-server 创建渠道记录
    channel = Channel(name=channel_name, ...)
    db.add(channel)
    
    # 2. 在 litellm 创建对应的 team
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{settings.litellm_url}/team/new",
            json={
                "team_alias": f"channel-{channel.id}",
                "metadata": {
                    "channel_id": str(channel.id),
                    "channel_name": channel_name
                }
            },
            headers={"Authorization": f"Bearer {settings.litellm_master_key}"}
        )
        data = response.json()
        
        # 保存 litellm team_id
        channel.litellm_team_id = data["team_id"]
    
    await db.commit()
    return channel

3.2 分配模型给渠道

mcp-server 操作:

async def allocate_models_to_channel(
    channel_id: str,
    models: list[str],  # ["azure/gpt-4", "gemini/gemini-pro"]
    db: AsyncSession
):
    # 只在 mcp-server 记录,不需要同步到 litellm
    # litellm 的 team 不限制模型,模型限制在 key 级别
    for model in models:
        allocation = ResourceAllocation(
            target_id=channel_id,
            target_type="channel",
            resource_type="model",
            resource_id=model
        )
        db.add(allocation)
    
    await db.commit()

3.3 渠道分配模型给租户(核心)

mcp-server 操作:

async def allocate_model_to_tenant(
    tenant_id: str,
    channel_id: str,
    model_name: str,
    rpm_limit: int,
    tpm_limit: int,
    max_budget: float,
    db: AsyncSession
):
    # 1. 验证渠道是否有该模型
    channel_has_model = await check_channel_has_model(channel_id, model_name, db)
    if not channel_has_model:
        raise HTTPException(status_code=403, detail="渠道没有该模型的权限")
    
    # 2. 获取渠道的 litellm team_id
    channel = await get_channel(channel_id, db)
    
    # 3. 在 litellm 创建 key(绑定 team + model + 配额)
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{settings.litellm_url}/key/generate",
            json={
                "team_id": channel.litellm_team_id,
                "models": [model_name],
                "rpm_limit": rpm_limit,
                "tpm_limit": tpm_limit,
                "max_budget": max_budget,
                "budget_duration": "monthly",  # 或 "total"
                "metadata": {
                    "tenant_id": str(tenant_id),
                    "channel_id": str(channel_id),
                    "model": model_name
                }
            },
            headers={"Authorization": f"Bearer {settings.litellm_master_key}"}
        )
        data = response.json()
    
    # 4. 保存到数据库
    tenant_key = TenantModelKey(
        tenant_id=tenant_id,
        channel_id=channel_id,
        model_name=model_name,
        litellm_key_id=data["key"],
        litellm_key_hash=encrypt(data["key"]),  # 加密存储
        rpm_limit=rpm_limit,
        tpm_limit=tpm_limit,
        max_budget=max_budget
    )
    db.add(tenant_key)
    
    # 5. 同时记录到 ResourceAllocation
    allocation = ResourceAllocation(
        target_id=tenant_id,
        target_type="tenant",
        resource_type="model",
        resource_id=model_name,
        rpm=rpm_limit,
        tpm=tpm_limit
    )
    db.add(allocation)
    
    await db.commit()
    return tenant_key

3.4 租户创建 Agent

mcp-server 操作:

async def create_custom_agent(
    tenant_id: str,
    agent_name: str,
    model_name: str,
    cpu_request: str,
    memory_request: str,
    db: AsyncSession
):
    # 1. 查询租户的模型 key
    tenant_key = await db.execute(
        select(TenantModelKey).where(
            and_(
                TenantModelKey.tenant_id == tenant_id,
                TenantModelKey.model_name == model_name,
                TenantModelKey.status == "active"
            )
        )
    )
    tenant_key = tenant_key.scalar_one_or_none()
    
    if not tenant_key:
        raise HTTPException(
            status_code=403,
            detail=f"您没有使用模型 {model_name} 的权限"
        )
    
    # 2. 调用 Agent Manager 创建 Pod
    # Agent Manager 不需要知道 litellm 的任何细节
    # 只需要注入环境变量
    result = await agent_manager.create_agent(
        name=agent_name,
        cpu_request=cpu_request,
        memory_request=memory_request,
        env_vars={
            "OPENAI_API_BASE": settings.litellm_url,
            "OPENAI_API_KEY": decrypt(tenant_key.litellm_key_hash),
            "MODEL_NAME": model_name
        }
    )
    
    return result

3.5 用户充值更新额度

mcp-server 操作:

async def recharge_tenant_budget(
    tenant_id: str,
    model_name: str,
    additional_budget: float,
    db: AsyncSession
):
    # 1. 获取租户的 key
    tenant_key = await get_tenant_model_key(tenant_id, model_name, db)
    
    # 2. 计算新的 budget
    new_budget = float(tenant_key.max_budget or 0) + additional_budget
    
    # 3. 更新 litellm key 的 budget
    async with httpx.AsyncClient() as client:
        await client.post(
            f"{settings.litellm_url}/key/update",
            json={
                "key": tenant_key.litellm_key_id,
                "max_budget": new_budget
            },
            headers={"Authorization": f"Bearer {settings.litellm_master_key}"}
        )
    
    # 4. 更新数据库
    tenant_key.max_budget = new_budget
    await db.commit()
    
    # ✅ 下一次请求立刻放行,无需重启任何服务

4. 数据模型

4.1 新增表:TenantModelKey

CREATE TABLE tenant_model_keys (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id UUID NOT NULL REFERENCES users(id),
    channel_id UUID REFERENCES channels(id),
    
    -- 模型信息
    model_name VARCHAR(100) NOT NULL,
    
    -- litellm Key 信息
    litellm_key_id VARCHAR(255) NOT NULL,  -- litellm 返回的完整 key
    litellm_key_hash TEXT NOT NULL,         -- 加密存储
    
    -- 配额配置(与 litellm 同步)
    rpm_limit INTEGER DEFAULT 0,
    tpm_limit INTEGER DEFAULT 0,
    max_budget NUMERIC(12, 2),
    budget_duration VARCHAR(20) DEFAULT 'monthly',
    
    -- 状态
    status VARCHAR(20) DEFAULT 'active',
    
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    
    UNIQUE(tenant_id, model_name)
);

4.2 Channel 表增加字段

ALTER TABLE channels ADD COLUMN litellm_team_id VARCHAR(100);

5. LiteLLM 配置

5.1 litellm_config.yaml

general_settings:
  master_key: "sk-taiji-master-key"
  database_url: "postgresql://..."  # 可选,用于持久化
  
model_list:
  # Azure GPT-4
  - model_name: "azure/gpt-4"
    litellm_params:
      model: "azure/gpt-4"
      api_base: "https://taiji-azure.openai.azure.com"
      api_key: "os.environ/AZURE_API_KEY"
      api_version: "2024-02-15-preview"
      
  # Azure GPT-3.5
  - model_name: "azure/gpt-35-turbo"
    litellm_params:
      model: "azure/gpt-35-turbo"
      api_base: "https://taiji-azure.openai.azure.com"
      api_key: "os.environ/AZURE_API_KEY"
      api_version: "2024-02-15-preview"
      
  # Google Gemini
  - model_name: "gemini/gemini-pro"
    litellm_params:
      model: "gemini/gemini-pro"
      api_key: "os.environ/GOOGLE_API_KEY"

# 启用用量追踪
litellm_settings:
  success_callback: ["prometheus"]
  track_cost_callback: true

5.2 LiteLLM Admin API 使用

API 用途 调用时机
POST /team/new 创建 team 创建渠道时
POST /key/generate 创建 key 分配模型给租户时
POST /key/update 更新 key 配额 修改配额/充值时
POST /key/delete 删除 key 取消分配时
GET /spend/logs 查询用量 统计报表时

6. 接口设计

6.1 渠道管理接口

接口 方法 功能 变更
POST /api/admin/channels/create POST 创建渠道 同步创建 litellm team
DELETE /api/admin/channels/{id} DELETE 删除渠道 同步删除 litellm team

6.2 模型分配接口

接口 方法 功能 变更
PUT /api/channel/tenants/{id}/models PUT 分配模型给租户 创建 litellm key
DELETE /api/channel/tenants/{id}/models/{model} DELETE 取消分配 删除 litellm key
PUT /api/channel/tenants/{id}/models/{model}/quota PUT 更新配额 更新 litellm key

6.3 租户接口

接口 方法 功能
GET /api/user/models/available GET 获取可用模型列表
POST /api/user/custom-agents POST 创建 Agent(注入 key)
GET /api/user/models/usage/stats GET 查询用量统计
POST /api/user/billing/recharge POST 充值(更新 litellm budget)

7. 实现计划

7.1 任务清单

  • 数据库迁移

    • 创建 tenant_model_keys 表
    • Channel 表增加 litellm_team_id 字段
  • litellm 集成

    • 实现 litellm Admin API 客户端
    • 创建渠道时同步创建 team
    • 分配模型时创建 key
    • 充值时更新 budget
  • 接口调整

    • 更新渠道创建接口
    • 实现模型分配接口
    • 更新 Agent 创建接口
    • 实现充值接口
  • Agent Manager

    • 支持注入 litellm key 环境变量

8. 关键行为说明

8.1 配额超限行为

状态 LiteLLM 行为 说明
RPM 超限 返回 429 等待下一分钟自动恢复
TPM 超限 返回 429 等待下一分钟自动恢复
Budget 用完 返回 403 需要充值才能恢复

8.2 充值后恢复

用户充值 → mcp-server 调用 litellm API 更新 budget → 下一次请求立刻放行
  • ✅ 不需要重启任何服务
  • ✅ 不需要重新创建 key
  • ✅ 实时生效

9. 总结

9.1 核心设计原则

  1. mcp-server 是业务规则制定者:决定谁能用什么、用多少
  2. litellm-gateway 是规则执行者:真正拦截超额请求
  3. Agent 与 litellm 解耦:Agent 只需要带正确的 api_key 调用
  4. 实时生效:配额更新、充值后立刻生效,无需重启

9.2 架构优势

优势 说明
职责清晰 mcp-server 管业务,litellm 管执行
延迟低 Agent 直接调用 litellm,无需代理
原生能力 充分利用 litellm 的配额和计费能力
易扩展 新增模型只需配置 litellm
实时生效 配额更新无需重启