三种重构方案

从标签协议到动画系统的完整设计对比

A

双标签独立解析

情绪和动作各自独立标签,各自独立事件,前端各管各的。

[动作:wave]
[情绪:joy/0.8]
你好呀!
后端:TagParser 解析两种标签 → emit chat:emotion + chat:action
前端:emotion 持续驱动动画 + blendshape,action 一次性播放

优点

  • 职责分离清晰
  • 各自独立扩展
  • action 可放在回复任意位置

缺点

  • 两个标签要写两行
  • LLM 可能忘记写 action
B

统一行为标签(推荐)

一条标签同时表达情绪和可选动作,紧凑且 LLM 不易遗漏。

[表现:joy/0.8]
你好呀!

[表现:joy/0.8,动作:wave]
太棒了!我一直在等你!
后端:BehaviorParser 一次解析 → emit chat:behavior{emotion, intensity, action?}
前端:统一处理——emotion 持续驱动,action(如有)一次性播放后回退

优点

  • 一个事件搞定一切
  • LLM 只需记一种格式
  • action 可选——不写就纯情绪

缺点

  • 格式稍复杂
  • action 不能穿插文中(但实际也不需要在文中)
C

自然语言驱动(激进)

去掉结构化标签,让 LLM 在 system prompt 的约束下用自然语言描述行为,后端用正则/关键词提取。

(开心地挥手)你好呀!

(惊讶地睁大眼睛)真的吗?
后端:正则匹配 (xxx地yyy) 模式 → 映射到 emotion + action
前端:同方案 B

优点

  • LLM 最自然的表达方式
  • 对用户可见(显示时保留或剔除都行)

缺点

  • 解析不可靠——LLM 可能不遵循格式
  • 中文分词/语义映射容易出错
  • 调试困难

我推荐方案 B

方案 B 在可靠性(结构化标签 LLM 容易遵循)和简洁性(一个标签一个事件)之间取得了最佳平衡。方案 C 太脆弱不值得冒险——哪怕 5% 的解析失败率都会让宠物表现很怪。

如果选 B,后端改动约 50 行 Go(改 emotionPromptSuffix + EmotionParser),前端改动约 80 行(重构 VRMPet 动画状态机)。