fix(usage): 用量按实际所用模型计量(语音任务归语音模型,别错记工作模型)

分开工作/语音模型后,语音任务实际跑语音模型(deepseek-chat),但 emitUsage 没带 Model,
网关 SaveUsageEvent 拿激活 chat 模型(deepseek-v4-pro)兜底 → 语音用量被错价成工作模型。
修:emitUsage 按任务 model_profile 选池、type-assert ModelName() 填真实模型名。

真机验证:语音任务首字出声 ~2s(deepseek-chat,较 v4-pro 的 5-7s 骤降),usage_event.model
正确记为 deepseek-chat。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-22 11:43:30 +08:00
parent aec7ad949c
commit a4669a0d82
3 changed files with 11 additions and 1 deletions
@@ -172,8 +172,18 @@ func (o *Orchestrator) emitUsage(t *contract.Task, b *harness.Budget) {
} }
uid, _ := t.Meta[contract.MetaUserID].(string) uid, _ := t.Meta[contract.MetaUserID].(string)
tid, _ := t.Meta[contract.MetaTenantID].(string) tid, _ := t.Meta[contract.MetaTenantID].(string)
// 记录本任务**实际所用模型**(语音任务=语音池,其余=工作池),让计费按真实模型定价,
// 别把语音快模型的账记到工作模型头上(否则 SaveUsageEvent 会拿激活 chat 模型兜底,错价)。
pool := o.pool
if meta(t, contract.MetaModelProfile) == contract.ModelProfileVoice && o.voicePool != nil && o.voicePool.Ready() {
pool = o.voicePool
}
model := ""
if mn, ok := pool.(interface{ ModelName() string }); ok {
model = mn.ModelName()
}
if err := o.usageSink.PublishUsage(&contract.UsageEvent{ if err := o.usageSink.PublishUsage(&contract.UsageEvent{
TaskID: t.ID, UserID: uid, TenantID: tid, PromptTok: p, CompTok: c, TotalTok: total, TaskID: t.ID, UserID: uid, TenantID: tid, Model: model, PromptTok: p, CompTok: c, TotalTok: total,
Exceeded: b.Exceeded(), TS: time.Now().UnixMilli(), Exceeded: b.Exceeded(), TS: time.Now().UnixMilli(),
}); err != nil { }); err != nil {
log.Printf("[usage] 回写用量失败 task=%s: %v", t.ID, err) log.Printf("[usage] 回写用量失败 task=%s: %v", t.ID, err)
Binary file not shown.
Binary file not shown.