forked from xiaohei/taiji-AI-PAD
14 KiB
14 KiB
模型供应商与租户模型使用设计方案(最终版 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 核心设计原则
- mcp-server 是业务规则制定者:决定谁能用什么、用多少
- litellm-gateway 是规则执行者:真正拦截超额请求
- Agent 与 litellm 解耦:Agent 只需要带正确的 api_key 调用
- 实时生效:配额更新、充值后立刻生效,无需重启
9.2 架构优势
| 优势 | 说明 |
|---|---|
| 职责清晰 | mcp-server 管业务,litellm 管执行 |
| 延迟低 | Agent 直接调用 litellm,无需代理 |
| 原生能力 | 充分利用 litellm 的配额和计费能力 |
| 易扩展 | 新增模型只需配置 litellm |
| 实时生效 | 配额更新无需重启 |