Emotion 模块维护基于 emoji 的统一的情绪字典,并将上游返回的 Emotion 信息转换为系统内部可识别的 Emotion 名称。模块本身不直接驱动界面或动作,而是通过事件和显示消息把 Emotion 分发到各模式和各板级 UI。按来源可以分为两类:
skill emotion:用户侧 ASR emotion。nlg emotion:AI 侧 TTS emotion。| 缩写 | 英文全称 | 中文含义 |
|---|---|---|
| ASR | Automatic Speech Recognition | 自动语音识别 |
| TTS | Text-to-Speech | 文本转语音 |
相关源码:
├── ../../wukong/skills/skill_emotion.h # Emotion 公共 API 与数据结构
├── ../../wukong/skills/skill_emotion.c # Emotion 字典与 Unicode 转换实现
├── ../../wukong/skills/wukong_ai_skills.c # 解析 Skill/NLG 数据并产生 Emotion 相关事件
├── ../../wukong/wukong_ai_agent.h # 定义 WUKONG_AI_EVENT_EMOTION 等事件
├── ../../mode/ # 模式层接收 Emotion 事件并转成 TY_DISPLAY_TP_EMOJI
├── ../../miscs/gui/display/tuya_ai_display.c # 显示消息统一入口
├── ../../miscs/gui/display/ui/font_emoji_64.c # EVB/EVB_PRO 的 emoji 图片映射
├── ../../boards/T5AI_BOARD_DESKTOP/ui/ # Desktop 板的 Emotion -> GIF 映射
├── ../../boards/T5AI_BOARD_ROBOT/ui/robot/ # Robot 板的 Emotion -> GIF 映射
└── ../../boards/T5AI_BOARD_EYES/ui/ # Eyes 板的 Emotion -> GIF 映射
在 Agent 开发过程中,需要通过提示词来约束模型在特定的场景下,返回特定的情绪。详情请参考 平台智能体提示词开发。情绪反馈提示词参考如下:

