Token 计费

wesgine 内置 Token 用量记录与查询,支持多维度分析、预算控制和实时监控。


概述

wesgine 的计费体系分三层:

层职责
wesgine记录 raw token 用量(cell_id, provider, model, input/output)
应用层本地 Observe 读取;可选 post-run settle
平台(weisyn)费率表 + 代理结算 + 钱包扣费

本文档聚焦 wesgine 引擎层的 Token 记录与查询能力。


Token 用量记录

每次 LLM 调用自动记录以下维度:

维度说明
cell_idCell 标识
providerProvider 名称
model模型名称
input_tokens输入 Token 数
output_tokens输出 Token 数
reasoning_tokens推理 Token 数(如支持)
cache_read_tokens缓存读取 Token 数
cache_creation_tokens缓存创建 Token 数
session_id会话 ID
agent_idAgent ID
tags自定义标签(含 actor)

记录时机

Token 用量在每次 LLM API 调用完成后立即记录,不依赖 Run 是否正常结束。


按维度查询

API 端点

GET /cells/{cellID}/observe/token-usage

查询参数

参数类型说明
group_bystring分组维度:model / agent / session / day / tag:actor
modelstring按模型过滤
sessionstring按会话过滤
tagsstring按标签过滤(JSON)
fromstring开始时间(RFC3339)
tostring结束时间(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)
	}
}

最佳实践

  1. 生产环境务必设置 TokensPerDay,防止意外成本爆炸
  2. 使用 group_by=tag:actor 实现多用户 Cell 的用量归因
  3. BudgetCheckFn 应快速返回(<100ms),避免阻塞 LLM 调用
  4. 定期导出用量数据 到外部分析系统
  5. 利用 from/to 参数 做月度/季度成本分析

注意事项