Run 预算管理
wesgine 使用多维预算跟踪 Run 的资源消耗,但不因预算耗尽主动终止。
预算维度
| 维度 | 字段 | 说明 |
|---|---|---|
| Token | TokenBudget | Token 消耗上限 |
| 轮次 | TurnBudget | LLM 调用轮次上限 |
| 时间 | TimeBudget | 运行时间上限 |
预算不触发终止
与终止哲学(INV-TERM-01)一致:
- 预算字段仅用于通知和参考
- 超预算不自动终止 Run
- 触发
budget_statusSSE 事件通知前端 - 触发 Grace Call(最后一次 LLM 调用)
BudgetCheckFn
应用层可注入外部预算检查:
AppRunRequest{
BudgetCheckFn: func(usage BudgetUsage) BudgetDecision {
if usage.TotalTokens > orgLimit {
return BudgetExhausted
}
return BudgetOK
},
}
| 返回值 | 行为 |
|---|---|
BudgetOK | 继续执行 |
BudgetExhausted | 终止 Run |
BudgetCheckFn 是应用层强制预算的唯一合法途径(平台计费用此)。
Grace Call
预算即将耗尽时:
预算接近上限
↓
标记 _budget_grace_call = true
↓
最后一次 LLM 调用
↓
模型输出总结(无 tool_call)
↓
Run 正常终结
Grace Call 确保模型有收尾的机会,即使预算耗尽。
Cell 级配额(CellQuotas)
Cell 级别的资源限制:
| 配额 | 说明 |
|---|---|
MaxConcurrentRuns | 最大并发 Run 数 |
TokensPerMinute | 每分钟 Token 上限 |
TokensPerDay | 每天 Token 上限 |
超配额行为
- 并发超限 → 429 拒绝
- Token 速率超限 → 429 排队
预算状态事件
Run 过程中推送 budget_status 事件:
{
"type": "budget_status",
"data": {
"tokens_used": 12500,
"tokens_budget": 50000,
"turns_used": 8,
"turns_budget": 30,
"elapsed_seconds": 120,
"time_budget_seconds": 600
}
}
前端据此显示进度条或警告。
Token 用量追踪
每次 LLM 调用自动记录:
(cell_id, provider, model, input_tokens, output_tokens, timestamp, actor)
查询
GET /cells/{id}/observe/token-usage
GET /cells/{id}/observe/token-summary
GET /cells/{id}/observe/token-usage/aggregate
MaxTokenEstimate
AppRunRequest.MaxTokenEstimate 不是终止阈值:
- 用于上下文压缩决策的参考值
- 不触发终止
- 帮助引擎判断何时启动 MidRunCompression
与终止机制的关系
| 机制 | 是否因预算终止 |
|---|---|
| TokenBudget / TurnBudget / TimeBudget | ❌ 仅通知 |
| BudgetCheckFn | ✅ 应用层强制 |
| CellQuotas.MaxConcurrentRuns | ❌ 拒绝新 Run,不终止进行中的 |
| CellQuotas.TokensPerMinute | ❌ 排队,不终止 |
相关文档
- 终止哲学 →
run-termination-philosophy.md - Run 生命周期 →
run-lifecycle.md - Token 用量与观测 →
token-usage-observe.md - ErrorStreak 检测 →
error-streak-detection.md