AI 模型在处理、反馈交互时,会将结构化的情绪数据下发给设备。情绪分为两类:“用户情绪” 和 “AI 情绪”。
用户侧 ASR emotion:
skill emotion 表示用户侧 Emotion,即 ASR 语义对应的情绪。wukong_ai_skills.h 中已经给出了 code="emo" 的 Skill 样例,skillContent.emotion[] 和 skillContent.text[] 用于描述用户 Emotion。1. Skill emotion(用户/ASR emotion)
┌──────────────────────────────────────────────┐
│ bizType = SKILL │
│ code = "emo" │
│ skillContent.emotion[] / text[] │
└──────────────────────────────────────────────┘
│
▼
2. wukong_ai_skills.c 解析 Skill 数据
┌──────────────────────────────────────────────┐
│ __wukong_ai_skill_process() │
│ 当前协议已定义,代码未单独下钻为 Emotion 事件 │
└──────────────────────────────────────────────┘
AI 侧 TTS emotion:
nlg emotion 表示 AI 侧 Emotion,即 TTS/回复内容对应的 Emotion。wukong_ai_skills.c 的 __wukong_ai_nlg_process() 会读取 data.tags[0],再通过 wukong_emoji_get_name() 转为 Emotion name。1 . nlg emotion(AI / TTS emotion)
┌──────────────────────────────────────────────┐
│ bizType = NLG │
│ data.content = "..." │
│ data.tags[0] = "U+1F606" │
└──────────────────────────────────────────────┘
│
▼
2. wukong_ai_skills.c 解析 NLG tags
┌──────────────────────────────────────────────┐
│ __wukong_ai_nlg_process() │
│ 读取 data.tags[0] │
└──────────────────────────────────────────────┘
│
▼
3. skill_emotion.c 做 Emotion 映射
┌──────────────────────────────────────────────┐
│ wukong_emoji_get_name("U+1F606") │
│ -> "laughing" │
└──────────────────────────────────────────────┘
│
▼
4. 产生 Emotion 事件
┌──────────────────────────────────────────────┐
│ wukong_ai_event_notify() │
│ WUKONG_AI_EVENT_EMOTION │
└──────────────────────────────────────────────┘
目前支持两种表达情绪的方式:在屏幕上展示不同的 GIF 表情文件、控制舵机执行不同的动作。
1. 各板级 UI 渲染/动作扩展
┌──────────────────────────────────────────────┐
│ emo.name 和 emo. emoji 映射和转换 │
│ tuya_ai_display_msg(..., TY_DISPLAY_TP_EMOJI) │
└──────────────────────────────────────────────┘
│
▼
2. 各板级 UI 渲染/动作扩展
┌──────────────────────────────────────────────┐
│ EVB / EVB_PRO : Unicode -> emoji 图片 │
│ Desktop : Emotion name -> GIF │
│ Robot / Eyes : Emotion name -> GIF │
│ Robot(可选) : Emotion name -> action │
└──────────────────────────────────────────────┘
wukong_emoji_get_by_name() 反查 Unicode,再由 font_emoji_64.c 把 Unicode 绑定到具体图片资源。desk_event_handle.c > s_gif_emoj_table[] 中,将 Emotion name 绑定到首页 GIF。gui_emotion_find() 在各自 Emotion 表中查找并切换 GIF 资源。T5AI_BOARD_ROBOT 支持。tuya_robot_action_set(),定义在 tuya_robot_actions.h。tuya_robot_action_set() 会继续调用 robot_action_add_action() 入队,后续在动作线程中再进入 servo_action_map_set(),最终分发到具体舵机动作函数。emotion -> action,建议在 Robot 板的 TY_DISPLAY_TP_EMOJI 分支增加独立映射表,而不是改动通用字典模块。1. 收到 Emotion name
┌──────────────────────────────────────────────┐
│ "happy" / "thinking" / "surprise" │
└──────────────────────────────────────────────┘
│
▼
2. emotion-action 映射表
┌──────────────────────────────────────────────┐
│ happy -> ROBOT_ACTION_DANCE │
│ thinking -> ROBOT_ACTION_STAND │
│ surprise -> ROBOT_ACTION_JUMP │
└──────────────────────────────────────────────┘
│
▼
3. 进入动作接口
┌──────────────────────────────────────────────┐
│ tuya_robot_action_set(action) │
└──────────────────────────────────────────────┘
│
▼
4. 动作入队
┌──────────────────────────────────────────────┐
│ robot_action_add_action(action) │
└──────────────────────────────────────────────┘
│
▼
5. 动作线程执行
┌──────────────────────────────────────────────┐
│ servo_action_map_set(action) │
└──────────────────────────────────────────────┘
│
▼
6. 舵机动作函数
┌──────────────────────────────────────────────┐
│ servo_action_dance_set() │
│ servo_action_jump_set() │
│ servo_action_stand_set() │
└──────────────────────────────────────────────┘
以下仅列出 skill_emotion.h 中声明的公共接口。
CONST CHAR_T* wukong_emoji_get_name(CONST CHAR_T* emoji);
说明:通过 Unicode 形式的 emoji 字符串查询 Emotion 名称。
参数:
emoji:输入的 Unicode 字符串,例如 U+1F636。返回值:
neutral。输入必须与字典表中的 Unicode 字符串完全一致。
未命中不会返回 NULL,而是回退到默认 Emotion。调用方如果需要区分 “未命中” 和 "neutral",应额外增加校验逻辑。
CONST CHAR_T* wukong_emoji_get_by_name(CONST CHAR_T* name);
说明:通过 Emotion 名称反查 Unicode 形式的 emoji 字符串。
参数:
name:Emotion 名称,例如 happy。返回值:
U+1F636。Emotion name 由 g_emotions[] 统一维护,建议全部使用小写名称。
未命中同样会回退到默认 Emotion,对板级显示来说可能表现为 “静默显示默认表情”。
INT_T wukong_emoji_unicode_to_utf8(CONST CHAR_T* unicode_str, CHAR_T* utf8_buf, size_t buf_size);
说明:将 U+XXXX 或 U+XXXXXX 形式的 Unicode 字符串转换为 UTF-8 字节流。
参数:
unicode_str:输入 Unicode 字符串,例如 U+1F606。utf8_buf:输出缓冲区。buf_size:输出缓冲区大小。返回值:
-1。当前实现要求 buf_size >= 5,以兼容 4 字节 UTF-8 加结尾 \0。
输入格式必须满足 U+ 前缀,否则直接失败。
#include "skill_emotion.h"
#include "tal_log.h"
VOID demo_lookup_emotion_name(VOID)
{
CONST CHAR_T *name = wukong_emoji_get_name("U+1F606");
TAL_PR_NOTICE("emotion name: %s", name);
}
#include "skill_emotion.h"
#include "tal_log.h"
VOID demo_show_emotion_utf8(VOID)
{
CONST CHAR_T *unicode = wukong_emoji_get_by_name("happy");
CHAR_T utf8_buf[5] = {0};
INT_T len = 0;
len = wukong_emoji_unicode_to_utf8(unicode, utf8_buf, sizeof(utf8_buf));
if (len > 0) {
TAL_PR_NOTICE("utf8 emoji: %s", utf8_buf);
}
}
在 skill_emotion.c 的 g_emotions[] 中增加一项:
{"U+1F973", "celebrating"}
之后按目标板补充绑定:
font_emoji_64.c 映射和 emoji 图片资源。s_gif_emoj_table[]。#include "tuya_robot_actions.h"
typedef struct {
CONST CHAR_T *emotion;
TUYA_ROBOT_ACTION_E action;
} EMOTION_ACTION_MAP_T;
STATIC CONST EMOTION_ACTION_MAP_T s_emotion_action_map[] = {
{"happy", ROBOT_ACTION_DANCE},
{"thinking", ROBOT_ACTION_STAND},
{"surprise", ROBOT_ACTION_JUMP},
};
STATIC VOID robot_emotion_action_trigger(CONST CHAR_T *emotion)
{
UINT_T i = 0;
if (emotion == NULL) {
return;
}
for (i = 0; i < CNTSOF(s_emotion_action_map); i++) {
if (strcmp(s_emotion_action_map[i].emotion, emotion) == 0) {
tuya_robot_action_set(s_emotion_action_map[i].action);
break;
}
}
}
建议把这段逻辑放在 Robot 板级 UI 层,而非 skill_emotion.c 或通用 Mode 层。
在开发过程遇到问题,可以到 TuyaOS 开发者论坛 > 联网单品开发版块 发帖咨询。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