Files
taiji-AI-PAD/Docs/项目文档/LiteLLM和AgentManager回调接口文档.md
T

534 lines
16 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.
# 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 消耗(1 EU = 10秒,不足10秒按1 EU计算)
- 根据 Agent 类型和运行时长计算成本(平台 Agent 使用 `calculate_platform_agent_cost`)
4. **查找现有记录**:
- 根据 `agentName` 和 `userId` 查找运行中的计费记录(`end_time == None`)
- **如果存在现有记录**: 更新该记录,只扣除增量成本(避免与周期计费重复扣款)
- **如果不存在记录**: 创建新记录,全额扣款(异常情况的兜底)
5. **计费记录内容**:
- 用户ID、渠道ID
- Agent 名称、类型
- 运行时长、EU消耗、成本
- 开始时间、结束时间
- 使用的工具列表
- 请求ID
6. **余额扣减**:
- 更新现有记录时:只扣除增量成本(新成本 - 已扣成本)
- 创建新记录时:全额扣款
7. **事务提交**: 所有操作在数据库事务中执行,失败时回滚
> **注意**: Agent 启动时会创建计费记录,周期计费任务会持续更新并增量扣款。
> 此回调接口负责结算最终费用,只扣除增量部分,避免重复扣款。
### 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 回调**: 通过 `agentName` + `userId` + `end_time == None` 实现幂等性
- 如果存在运行中的计费记录,则更新该记录而不是创建新记录
- 只扣除增量成本,避免与周期计费重复扣款
### 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 回调接口文档