Token 计费
wesgine 内置 Token 用量记录与查询,支持多维度分析、预算控制和实时监控。
概述
wesgine 的计费体系分三层:
| 层 | 职责 |
|---|---|
| wesgine | 记录 raw token 用量(cell_id, provider, model, input/output) |
| 应用层 | 本地 Observe 读取;可选 post-run settle |
| 平台(weisyn) | 费率表 + 代理结算 + 钱包扣费 |
本文档聚焦 wesgine 引擎层的 Token 记录与查询能力。
Token 用量记录
每次 LLM 调用自动记录以下维度:
| 维度 | 说明 |
|---|---|
cell_id | Cell 标识 |
provider | Provider 名称 |
model | 模型名称 |
input_tokens | 输入 Token 数 |
output_tokens | 输出 Token 数 |
reasoning_tokens | 推理 Token 数(如支持) |
cache_read_tokens | 缓存读取 Token 数 |
cache_creation_tokens | 缓存创建 Token 数 |
session_id | 会话 ID |
agent_id | Agent ID |
tags | 自定义标签(含 actor) |
记录时机
Token 用量在每次 LLM API 调用完成后立即记录,不依赖 Run 是否正常结束。
按维度查询
API 端点
GET /cells/{cellID}/observe/token-usage
查询参数
| 参数 | 类型 | 说明 |
|---|---|---|
group_by | string | 分组维度:model / agent / session / day / tag:actor |
model | string | 按模型过滤 |
session | string | 按会话过滤 |
tags | string | 按标签过滤(JSON) |
from | string | 开始时间(RFC3339) |
to | string | 结束时间(RFC3339) |
查询示例
# 按模型分组查询最近 7 天用量
curl "http://localhost:9091/cells/my-cell/observe/token-usage?group_by=model&from=2026-09-07T00:00:00Z" \
-H "Authorization: Bearer <token>"
# 按 Agent 按天分组
curl "http://localhost:9091/cells/my-cell/observe/token-usage/aggregate?agent=reporter&group_by=day&days=30" \
-H "Authorization: Bearer <token>"
# 按用户(actor)分组
curl "http://localhost:9091/cells/my-cell/observe/token-usage?group_by=tag:actor" \
-H "Authorization: Bearer <token>"
响应格式
{
"groups": [
{
"key": "gpt-4o",
"input_tokens": 125000,
"output_tokens": 45000,
"reasoning_tokens": 8000,
"cache_read_tokens": 80000,
"total_tokens": 178000,
"call_count": 42
},
{
"key": "claude-3-5-sonnet",
"input_tokens": 95000,
"output_tokens": 32000,
"total_tokens": 127000,
"call_count": 28
}
],
"total": {
"input_tokens": 220000,
"output_tokens": 77000,
"total_tokens": 305000,
"call_count": 70
}
}
聚合统计
Token 用量摘要
GET /cells/{cellID}/observe/token-summary
返回 Cell 级别的聚合摘要:
{
"total_input_tokens": 1250000,
"total_output_tokens": 450000,
"total_tokens": 1700000,
"total_calls": 520,
"total_runs": 85,
"period": {
"from": "2026-09-01T00:00:00Z",
"to": "2026-09-14T23:59:59Z"
},
"top_models": [
{"model": "gpt-4o", "tokens": 980000, "calls": 310},
{"model": "claude-3-5-sonnet", "tokens": 520000, "calls": 150}
],
"top_agents": [
{"agent": "assistant", "tokens": 1200000, "calls": 400},
{"agent": "reporter", "tokens": 300000, "calls": 80}
]
}
按 Agent/Day 聚合
GET /cells/{cellID}/observe/token-usage/aggregate
# 最近 30 天按天聚合
curl "http://localhost:9091/cells/my-cell/observe/token-usage/aggregate?group_by=day&days=30" \
-H "Authorization: Bearer <token>"
# 特定 Agent 的每日用量
curl "http://localhost:9091/cells/my-cell/observe/token-usage/aggregate?agent=reporter&group_by=day&days=7" \
-H "Authorization: Bearer <token>"
预算控制
CellQuotas
通过 CellSpec 设置 Token 配额:
spec := wesgine.CellSpec{
ID: "budget-cell",
Quotas: wesgine.CellQuotas{
TokensPerMinute: 100000, // 每分钟 Token 上限
TokensPerDay: 5000000, // 每天 Token 上限
},
}
超限行为:返回 HTTP 429(Too Many Requests),不终止正在运行的 Run。
BudgetCheckFn
外部预算检查回调——在每次 LLM 调用前检查:
spec.BudgetCheckFn = func(ctx context.Context, req BudgetCheckRequest) BudgetCheckResult {
// 查询外部计费系统
remaining, err := billingService.GetRemaining(req.CellID, req.Actor)
if err != nil {
return BudgetCheckResult{Status: BudgetCheckError}
}
if remaining <= 0 {
return BudgetCheckResult{
Status: BudgetExhausted,
Message: "账户余额不足,请充值后继续",
}
}
return BudgetCheckResult{Status: BudgetCheckOK}
}
BudgetCheckResult 状态
| 状态 | 行为 |
|---|---|
BudgetCheckOK | 继续执行 |
BudgetExhausted | 终止 Run,返回 budget_exhausted done reason |
BudgetCheckError | 继续执行(fail-open) |
INV-TERM-01:引擎不因 counter 阈值主动终止。
BudgetCheckFn返回Exhausted是唯一的外部预算终止路径。
SDK 用法
查询 Token 用量
// 列出 Token 用量
usage, err := cell.Observe().TokenUsage(ctx, observe.TokenUsageQuery{
GroupBy: "model",
From: time.Now().AddDate(0, 0, -7),
To: time.Now(),
})
for _, group := range usage.Groups {
fmt.Printf("模型: %s, 总 Token: %d, 调用次数: %d\n",
group.Key, group.TotalTokens, group.CallCount)
}
查询 Token 摘要
summary, err := cell.Observe().TokenSummary(ctx)
fmt.Printf("总 Token: %d, 总调用: %d\n",
summary.TotalTokens, summary.TotalCalls)
跨 Cell 统计(Admin)
Admin 可以查看跨 Cell 的统计:
# 各 Cell 统计
curl "http://localhost:9091/admin/observe/per-cell-stats" \
-H "Authorization: Bearer <admin-token>"
# 特定 Cell 集合
curl "http://localhost:9091/admin/observe/per-cell-stats?cell=dept-legal&cell=dept-audit" \
-H "Authorization: Bearer <admin-token>"
实战示例
企业部门预算控制
// 为金融部门设置严格预算
spec := wesgine.CellSpec{
ID: "dept-finance",
Quotas: wesgine.CellQuotas{
TokensPerMinute: 50000,
TokensPerDay: 2000000,
},
}
// 外部预算检查
spec.BudgetCheckFn = func(ctx context.Context, req BudgetCheckRequest) BudgetCheckResult {
budget := departmentBudgetService.Check(req.CellID, req.Actor)
if budget.Exhausted {
return BudgetCheckResult{
Status: BudgetExhausted,
Message: fmt.Sprintf("部门月度预算已用完(%d/%d)", budget.Used, budget.Limit),
}
}
return BudgetCheckResult{Status: BudgetCheckOK}
}
用量监控仪表盘
// 定时采集 Token 用量
ticker := time.NewTicker(5 * time.Minute)
for range ticker.C {
stats, _ := hyp.Observe().PerCellStats(ctx)
for _, s := range stats {
metrics.Gauge("token_usage_total", float64(s.TotalTokens),
"cell", s.CellID)
metrics.Gauge("active_runs", float64(s.ActiveRuns),
"cell", s.CellID)
}
}
最佳实践
- 生产环境务必设置
TokensPerDay,防止意外成本爆炸 - 使用
group_by=tag:actor实现多用户 Cell 的用量归因 BudgetCheckFn应快速返回(<100ms),避免阻塞 LLM 调用- 定期导出用量数据 到外部分析系统
- 利用
from/to参数 做月度/季度成本分析
注意事项
- Token 用量随 LLM 调用即时记录,不等 Run 结束
TokensPerMinute/TokensPerDay超限返回 429,不终止进行中的 RunBudgetCheckFn返回Error时 fail-open(继续执行),不是 fail-closed- 跨 Cell 统计只通过 Admin Token 的
/admin/observe/*端点 tag:actor分组依赖AppRunRequest.Actor字段的正确填写