让语音助手通过表情模式听起来更加自然亲切


语音代理已经非常擅长判断该说什么了。而借助 LiveKit Inference 中的 Gemma 4 31B 模型,它们能够在亚秒级的延迟下做出回应,让用户的感觉就像得到了即时的回复一样。
但是,他们的表达方式如何呢?如今大多数语音助手给出的每一句话都是用相同的语调来说的:充满活力且欢快,但却完全忽略了用户真实的感受。如果你告诉助手你的航班被取消了,而且还要在有两个孩子的情况下度过一整晚,那么助手不应该用那种热情的语调来确认你是否会重新预订航班,而应该使用那种推销座位选择的语调来诱导你做出决定。
这不仅仅是一个美学问题。人工智能在分析和“思考”类型的任务上表现得相当出色,但在处理需要情感反应的“感受”类型任务时则显得力不从心。2025 年发表在《商业研究杂志》上的一项研究将这一现象称为“情感技能差距”。而这种现象确实带来了代价:当语音助手解决客户的问题时,客户往往不会感到满意,也不太可能再次购买该产品。而正是这些时刻,匹配好客户的情绪状态就显得至关重要了。
我们已经在解决这个问题上投入了很长时间。今天,我们很高兴地宣布:LiveKit 代理现在支持情感表达模式了。这个模式只需一个标志,就能让你的代理在对话中表现出丰富的情感,而不是单调乏味的声音。
试试实时演示版吧。# 像对待朋友一样与它交谈吧。告诉它一些好消息或坏消息,然后观察它的反应如何。关闭表情模式,以听到同一个声音的声音效果;或者切换语音选项,以便比较不同的服务提供商。
文字转语音设备 Fish Audio 表达
关于 开始说话吧。 告诉对方一些好消息,或者一些坏消息,然后观察这些信息传达方式是否有所改变。
为什么可视化工具无法反映 xAI 的情绪呢? xAI 并未发布任何 lk.expression 情绪值,因此没有可用于驱动可视化器的情绪信号。 表达模式是如何工作的?# 来自 Fish Audio、Inworld、Cartesia 和 xAI 等公司的现代语音合成模型能够生成非常逼真的语调,包括温暖、兴奋、犹豫、笑声和叹息等情感表达。不过,这些功能只有在被特定指令触发时才会生效。这种指令可以通过内嵌的标记标签来指定,而每个供应商还会使用自己特有的方言进行语音合成。
表达模式充当了你的大语言模型和文本转语音系统之间的翻译层。当该功能启用时,框架会将特定于提供商的指令注入到大语言模型的提示中,从而让大语言模型在生成语音时能够表达出相应的情感、风格、非语言声音以及停顿效果。所有这些元素都是根据对话上下文来选择的。
这个 LLM 使用一种标记语言进行通信,而该框架会根据当前使用的提供者所使用的语言来自动调整通信方式。
<expr type="expression" label="excited"/> Oh my god, no way! <expr type="sound" label="laughing"/> <expr type="expression" label="happy"/> I <expr type="prosody" label="emphasis">knew</expr> you'd nail it. 这些标签并不是由你亲自编写的。它们是由大语言模型生成的,而该框架会在这些标签被传输给语音合成器之前,对常见的错误进行规范化处理(比如那些不是自闭合类型的标签)。此外,这些标签也会被从面向用户的文字记录中去除,因此你的聊天界面上看到的始终都是清晰明了的文本。
第二个方法则不太明显。将文本逐句流式传输给 TTS 模型,这种方法实际上会削弱语言的表达力,因为 TTS 模型无法捕捉到对话中的情感线索。每句话都是孤立地呈现的,因此渲染出的情感和语调也会随着每句话的切换而发生变化。相反,我们会将句子分批处理成更大的片段,然后再进行合成。我们发现这种方法能够提升 TTS 模型的上下文感知能力,同时更能稳定每句对话中的情感和语调。这些较大的片段并不会增加明显的延迟,尤其是当使用像 Gemma 4 31B 这样的语音优化大语言模型时。
使用表达性模式# 将其启用是一个需要配置的参数,位于你的 AgentSession 上。
from livekit.agents import AgentSession, inference
session = AgentSession( stt=inference.STT("deepgram/nova-3"), llm=inference.LLM("google/gemma-4-31b-it"), tts=inference.TTS("fishaudio/s2.1-pro", voice="9a9cf47702da476aa4629e2506d4a857"), expressive=True, ) 这就是整个流程。代理会从对话中自行选择要传递的内容,所以大多数代理不需要其他任何东西了。
这种表达模式适用于任何大型语言模型。在文本转语音方面,需要使用声明了特定标记语法的 LiveKit 推理模型。目前,Fish Audio( fishaudio/s2.1-pro )、Inworld( inworld/inworld-tts-2 )、Cartesia( cartesia/sonic-3 )和 xAI( xai/tts-1 )这些供应商都针对此功能进行了优化。未来还会有更多的供应商加入这一阵营。如果某个供应商没有针对该语法的模型,那么其转语音效果就会表现不佳,该标志也会保持静止状态。
指导交付# expressive=True 能够提供完整的表达范围。大多数制作人员都希望达到这种效果:注入的指令会告诉模型如何根据当前情境来调整自己的表现,即使在压力很大的时候也能保持冷静。
当你确实需要删除某个东西时,可以使用 ExpressiveOptions 来替代 True 。
from livekit.agents import AgentSession, ExpressiveOptions
expressive: ExpressiveOptions = { "speech_steering": { "pace": "slow", "nonverbal_sounds": {"laughing": False}, }, }
session = AgentSession( # ... stt, llm, tts expressive=expressive, ) 每个键都是一个稀疏的覆盖选项,因此上面的例子中,除了“笑声”之外,其他所有声音都得到了保留。您也可以完全用 tts_instructions_template 或 tts_instructions_append 来替换或扩展注入的提示词。
根据代理的情绪状态来驱动用户的界面操作# 如果您的代理具有像可视化器或情绪指示器这样的视觉元素,那么您希望前端能够了解代理的情绪状态,而不仅仅是它所说的话。
当框架从转录段中移除表达性标记时,它会将该段的引导性标记作为属性附加到 lk.expression 上,该属性会显示在 lk.transcription 文本流中,与干净的文本一起呈现。这个属性的值是一个 JSON 对象,类似于 {"value": "speak happy"} 。因此,我们可以在之后添加字段,而不会破坏你的解析器功能。
需要记住的一点是:这种数值并非固定不变的。Fish Audio 会输出来自固定词汇表的单个词汇,而 Inworld 则会输出类似 "soft, with genuine care" 这样的自由形式英语词汇。此外,模型的表现也会随着它们所处的词汇表而发生变化。因此,与其直接使用原始字符串,Agent UI 会提供一个 useAgentExpression 钩子,它能够将这种表现转化为标准化的情绪状态,并给出相应的颜色表示。
import { useAgentExpression } from '@livekit/compontents-react'; import { AgentAudioVisualizerAura } from '@/compontents/agents-ui';
export const MOOD_COLORS = { angry: '#F5222D', excited: '#FF7A45', happy: '#FFC53D', playful: '#F759AB', surprised: '#B37FEB', anxious: '#D46B08', hopeful: '#52C41A', empathetic: '#36CFC9', curious: '#6600FF', sad: '#2F54EB', calm: '#1FD5F9', };
function Expressive() { const { mood } = useAgentExpression(); const color = MOOD_COLORS[mood] ?? MOOD_COLORS.calm;
return ( <> <AgentAudioVisualizerAura color={color} /> <span style={{ color }}>{mood}</span> </> ); } label 始终呈现的是提供方的原始字符串格式;而颜色则通过你选择的主色调进行融合处理,因此视觉呈现仍然能够体现你的品牌特色。这正是上述演示所展示的效果。
展望未来# 这是我们的第一个表达模式版本,我们已经在着手规划接下来的改进:在会话过程中能够即时切换表达方式,更好地支持更多的文本转语音提供者,以及为前端提供更丰富的表情信号。
今天就试试吧。# 了解两者差异的最快方式就是观看上面的演示视频。之后,只需在您的代理程序中添加一行代码即可启用该功能。完整的演示代码可以在 GitHub 上找到,而关于表达模式的文档则详细说明了其余内容。
那些虽然能正确传达话语情感,但却让用户体验不佳的语音智能助手,最终还是会失去用户。表达模式是我们迈向能够根据用户的情绪来响应的智能助手的第一步。
试试看吧!我们非常希望听到你构建出的作品的效果,以及你收到的任何反馈意见。