大模型让 Agent 变得更会回答问题,但“会说”不等于“有活人感”。当 AI 被放进展厅讲解、情感陪伴、教育科普、文旅导览或人形机器人时,用户期待的并不是一个不断吐字的文本框,而是一个能理解语境、及时回应,并通过表情、语气和动作建立信任的角色。
这也是 AI 应用交互正在变化的地方:语言模型负责理解和生成内容,数字人或机器人负责把内容变成可感知的表达。真正有价值的 Agent,不只是增加一个头像,而是把“说什么”和“怎么说”统一起来。
“有情感”不是给模型加一句提示词
给 Agent 加上“请表现得亲切”这样的提示词,只能影响文字风格,无法自动解决实时交互中的几个问题:
- 表达通道太单一:文本内容正确,但没有眼神、停顿、手势和表情。
- 情绪和语义脱节:讲慰问话时面带微笑,或者介绍紧急事项时动作过于轻松,都会削弱可信度。
- 响应节奏不自然:每次都等完整回答生成后才开始播报,用户会感到迟钝。
- 角色缺乏连续性:上一轮表现得耐心温和,下一轮却突然变成机械客服。
因此,可以把一次 Agent 响应拆成三个层次:
- 语义层:回答用户的问题,决定事实、观点和下一步行动。
- 情绪层:判断当前表达更适合平静、热情、安慰、严肃还是惊讶。
- 表现层:把情绪转换成语音参数、面部表情、视线、手势和动作时长。
这个拆分很重要。它让产品团队可以分别评估“答得对不对”和“表达得像不像一个合适的角色”,也方便把同一个大模型回答接入数字人、屏幕角色或机器人身体。
一条可落地的 Agent 表现链路
一个较实用的架构可以是:
用户输入
↓
意图与安全判断
↓
大模型生成回答 + 情绪标签 + 动作建议
↓
文本转语音(TTS)与动画编排
↓
数字人渲染 / 机器人执行
↓
实时打断、反馈与状态更新
关键不是让模型自由发挥所有动作,而是给它一个有限、可验证的表现协议。例如,模型只允许输出 calm、warm、serious 三类情绪,以及 nod、wave、point 三种动作。渲染端再把这些标签映射到具体的表情参数和动画资源。
这样做有三个好处:
- 可控:避免模型输出无法执行的动作名称。
- 可测试:可以针对不同场景检查情绪和动作是否匹配。
- 可替换:更换数字人引擎或机器人硬件时,不必重写对话逻辑。
一个可以运行的最小原型
下面的 Python 示例不依赖外部库,用关键词模拟语义与情绪判断,并输出一个统一的“角色表现事件”。它不是完整的大模型系统,但可以用来验证前后端协议:前端数字人收到事件后,就能根据 emotion 和 gesture 播放对应资源。
将代码保存为 emotion_agent.py,使用 Python 3 运行:
import json
import sys
from typing import Dict
def build_avatar_event(user_text: str) -> Dict[str, object]:
"""根据用户输入生成一个最小的数字人表现事件。"""
text = user_text.strip()
if any(word in text for word in ("难过", "焦虑", "担心", "压力")):
return {
"text": "听起来这件事让你承受了不少压力。我们可以一步一步梳理。",
"emotion": "warm",
"gesture": "nod",
"speaking_rate": 0.92,
"interruptible": True,
}
if any(word in text for word in ("危险", "紧急", "火灾", "报警")):
return {
"text": "请先确保自己处于安全位置,并立即联系现场工作人员或当地紧急服务。",
"emotion": "serious",
"gesture": "point",
"speaking_rate": 1.0,
"interruptible": False,
}
if any(word in text for word in ("你好", "嗨", "介绍")):
return {
"text": "你好,我可以为你讲解展品、回答问题,也可以带你继续参观。",
"emotion": "warm",
"gesture": "wave",
"speaking_rate": 1.0,
"interruptible": True,
}
return {
"text": "我会先了解你的问题,再给出简洁的说明。你想从哪一部分开始?",
"emotion": "calm",
"gesture": "nod",
"speaking_rate": 0.98,
"interruptible": True,
}
if __name__ == "__main__":
question = " ".join(sys.argv[1:]) or input("用户:")
print(json.dumps(build_avatar_event(question), ensure_ascii=False, indent=2))
运行示例:
python emotion_agent.py "我最近有点焦虑,能陪我聊聊吗"
输出类似:
{
"text": "听起来这件事让你承受了不少压力。我们可以一步一步梳理。",
"emotion": "warm",
"gesture": "nod",
"speaking_rate": 0.92,
"interruptible": true
}
在真实项目中,可以把 build_avatar_event 换成大模型调用,并要求模型严格返回 JSON。例如,给模型的系统提示可以这样设计:
你是展厅数字人的对话编排器。
请根据用户输入生成 JSON,不要输出 Markdown。
字段必须为:text、emotion、gesture、speaking_rate、interruptible。
emotion 只能是 calm、warm、serious;gesture 只能是 nod、wave、point、none。
紧急、安全和医疗相关内容优先使用 serious,并避免做出轻佻或夸张动作。
这类协议还应在服务端做 JSON Schema 校验。不要直接把模型返回的任意字符串交给动画引擎,否则一个拼写错误就可能导致动作丢失,甚至触发不安全行为。
实时感来自“节奏”,不只是外观
有形象、有表情只是起点。用户是否觉得 Agent 像一个真实角色,很大程度取决于交互节奏。
支持打断
语音播报过程中,用户可能突然补充信息、纠正事实或表示“不用了”。系统应该能够停止当前 TTS 和动作,立即进入新一轮识别,而不是把整段话播完。interruptible 可以作为协议中的显式字段,帮助编排层决定哪些回答允许被打断。
分阶段输出
不要让模型生成完整长文本后才开始渲染。可以先发送短确认,再流式发送回答内容,最后补充动作或下一步建议:
{"type":"ack","text":"我听到了,正在帮你查找。","emotion":"calm"}
{"type":"speech_delta","text":"这件展品的核心材料是"}
{"type":"speech_delta","text":"……"}
{"type":"gesture","name":"point","duration_ms":900}
{"type":"done","can_interrupt":true}
这种事件流比一次性返回完整 JSON 更适合展厅和机器人场景。用户能更早获得反馈,系统也可以在网络延迟或模型生成较慢时维持交互连续性。
保持角色一致
角色设定不应只写成一段营销文案,而要转成可执行的规则,例如:
- 面向儿童时减少术语,每次只解释一个概念。
- 面向老年用户时降低语速,确认对方是否听清。
- 讲解珍贵展品时使用平静语气,避免夸张手势。
- 遇到不确定信息时明确说“我需要进一步确认”,不要用自信表情掩盖未知。
情感表达的边界与验收清单
“有温度”不代表让 AI 假装拥有真实情绪。产品需要清楚告知用户这是 AI 角色,并避免利用表情和陪伴感制造过度依赖。涉及心理健康、医疗、金融或安全问题时,情绪表达应服务于清晰、谨慎的建议,而不是替代专业帮助。
上线前可以用下面的清单验收:
- 语义是否正确,是否能说明信息来源或不确定性?
- 情绪、语音和动作是否与内容匹配?
- 用户打断后,上一轮动作和播报能否在合理时间停止?
- 网络变慢时,角色是否会保持自然反馈,而不是长时间无响应?
- 所有动作是否来自白名单,是否经过安全审核?
- 是否保留了文本和事件日志,方便复盘错误表现?
- 不同年龄、文化和无障碍需求的用户,是否都能理解这些表达?
结语:先做一套稳定的表现协议
从文本对话框走向有活人感的 Agent,并不意味着一开始就要打造完美数字人。更稳妥的路径是先定义统一事件协议,再逐步接入 TTS、表情、手势和实时渲染能力。让模型负责理解和规划,让表现引擎负责可控地执行,才能把“情感”从一句宣传语变成可测试、可迭代的产品能力。
对团队而言,最值得优先验证的不是“角色看起来多逼真”,而是三个问题:它是否回应得及时,表达是否与语境一致,以及用户是否知道下一步该做什么。做到这三点,Agent 才真正开始从会回答问题,走向会与人相处。