perf(voice): 砍兜底等待 1.2s→0.5s + 语音提示词强制简短 + 时延测量

- voice.go: ClientEnd 兜底等待 1200ms→500ms(白吃的时延),首字出声 6.6s→5.3s
- voice_task.go: JARVIS 系统提示词改"必须简短/最多三句/先给结论"(语音场景长答案既拖慢
  首字又难听;注:deepseek-v4-pro 仍可能不理会长度指令,可靠收短需 max_tokens 硬顶)
- voicesim: 时延拆解(提交/首字出声/朗读完毕,以"说完"为0点)

现状:首字出声 ~5.3s,大头是 deepseek 生成第一句(大模型 TTFT);管线开销(兜底+TTS握手)已压到~1s。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Blizzard
2026-07-22 11:17:28 +08:00
parent 9ae06229b8
commit 6b31856551
6 changed files with 31 additions and 7 deletions
+3 -2
View File
@@ -156,9 +156,10 @@ func (s *voiceSession) onControl(m voice.ClientMsg) (done bool) {
_ = s.asr.Finish() // 告知火山本轮说完
}
// 火山流式 ASR 只在 VAD 静音时才发 Final;客户端显式 end(点停)时不能干等——
// 给收尾时间让末尾部分结果到齐,再用"最新转写"兜底提交(trySubmit 去重,Final 先到就它先提交)。
// 给一小段收尾时间让末尾部分结果到齐,再用"最新转写"兜底提交(trySubmit 去重,Final 先到就它先提交)。
// 500ms 是"够接住末尾 partial"与"别拖慢首字出声"的折中(此前 1.2s 白白吃掉一秒多时延)。
go func() {
time.Sleep(1200 * time.Millisecond)
time.Sleep(500 * time.Millisecond)
s.turnMu.Lock()
txt := s.latestText
s.turnMu.Unlock()
@@ -14,9 +14,11 @@ import (
// 语音只是"嘴替键盘",一行编排/工具/计费逻辑都不新造:走的正是 HTTP SubmitTask 那条关卡
// (见记忆 execution-single-entry「提交必走 preflight()+launch() 共用关卡」)。
// voiceAgentSystem 是语音默认单 agent 的系统提示词:口语化、简洁、适合朗读(下行要过 TTS)。
const voiceAgentSystem = "你是用户的语音助手 JARVIS。用简洁、口语化、适合朗读的中文回答," +
"避免冗长的列表和代码块;必要时可调用工具获取信息后再作答。"
// voiceAgentSystem 是语音默认单 agent 的系统提示词:口语化、**极简**、适合朗读(下行要过 TTS)。
// 语音场景务必短——长答案既拖慢首字出声(要等第一句合成),又让人干听十几秒。
const voiceAgentSystem = "你是用户的语音助手 JARVIS。这是语音对话,回答必须简短——像真人聊天," +
"通常一两句话说清重点即可,最多不超过三句,别长篇大论、别列清单、别念代码。" +
"先直接给结论。口语化、自然、适合朗读。需要更多细节时再由用户追问。"
// buildVoiceGraph 把一句转写组成最简可执行图:input(转写) → agent(JARVIS)。
// 与前端画布 exportDsl 同构(kind=input/agent、config.text/system),dispatcher 直接吃。