new version
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
# LiteLLM 和 Agent Manager 回调接口文档
|
||||
|
||||
## 概述
|
||||
|
||||
本文档描述了 mcp-server 接收 LiteLLM 和 Agent Manager 服务的回调接口规范,包括请求体格式、响应体格式以及处理逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 1. LiteLLM 回调接口
|
||||
|
||||
### 1.1 接口信息
|
||||
|
||||
- **接口路径**: `/api/v1/billing/litellm-callback`
|
||||
- **请求方法**: `POST`
|
||||
- **Content-Type**: `application/json`
|
||||
- **功能**: 接收 LiteLLM 的实时 Token 计费数据,支持单个对象或批量数组格式
|
||||
|
||||
### 1.2 请求体格式
|
||||
|
||||
#### 1.2.1 单个对象格式
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "call-abc123", // 必填:调用ID(别名:call_id)
|
||||
"trace_id": "trace-xyz789", // 可选:追踪ID
|
||||
"model": "gpt-4", // 必填:模型名称
|
||||
"call_type": "completion", // 可选:调用类型
|
||||
"cache_hit": false, // 可选:是否缓存命中
|
||||
"stream": false, // 可选:是否流式响应
|
||||
"status": "success", // 可选:状态(默认:success)
|
||||
"custom_llm_provider": "openai", // 可选:LLM提供商
|
||||
"startTime": "2026-01-11T10:00:00Z", // 可选:开始时间(ISO 8601 或 Unix 时间戳)
|
||||
"endTime": "2026-01-11T10:00:05Z", // 可选:结束时间(ISO 8601 或 Unix 时间戳)
|
||||
"response_time": 5.2, // 可选:响应时间(秒)
|
||||
"response_cost": 0.001, // 可选:响应成本(美元)
|
||||
"total_tokens": 1500, // 可选:总Token数
|
||||
"prompt_tokens": 1000, // 可选:Prompt Token数
|
||||
"completion_tokens": 500, // 可选:Completion Token数
|
||||
"api_key": "sk-xxx", // 可选:API密钥
|
||||
"team_id": "team-123", // 可选:团队ID
|
||||
"api_base": "https://api.openai.com", // 可选:API基础URL
|
||||
"model_group": "gpt-4", // 可选:模型组
|
||||
"model_id": "gpt-4-0613", // 可选:模型ID
|
||||
"messages": [ // 可选:消息列表
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Hello"
|
||||
}
|
||||
],
|
||||
"response": { // 可选:响应内容
|
||||
"choices": [...]
|
||||
},
|
||||
"metadata": { // 可选:元数据(重要:包含租户信息)
|
||||
"user_api_key_hash": "hash-xxx", // API密钥哈希
|
||||
"user_api_key_team_id": "team-123", // 团队ID
|
||||
"user_api_key_auth_metadata": { // 租户认证元数据(优先使用)
|
||||
"tenant_id": "tenant-123",
|
||||
"channel_id": "channel-456",
|
||||
"tenant_name": "租户名称"
|
||||
},
|
||||
"usage_object": { // Token使用量对象
|
||||
"total_tokens": 1500,
|
||||
"prompt_tokens": 1000,
|
||||
"completion_tokens": 500
|
||||
}
|
||||
},
|
||||
"hidden_params": {}, // 可选:隐藏参数
|
||||
"model_map_information": {}, // 可选:模型映射信息
|
||||
"cost_breakdown": {}, // 可选:成本明细
|
||||
"error_str": null, // 可选:错误信息
|
||||
"error_information": {} // 可选:错误详情
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2.2 批量数组格式
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "call-abc123",
|
||||
"model": "gpt-4",
|
||||
"total_tokens": 1500,
|
||||
"metadata": {
|
||||
"user_api_key_auth_metadata": {
|
||||
"tenant_id": "tenant-123",
|
||||
"channel_id": "channel-456"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "call-xyz789",
|
||||
"model": "gpt-3.5-turbo",
|
||||
"total_tokens": 800,
|
||||
"metadata": {
|
||||
"user_api_key_auth_metadata": {
|
||||
"tenant_id": "tenant-123",
|
||||
"channel_id": "channel-456"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### 1.2.3 字段说明
|
||||
|
||||
| 字段名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| `id` / `call_id` | string | 是 | 调用唯一标识符,用于幂等性检查 |
|
||||
| `trace_id` | string | 否 | 追踪ID,当 `id` 不存在时作为备用 |
|
||||
| `model` | string | 是 | 模型名称(如:gpt-4, gpt-3.5-turbo) |
|
||||
| `total_tokens` | integer | 否 | 总Token数,用于计算EU消耗 |
|
||||
| `prompt_tokens` | integer | 否 | Prompt Token数 |
|
||||
| `completion_tokens` | integer | 否 | Completion Token数 |
|
||||
| `startTime` | string/float | 否 | 开始时间(ISO 8601 字符串或 Unix 时间戳) |
|
||||
| `endTime` | string/float | 否 | 结束时间(ISO 8601 字符串或 Unix 时间戳) |
|
||||
| `response_cost` | float | 否 | 响应成本(美元) |
|
||||
| `metadata` | object | 否 | 元数据对象,包含租户信息 |
|
||||
| `metadata.user_api_key_hash` | string | 否 | API密钥哈希值 |
|
||||
| `metadata.user_api_key_team_id` | string | 否 | 团队ID |
|
||||
| `metadata.user_api_key_auth_metadata` | object | 否 | **优先使用**:租户认证元数据 |
|
||||
| `metadata.user_api_key_auth_metadata.tenant_id` | string | 否 | 租户ID |
|
||||
| `metadata.user_api_key_auth_metadata.channel_id` | string | 否 | 渠道ID |
|
||||
| `metadata.usage_object` | object | 否 | Token使用量对象(备用) |
|
||||
|
||||
### 1.3 响应体格式
|
||||
|
||||
#### 1.3.1 单个对象响应
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Success",
|
||||
"call_id": "call-abc123",
|
||||
"record_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"eu_consumed": 0.15,
|
||||
"balance_updated": true
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3.2 批量数组响应
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Batch processed",
|
||||
"count": 2,
|
||||
"results": [
|
||||
{
|
||||
"message": "Success",
|
||||
"call_id": "call-abc123",
|
||||
"record_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"eu_consumed": 0.15,
|
||||
"balance_updated": true
|
||||
},
|
||||
{
|
||||
"message": "Success",
|
||||
"call_id": "call-xyz789",
|
||||
"record_id": "550e8400-e29b-41d4-a716-446655440001",
|
||||
"eu_consumed": 0.08,
|
||||
"balance_updated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3.3 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
"detail": "无法解析租户ID"
|
||||
}
|
||||
```
|
||||
|
||||
**HTTP 状态码**:
|
||||
- `200`: 成功处理
|
||||
- `400`: 请求参数错误(如无法解析租户ID)
|
||||
- `500`: 服务器内部错误
|
||||
|
||||
#### 1.3.4 响应字段说明
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `message` | string | 处理结果消息("Success" / "Already processed" / "Skipped - no call_id") |
|
||||
| `call_id` | string | 调用ID |
|
||||
| `record_id` | string | 计费记录ID(UUID) |
|
||||
| `eu_consumed` | float | 消耗的EU数量 |
|
||||
| `balance_updated` | boolean | 是否成功更新余额 |
|
||||
|
||||
### 1.4 处理逻辑
|
||||
|
||||
1. **幂等性检查**: 根据 `call_id` 检查是否已处理过,避免重复计费
|
||||
2. **租户信息解析**:
|
||||
- 优先从 `metadata.user_api_key_auth_metadata` 获取租户信息
|
||||
- 如果不存在,则通过 `metadata.user_api_key_hash` 从数据库查询
|
||||
3. **Token计算**:
|
||||
- 优先使用顶级字段 `total_tokens`、`prompt_tokens`、`completion_tokens`
|
||||
- 如果不存在,从 `metadata.usage_object` 获取
|
||||
4. **EU计算**: 根据模型类型和Token数量计算EU消耗
|
||||
- GPT-4: 0.0001 EU/token
|
||||
- GPT-3.5-turbo: 0.00005 EU/token
|
||||
- 默认: 0.0001 EU/token
|
||||
5. **余额扣减**: 使用数据库行锁确保并发安全,原子性更新用户余额
|
||||
6. **计费记录**: 创建 `ModelBillingRecord` 记录,保存完整的回调数据
|
||||
|
||||
### 1.5 健康检查接口
|
||||
|
||||
- **接口路径**: `/api/v1/billing/litellm-callback/health`
|
||||
- **请求方法**: `GET`
|
||||
- **响应**:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"endpoint": "/api/v1/billing/litellm-callback"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Agent Manager 回调接口
|
||||
|
||||
### 2.1 接口信息
|
||||
|
||||
- **接口路径**: `/api/v1/billing/agent-callback`
|
||||
- **请求方法**: `POST`
|
||||
- **Content-Type**: `application/json`
|
||||
- **功能**: 接收 Agent Manager 的 Agent 运行时信息,用于记录运行时长并计费
|
||||
|
||||
### 2.2 请求体格式
|
||||
|
||||
```json
|
||||
{
|
||||
"agentName": "taiji-assistant-abc123", // 必填:Agent 名称
|
||||
"userId": "user-123-456", // 必填:用户 ID
|
||||
"podRunningTimeSeconds": 120, // 必填:Pod 运行时间(秒),即 VM 运行时间
|
||||
"toolsUsed": [ // 可选:使用的工具列表
|
||||
"web_search",
|
||||
"calculator",
|
||||
"file_reader"
|
||||
],
|
||||
"startTime": "2026-01-11T10:00:00Z", // 可选:开始时间(ISO 8601 格式)
|
||||
"endTime": "2026-01-11T10:02:00Z", // 可选:结束时间(ISO 8601 格式)
|
||||
"requestId": "req-abc-123" // 可选:请求 ID
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 请求字段说明
|
||||
|
||||
| 字段名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| `agentName` | string | 是 | Agent 名称,用于标识具体的 Agent 实例 |
|
||||
| `userId` | string | 是 | 用户 ID,必须是系统中存在的用户 |
|
||||
| `podRunningTimeSeconds` | integer | 是 | Pod 运行时间(秒),即 VM 实际运行时长,用于计费 |
|
||||
| `toolsUsed` | array[string] | 否 | 使用的工具列表,用于记录 Agent 调用的工具 |
|
||||
| `startTime` | string | 否 | 开始时间,ISO 8601 格式(如:2026-01-11T10:00:00Z) |
|
||||
| `endTime` | string | 否 | 结束时间,ISO 8601 格式(如:2026-01-11T10:02:00Z) |
|
||||
| `requestId` | string | 否 | 请求 ID,用于追踪和关联请求 |
|
||||
|
||||
### 2.4 响应体格式
|
||||
|
||||
#### 2.4.1 成功响应
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Agent 计费记录创建成功",
|
||||
"recordId": "550e8400-e29b-41d4-a716-446655440000"
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.4.2 错误响应
|
||||
|
||||
**用户不存在**:
|
||||
```json
|
||||
{
|
||||
"detail": "用户不存在: user-123-456"
|
||||
}
|
||||
```
|
||||
HTTP 状态码: `404`
|
||||
|
||||
**服务器错误**:
|
||||
```json
|
||||
{
|
||||
"detail": "回调处理失败: [错误详情]"
|
||||
}
|
||||
```
|
||||
HTTP 状态码: `500`
|
||||
|
||||
#### 2.4.3 响应字段说明
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| `success` | boolean | 是否成功处理 |
|
||||
| `message` | string | 处理结果消息 |
|
||||
| `recordId` | string | 创建的计费记录ID(UUID),失败时为 null |
|
||||
|
||||
### 2.5 处理逻辑
|
||||
|
||||
1. **用户验证**: 验证 `userId` 是否存在,不存在则返回 404 错误
|
||||
2. **时间解析**: 解析 `startTime` 和 `endTime`(ISO 8601 格式),转换为 UTC 时间
|
||||
3. **成本计算**:
|
||||
- 根据 `podRunningTimeSeconds` 计算 EU 消耗
|
||||
- 根据 Agent 类型和运行时长计算成本(平台 Agent 使用 `calculate_platform_agent_cost`)
|
||||
4. **计费记录**: 创建 `AgentBillingRecord` 记录,包含:
|
||||
- 用户ID、渠道ID
|
||||
- Agent 名称、类型
|
||||
- 运行时长、EU消耗、成本
|
||||
- 开始时间、结束时间
|
||||
- 使用的工具列表
|
||||
- 请求ID
|
||||
5. **余额扣减**: 调用 `deduct_balance` 扣除用户余额
|
||||
6. **事务提交**: 所有操作在数据库事务中执行,失败时回滚
|
||||
|
||||
### 2.6 健康检查接口
|
||||
|
||||
- **接口路径**: `/api/v1/billing/agent-callback/health`
|
||||
- **请求方法**: `GET`
|
||||
- **响应**:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"endpoint": "/api/v1/billing/agent-callback"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 通用说明
|
||||
|
||||
### 3.1 认证
|
||||
|
||||
目前两个回调接口均未实现认证机制,建议在生产环境中添加:
|
||||
- API Key 认证
|
||||
- IP 白名单
|
||||
- 签名验证
|
||||
|
||||
### 3.2 幂等性
|
||||
|
||||
- **LiteLLM 回调**: 通过 `call_id` 实现幂等性,相同 `call_id` 的请求只会处理一次
|
||||
- **Agent Manager 回调**: 目前未实现幂等性,建议添加 `requestId` 的唯一性检查
|
||||
|
||||
### 3.3 错误处理
|
||||
|
||||
- 所有错误都会记录到日志中
|
||||
- 数据库操作失败时会自动回滚事务
|
||||
- 返回适当的 HTTP 状态码和错误信息
|
||||
|
||||
### 3.4 性能考虑
|
||||
|
||||
- LiteLLM 回调支持批量处理,提高吞吐量
|
||||
- 使用数据库行锁确保并发安全
|
||||
- 余额更新使用原子操作
|
||||
|
||||
### 3.5 数据存储
|
||||
|
||||
- **LiteLLM 回调**: 数据存储在 `ModelBillingRecord` 表中
|
||||
- **Agent Manager 回调**: 数据存储在 `AgentBillingRecord` 表中
|
||||
- 所有回调的原始数据都会保存,便于后续审计和分析
|
||||
|
||||
---
|
||||
|
||||
## 4. 示例代码
|
||||
|
||||
### 4.1 LiteLLM 回调示例(cURL)
|
||||
|
||||
```bash
|
||||
# 单个对象
|
||||
curl -X POST http://mcp-server:8002/api/v1/billing/litellm-callback \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"id": "call-abc123",
|
||||
"model": "gpt-4",
|
||||
"total_tokens": 1500,
|
||||
"prompt_tokens": 1000,
|
||||
"completion_tokens": 500,
|
||||
"metadata": {
|
||||
"user_api_key_auth_metadata": {
|
||||
"tenant_id": "tenant-123",
|
||||
"channel_id": "channel-456"
|
||||
}
|
||||
}
|
||||
}'
|
||||
|
||||
# 批量数组
|
||||
curl -X POST http://mcp-server:8002/api/v1/billing/litellm-callback \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '[
|
||||
{
|
||||
"id": "call-abc123",
|
||||
"model": "gpt-4",
|
||||
"total_tokens": 1500,
|
||||
"metadata": {
|
||||
"user_api_key_auth_metadata": {
|
||||
"tenant_id": "tenant-123",
|
||||
"channel_id": "channel-456"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "call-xyz789",
|
||||
"model": "gpt-3.5-turbo",
|
||||
"total_tokens": 800,
|
||||
"metadata": {
|
||||
"user_api_key_auth_metadata": {
|
||||
"tenant_id": "tenant-123",
|
||||
"channel_id": "channel-456"
|
||||
}
|
||||
}
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
### 4.2 Agent Manager 回调示例(cURL)
|
||||
|
||||
```bash
|
||||
curl -X POST http://mcp-server:8002/api/v1/billing/agent-callback \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"agentName": "taiji-assistant-abc123",
|
||||
"userId": "user-123-456",
|
||||
"podRunningTimeSeconds": 120,
|
||||
"toolsUsed": ["web_search", "calculator"],
|
||||
"startTime": "2026-01-11T10:00:00Z",
|
||||
"endTime": "2026-01-11T10:02:00Z",
|
||||
"requestId": "req-abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
### 4.3 Python 示例
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
# LiteLLM 回调
|
||||
litellm_data = {
|
||||
"id": "call-abc123",
|
||||
"model": "gpt-4",
|
||||
"total_tokens": 1500,
|
||||
"metadata": {
|
||||
"user_api_key_auth_metadata": {
|
||||
"tenant_id": "tenant-123",
|
||||
"channel_id": "channel-456"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
"http://mcp-server:8002/api/v1/billing/litellm-callback",
|
||||
json=litellm_data
|
||||
)
|
||||
print(response.json())
|
||||
|
||||
# Agent Manager 回调
|
||||
agent_data = {
|
||||
"agentName": "taiji-assistant-abc123",
|
||||
"userId": "user-123-456",
|
||||
"podRunningTimeSeconds": 120,
|
||||
"toolsUsed": ["web_search", "calculator"],
|
||||
"startTime": "2026-01-11T10:00:00Z",
|
||||
"endTime": "2026-01-11T10:02:00Z",
|
||||
"requestId": "req-abc-123"
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
"http://mcp-server:8002/api/v1/billing/agent-callback",
|
||||
json=agent_data
|
||||
)
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 配置说明
|
||||
|
||||
### 5.1 LiteLLM 配置
|
||||
|
||||
在 LiteLLM 配置文件中设置回调地址:
|
||||
|
||||
```yaml
|
||||
general_settings:
|
||||
success_callback: ["webhook"]
|
||||
failure_callback: ["webhook"]
|
||||
webhook_url: "http://mcp-server:8002/api/v1/billing/litellm-callback"
|
||||
webhook_headers:
|
||||
Content-Type: "application/json"
|
||||
```
|
||||
|
||||
### 5.2 Agent Manager 配置
|
||||
|
||||
Agent Manager 需要在 Agent 运行结束后调用回调接口,配置回调地址:
|
||||
|
||||
```
|
||||
CALLBACK_URL=http://mcp-server:8002/api/v1/billing/agent-callback
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 注意事项
|
||||
|
||||
1. **时间格式**:
|
||||
- LiteLLM 回调支持 ISO 8601 字符串和 Unix 时间戳
|
||||
- Agent Manager 回调仅支持 ISO 8601 格式
|
||||
|
||||
2. **租户信息**:
|
||||
- LiteLLM 回调优先从 `metadata.user_api_key_auth_metadata` 获取租户信息
|
||||
- 如果不存在,会尝试从数据库查询,但可能失败
|
||||
|
||||
3. **Token 计算**:
|
||||
- 优先使用顶级字段,其次使用 `metadata.usage_object`
|
||||
- 如果都不存在,Token 数默认为 0
|
||||
|
||||
4. **并发安全**:
|
||||
- 使用数据库行锁确保余额更新的原子性
|
||||
- 建议在生产环境中使用连接池和适当的并发控制
|
||||
|
||||
5. **日志记录**:
|
||||
- 所有回调都会记录详细日志
|
||||
- 建议配置日志轮转和监控告警
|
||||
|
||||
---
|
||||
|
||||
## 7. 更新日志
|
||||
|
||||
- **2026-01-11**: 初始版本,包含 LiteLLM 和 Agent Manager 回调接口文档
|
||||
|
||||
Reference in New Issue
Block a user