Files
taiji-AI-PAD/Docs/项目文档/计费管理三维度接口文档.md
2026-03-10 06:40:38 +00:00

9.5 KiB
Raw Permalink Blame History

计费管理三维度接口文档

接口信息

接口路径: GET /api/admin/billing/overview

功能: 获取计费管理三维度统计数据(渠道维度、租户维度、调用记录)

认证: 需要 Bearer Token

权限: 管理员角色(super_admin、billing_admin、operations_admin)


请求参数

参数 类型 必填 说明
startTime string ✅ 开始时间,ISO 8601格式,如 2026-03-01T00:00:00Z
endTime string ✅ 结束时间,ISO 8601格式,如 2026-03-31T23:59:59Z
channelName string ❌ 渠道名称筛选
tenantName string ❌ 租户名称筛选
minCalls int ❌ 最小调用次数筛选
maxCalls int ❌ 最大调用次数筛选
export string ❌ 导出格式:excel、csv、pdf

响应数据结构

{
  "success": true,
  "data": {
    "channelStats": [...],
    "tenantStats": [...],
    "callRecords": [...]
  }
}

一、渠道维度 (channelStats)

数据结构

{
  "channelStats": [
    {
      "channelId": "550e8400-e29b-41d4-a716-446655440001",
      "channelName": "渠道A",
      "calls": 1500,
      "totalEU": 7500.0,
      "totalCost": 750.00
    },
    {
      "channelId": "550e8400-e29b-41d4-a716-446655440002",
      "channelName": "渠道B",
      "calls": 800,
      "totalEU": 4000.0,
      "totalCost": 400.00
    }
  ]
}

字段说明

字段 类型 说明
channelId string 渠道ID(UUID)
channelName string 渠道名称
calls int 调用次数
totalEU float 总EU消耗
totalCost float 渠道总价(USD)

前端汇总计算

// 渠道总数
const channelCount = channelStats.length;

// 总计费额
const totalCost = channelStats.reduce((sum, c) => sum + c.totalCost, 0);

// 总EU消耗
const totalEU = channelStats.reduce((sum, c) => sum + c.totalEU, 0);

二、租户维度 (tenantStats)

数据结构

{
  "tenantStats": [
    {
      "tenantId": "b0d02105-55f8-41a7-b09a-bba8f49a9d62",
      "tenantName": "xiaohei",
      "channelName": "66",
      "calls": 84,
      "totalEU": 44197.14,
      "totalCost": 12.2905,
      "avgCost": 0.1463
    },
    {
      "tenantId": "6b49508d-9c2c-4eac-99e1-c36263fd1699",
      "tenantName": "cccccccc",
      "channelName": "66",
      "calls": 2,
      "totalEU": 18.0,
      "totalCost": 0.0046,
      "avgCost": 0.0023
    }
  ]
}

字段说明

字段 类型 说明
tenantId string 租户ID(UUID)
tenantName string 租户名称
channelName string 所属渠道名称(无渠道时显示"无渠道")
calls int 调用次数(Agent使用 + 模型调用)
totalEU float 总EU消耗
totalCost float 用户总价(USD)
avgCost float 平均消费(totalCost / calls)

前端汇总计算

// 租户总数
const tenantCount = tenantStats.length;

// 用户总价
const userTotalCost = tenantStats.reduce((sum, t) => sum + t.totalCost, 0);

// 平均消费
const avgCost = tenantCount > 0 ? userTotalCost / tenantCount : 0;

三、调用记录 (callRecords)

调用记录包含两种类型:

  • agent: Agent 使用记录(来自 AgentBillingRecord 表)
  • model: 模型调用记录(来自 ModelBillingRecord 表,LiteLLM 回调数据)

数据结构

{
  "callRecords": [
    {
      "id": "7d984099-534f-4b8b-a892-74dead3fd5fd",
      "type": "agent",
      "timestamp": "2026-03-09T07:05:41.118384",
      "channelName": "无渠道",
      "tenantName": "xiaohei",
      "agentName": "search-agent-b0d02105-21015e",
      "modelName": "taiji/claude-sonnet-4-5",
      "duration": 83430,
      "eu": 8343,
      "cost": 2.3175
    },
    {
      "id": "d69e4da8-0852-4e35-94dc-ee2bd584e9ca",
      "type": "model",
      "timestamp": "2026-03-05T16:02:47.186423",
      "channelName": "66",
      "tenantName": "xiaohei",
      "agentName": null,
      "modelName": "openrouter/nousresearch/hermes-3-llama-3.1-405b",
      "duration": 44.76,
      "eu": 0.3862,
      "cost": 0.003862,
      "inputTokens": 2932,
      "outputTokens": 930,
      "totalTokens": 3862
    }
  ]
}

字段说明

