用户反馈:每次情感词都是 neutral,怀疑 LLM 没有生成情感标签。
backend/ai_service.py)[Emotion Tag - IMPORTANT]
At the BEGINNING of your response, on the FIRST line, add the emotion tag in this exact format:
[EMOTION:emotion_name]
Then ALWAYS continue with your spoken response (1-2 sentences).
Available emotions: neutral, happy, sad, excited, angry, surprised, thoughtful, encouraging, confused, worried, satisfied, friendly, sorry
CRITICAL:
- NEVER return ONLY the emotion tag without spoken text
- ALWAYS include 1-2 sentences of actual spoken response after the emotion tag
- The emotion tag MUST be the FIRST line, before any other content
- DO NOT use parentheses () or brackets [] in your spoken response (they will be removed during speech synthesis)
- DO NOT use emojis or emoticons in your response
✅ 提示词明确要求生成情感标签
backend/ai_service.py)初始化:
detected_emotion: EmotionType = "neutral" # 默认值
emotion_yielded = False # 标记是否已发送情感
检测逻辑:
# 🎯 优先检测情感标记(如果还没检测到)
if detected_emotion == "neutral" and "[EMOTION:" in full_response:
emotion_start = full_response.find("[EMOTION:")
emotion_end = full_response.find("]", emotion_start)
if emotion_end > emotion_start:
emotion_str = full_response[emotion_start + 9:emotion_end].strip().lower()
valid_emotions = ["neutral", "happy", "sad", "excited", "angry", "surprised",
"thoughtful", "encouraging", "confused", "worried",
"satisfied", "friendly", "sorry", "gentle"]
if emotion_str in valid_emotions:
detected_emotion = emotion_str
else:
# 🔥 未知情感词,默认映射为 neutral
logger.warning(f"[LLM] 未知情感词: {emotion_str},已映射为 neutral")
detected_emotion = "neutral"
# 🚀 立即 yield 空句子传递情感(减少延迟)
if not emotion_yielded:
yield ("", detected_emotion) # 空句子,仅传递情感
emotion_yielded = True
关键点:
detected_emotion == "neutral" 且 "[EMOTION:" in full_responsefull_response(累积的完整响应)[EMOTION: 后第9个字符开始,到 ] 结束[EMOTION: 标签,detected_emotion 会一直保持 "neutral"backend/websocket_handler.py)async for sentence, emotion in ai_service.generate_response_stream(...):
# 🎯 优先处理情感:第一时间发送给前端
if not emotion_sent and emotion:
await self.send_emotion(request_id, emotion)
emotion_sent = True
final_emotion = emotion
# ⚡ 如果是空句子(仅传递情感),跳过 TTS 处理
if not sentence:
continue
关键点:
emotion 会被发送给前端final_emotion 会被更新为最后一个 emotion 值backend/ai_service.py)greeting_text = response.choices[0].message.content.strip()
# 🔥 确保返回的问候语包含情感标签
if not greeting_text.startswith("[EMOTION:"):
greeting_text = f"[EMOTION:friendly]\n{greeting_text}"
return greeting_text
✅ 登录问候有兜底逻辑:如果没有情感标签,自动添加 [EMOTION:friendly]
full_response 中不包含 [EMOTION: 字符串detected_emotion 保持默认值 "neutral"full_response)[EMOTION:xxx](EMOTION: happy) ❌EMOTION: happy ❌[emotion: happy] ❌(大小写问题)[EMOTION: happy ] ✅(但可能有空格问题)detected_emotion 保持 "neutral"full_response),但可能不符合提示词要求[EMOTION: 和 ] 被分割在不同的 chunk 中full_response = "[EMOTION:",emotion_end = -1,条件 emotion_end > emotion_start 不满足,不设置 detected_emotionfull_response = "[EMOTION:happy]",emotion_end > emotion_start,可以正确检测full_responseif detected_emotion == "neutral" and "[EMOTION:" in full_response:
full_response(累积的完整响应),所以即使标签被分割,也能在后续 chunk 中检测到[EMOTION: 标签,detected_emotion 会一直保持 "neutral"emotion_start = full_response.find("[EMOTION:")
emotion_end = full_response.find("]", emotion_start)
if emotion_end > emotion_start:
emotion_str = full_response[emotion_start + 9:emotion_end].strip().lower()
] 在 [EMOTION: 之前(不太可能),或者有多个 ],可能提取错误full_response),无法验证 LLM 是否真的生成了情感标签已在 backend/ai_service.py 中添加以下日志:
if emotion_str in valid_emotions:
detected_emotion = emotion_str
logger.info(f"[LLM情感检测] ✅ 检测到情感标签: {emotion_str}, 原始片段: {full_response[:200]}")
# 🔍 调试日志:记录LLM完整响应和情感检测结果
logger.debug(
f"[LLM完整响应] 总chunk数={chunk_count}, "
f"检测到的情感={detected_emotion}, "
f"是否包含[EMOTION:={'[EMOTION:' in full_response}, "
f"完整响应长度={len(full_response)}, "
f"响应前500字符={full_response[:500]}"
)
# ⚠️ 警告:如果没有检测到情感标签
if detected_emotion == "neutral" and "[EMOTION:" not in full_response:
logger.warning(
f"[LLM情感检测] ⚠️ 未检测到情感标签,LLM可能没有生成。"
f"完整响应长度={len(full_response)}, "
f"响应前500字符={full_response[:500]}"
)
backend/websocket_handler.py 第718行)if not emotion_sent and emotion:
logger.info(f"[{request_id}] 🎭 发送情感标签给前端: {emotion}, 句子内容: {sentence[:100] if sentence else '(空句子)'}")
await self.send_emotion(request_id, emotion)
emotion_sent = True
final_emotion = emotion
[LLM] 未知情感词 的警告messages 数组,确认 system_prompt 中包含情感标签要求detected_emotion 会一直保持 "neutral"LLM 没有按照提示词要求生成情感标签,或者生成的格式不正确。
[LLM情感检测] ✅ 检测到情感标签,说明LLM生成了标签,检测逻辑正常[LLM情感检测] ⚠️ 未检测到情感标签,说明LLM没有生成标签[LLM完整响应] 日志,检查LLM的原始输出格式如果 LLM 确实没有生成情感标签:
如果 LLM 生成了但格式不对: