feat(model): 工作模型与 JARVIS 语音模型分开配置 + 语音任务路由到快模型

模型配置加"用途"维度:工作主力(chat,要强)与 JARVIS 语音(voice,要快/低时延)各配各激活,
语音任务走语音模型池,未配置则透明回落工作模型——不影响现有功能。

- contract: ConfigKindVoice="voice" + Meta[model_profile]=voice(与 intent==report 同类路由)
- gateway: ServeConfig/broadcastActive 循环纳入 voice;submitVoiceTask 打 model_profile=voice 标记
- dispatcher: 第二个 llm.Pool(voicePool)吃 voice 配置热更新;board.useVoice 从 Meta 派生(含快照);
  Orchestrator.agentPool(b) 按黑板选池——语音且语音池就绪→语音池,否则工作池;
  agent 生成路径(graph/react/coordinator/compose)全改走 agentPool(b),报告/护栏/记忆固定工作池
- admin: 模型页三 Tab(工作主力/JARVIS语音/向量化),复用 ModelManager;api Kind 加 voice

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-22 11:39:17 +08:00
parent b6927247da
commit aec7ad949c
15 changed files with 102 additions and 50 deletions
@@ -99,6 +99,7 @@ const specialistTimeout = 3 * time.Minute
// Orchestrator 把每个 DSL 任务动态编译为 Eino 图并执行(记忆召回 → 工具节点 → 注入 → 流式)。
type Orchestrator struct {
pool LLM
voicePool LLM // JARVIS 语音模型池(可为 nil → 语音任务回落 pool)
breaker *harness.CircuitBreaker
eval *harness.Evaluator
sink TokenSink
@@ -122,6 +123,19 @@ func NewOrchestrator(pool LLM, breaker *harness.CircuitBreaker, eval *harness.Ev
return &Orchestrator{pool: pool, breaker: breaker, eval: eval, sink: sink, tools: tools, exec: exec, status: status, approval: approval, evalSink: evalSink}, nil
}
// SetVoicePool 注入 JARVIS 语音模型池(可选)。注入且就绪时,标了 model_profile==voice 的任务
// 用它跑,抢首字时延;不注入或未就绪则语音任务透明回落工作模型池(o.pool)。
func (o *Orchestrator) SetVoicePool(p LLM) { o.voicePool = p }
// agentPool 按黑板选本任务该用的模型池:语音任务且语音池就绪 → 语音池;否则工作池。
// 只用于面向用户的 agent 生成(对话/协作);报告/护栏/记忆抽取等固定走工作池。
func (o *Orchestrator) agentPool(b *board) LLM {
if b != nil && b.useVoice && o.voicePool != nil && o.voicePool.Ready() {
return o.voicePool
}
return o.pool
}
// SetGuardian 注入输入护栏 Tier2 的 LLM 分类器(可选;不注入则灰区任务直接放行执行)。
func (o *Orchestrator) SetGuardian(c *harness.Classifier) { o.guard = c }