feat(harness): 成本/Token 预算护栏 —— 单任务硬上限 + 单用户日预算(恒温器最后一环)
token 用量估算计量(CJK≈1/字、ASCII≈1/4字,无需分词器,护栏够用)。 单任务硬上限(dispatcher):Budget 挂 ctx 沿图透传,各 LLM 节点(对话/ReAct/compose/ 报告)入口计输入 token、出口计输出,触顶即中止整图——防失控成本(死循环/超大报告)。 报告路径优雅降级:触顶跳过剩余章节出部分稿,不整体失败。预算来源 Meta.token_budget 或 env TASK_TOKEN_BUDGET(默认 20 万)。 单用户日预算(gateway):dispatcher 收尾经 NATS 回写 UsageEvent → 网关按用户按天累计 Redis(48h 过期自滚动)→ 提交前门控 USER_DAILY_TOKEN_BUDGET(0=不限,超额 402)。 /billing 升级为真实用量:当日已用 / 日预算 / 余额。 契约 UsageEvent + MetaTokenBudget + SubjectUsage;bus Publish/SubscribeUsage; orchestrator SetUsageSink + 预算触顶 failed(不计熔断)。harness budget 5 单测,三模块全绿。 live:单任务 budget=30 → failed(已用约689);用户日 budget=200 → /billing remaining=0 → 402。 至此 harness 由「测温计」完成向「恒温器」的演进(评测闭环/纠偏/忠实度/脱敏/输入护栏/预算六项)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/sundynix/sundynix-dispatcher/internal/dsl"
|
||||
"github.com/sundynix/sundynix-dispatcher/internal/harness"
|
||||
"github.com/sundynix/sundynix-dispatcher/internal/llm"
|
||||
"github.com/sundynix/sundynix-shared/contract"
|
||||
)
|
||||
@@ -204,6 +205,14 @@ func (o *Orchestrator) writeSection(ctx context.Context, topic, kb, heading stri
|
||||
ub.WriteString("\n")
|
||||
}
|
||||
ub.WriteString("请就「本章标题」撰写 200–400 字正文。只输出正文,不要重复标题、不要再列提纲。")
|
||||
// 成本护栏:计入输入;若已触顶则跳过本章(报告优雅降级出部分稿,不整体失败)。
|
||||
if bud := harness.BudgetFrom(ctx); bud != nil {
|
||||
bud.AddPrompt(sys + ub.String())
|
||||
if bud.Exceeded() {
|
||||
tr.info(node, "system", "token 预算", "已达预算上限,跳过本章")
|
||||
return "(已达 token 预算上限,本章自动跳过。)"
|
||||
}
|
||||
}
|
||||
cctx, cancel := llmCtx(ctx)
|
||||
defer cancel()
|
||||
txt, err := o.pool.Chat(cctx, []llm.ChatMessage{{Role: "system", Content: sys}, {Role: "user", Content: ub.String()}})
|
||||
@@ -211,6 +220,9 @@ func (o *Orchestrator) writeSection(ctx context.Context, topic, kb, heading stri
|
||||
log.Printf("[report] 撰写「%s」失败: %v", heading, err)
|
||||
return "(本章撰写失败:" + err.Error() + ")"
|
||||
}
|
||||
if bud := harness.BudgetFrom(ctx); bud != nil {
|
||||
bud.AddComplete(txt) // 成本护栏:计入输出
|
||||
}
|
||||
return strings.TrimSpace(txt)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user