字段 类型 说明
id string 调用ID(UUID)
type string 记录类型:agent(Agent使用)或 model(模型调用)
timestamp string 时间戳(ISO 8601格式)
channelName string 渠道名称(无渠道时显示"无渠道")
tenantName string 租户名称
agentName string Agent名称(模型调用时为 null)
modelName string 模型名称(如 taiji/claude-sonnet-4-5)
duration float 时长(秒)- Agent为运行时长,模型为响应时间
eu float EU消耗
cost float 单次调用总价(USD)
inputTokens int 输入Token数(仅 type=model 时有值)
outputTokens int 输出Token数(仅 type=model 时有值)
totalTokens int 总Token数(仅 type=model 时有值)

EU计算规则

Agent 使用(type=agent):

1 EU = 10秒运行时间
不足10秒按1 EU计算

公式:EU = ceil(duration / 10)

示例:
- 5秒 → 1 EU
- 10秒 → 1 EU
- 15秒 → 2 EU
- 35秒 → 4 EU

模型调用(type=model):

EU 按 Token 数量计算
公式由 LiteLLM 回调提供

前端调用示例

请求示例

const response = await fetch(
  '/api/admin/billing/overview?' + new URLSearchParams({
    startTime: '2026-03-01T00:00:00Z',
    endTime: '2026-03-31T23:59:59Z'
  }),
  {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  }
);

const data = await response.json();

数据处理示例

if (data.success) {
  const { channelStats, tenantStats, callRecords } = data.data;
  
  // ========== 渠道维度汇总 ==========
  const channelSummary = {
    totalChannels: channelStats.length,
    totalCost: channelStats.reduce((sum, c) => sum + c.totalCost, 0),
    totalEU: channelStats.reduce((sum, c) => sum + c.totalEU, 0)
  };
  
  // ========== 租户维度汇总 ==========
  const tenantSummary = {
    totalTenants: tenantStats.length,
    userTotalCost: tenantStats.reduce((sum, t) => sum + t.totalCost, 0),
    avgCost: tenantStats.length > 0 
      ? tenantStats.reduce((sum, t) => sum + t.totalCost, 0) / tenantStats.length 
      : 0
  };
  
  // ========== 渠道计费详情表格数据 ==========
  const channelTableData = channelStats.map(c => ({
    渠道名称: c.channelName,
    调用次数: c.calls,
    总EU: c.totalEU,
    渠道总价: `$${c.totalCost.toFixed(2)}`
  }));
  
  // ========== 租户计费详情表格数据 ==========
  const tenantTableData = tenantStats.map(t => ({
    租户名称: t.tenantName,
    所属渠道: t.channelName,
    调用次数: t.calls,
    总EU: t.totalEU,
    用户总价: `$${t.totalCost.toFixed(2)}`
  }));
  
  // ========== 调用记录明细表格数据 ==========
  const callTableData = callRecords.map(r => ({
    调用ID: r.id,
    租户: r.tenantName,
    渠道: r.channelName,
    调用时间: r.agentName,
    '时长(秒)': r.duration,
    EU: r.eu,
    单次调用总价: `$${r.cost.toFixed(2)}`,
    时间戳: r.timestamp
  }));
}

前端页面字段映射

渠道维度卡片

前端显示 数据来源
渠道总数 channelStats.length
总计费额 channelStats.reduce((sum, c) => sum + c.totalCost, 0)
总EU消耗 channelStats.reduce((sum, c) => sum + c.totalEU, 0)

渠道计费详情表格

表头 字段
渠道名称 channelName
调用次数 calls
总EU totalEU
渠道总价 totalCost

租户维度卡片

前端显示 数据来源
租户总数 tenantStats.length
用户总价 tenantStats.reduce((sum, t) => sum + t.totalCost, 0)
平均消费 用户总价 / 租户总数

租户计费详情表格

表头 字段
租户名称 tenantName
所属渠道 channelName
调用次数 calls
总EU totalEU
用户总价 totalCost

调用记录明细表格

表头 字段
调用ID id
类型 type(agent/model)
租户 tenantName
渠道 channelName
Agent名称 agentName
模型名称 modelName
时长(秒) duration
EU eu
单次调用总价 cost
输入Token inputTokens(仅模型调用)
输出Token outputTokens(仅模型调用)
总Token totalTokens(仅模型调用)
时间戳 timestamp

数据来源说明

本接口从以下两个表聚合数据:

表名 说明 对应 type
AgentBillingRecord Agent 使用计费记录 agent
ModelBillingRecord 模型调用计费记录(LiteLLM 回调) model

注意事项

  1. 时间格式: 请求参数中的时间需要使用 ISO 8601 格式
  2. 金额单位: 所有金额字段单位为 USD(美元)
  3. 调用记录限制: 默认返回最近100条记录(Agent 50条 + 模型 50条),按时间倒序排列
  4. EU计算: Agent 使用按 1 EU = 10秒计算;模型调用按 Token 数量计算
  5. 渠道名称: 如果租户未关联渠道,显示"无渠道"
  6. 记录类型: 通过 type 字段区分 Agent 使用记录和模型调用记录