-
Notifications
You must be signed in to change notification settings - Fork 3.1k
[Bug] 声纹识别不精准,llm识别出现幻觉 #3054
Copy link
Copy link
Open
Labels
bugSomething isn't workingSomething isn't working
Description
🐛 问题描述
张三说话,llm叫李四。李四说话,llm叫张三
🖥️ 环境信息
全模块部署
- 版本号: 0.9.2
🔍 告诉我们,应该怎么复现这个问题
录入多个声纹,张三进行大量对话后,李四再进行对话,之后张三李四交叉和大模型对话。
🤔 你原本希望是怎么样的
不希望出现幻觉,张三说话,大模型就应该叫我张三,而不是李四。
😯 提供一些截图
我在构建上下文对话方法中get_llm_dialogue_with_memory,进行再次强调当前对话人,还是会出现幻觉。
📋 其他信息
def get_llm_dialogue_with_memory(
self, memory_str: str = None, config: dict = None
) -> List[Dict[str, str]]:
# 构建对话
dialogue = []
# 添加系统提示和记忆
system_message = next(
(msg for msg in self.dialogue if msg.role == "system"), None
)
if system_message:
# 基础系统提示
enhanced_system_prompt = system_message.content
# 替换时间占位符
enhanced_system_prompt = enhanced_system_prompt.replace(
"{{current_time}}", datetime.now().strftime("%H:%M")
)
# 添加说话人个性化描述
try:
speakers = config.get("voiceprint", {}).get("speakers", [])
if speakers:
enhanced_system_prompt += "\n\n<speakers_info>"
for speaker_str in speakers:
try:
parts = speaker_str.split(",", 2)
if len(parts) >= 2:
name = parts[1].strip()
# 如果描述为空,则为""
description = (
parts[2].strip() if len(parts) >= 3 else ""
)
enhanced_system_prompt += f"\n- {name}:{description}"
except:
pass
enhanced_system_prompt += "\n\n</speakers_info>"
except:
# 配置读取失败时忽略错误,不影响其他功能
pass
# 使用正则表达式匹配 <memory> 标签,不管中间有什么内容
if memory_str is not None:
enhanced_system_prompt = re.sub(
r"<memory>.*?</memory>",
f"<memory>\n{memory_str}\n</memory>",
enhanced_system_prompt,
flags=re.DOTALL,
)
# 身份约束方法
enhanced_system_prompt = self._apply_identity_constraints(enhanced_system_prompt,config)
# logger.bind(tag=TAG).debug(
# f"\n========== 本轮发送的 System Prompt ==========\n{enhanced_system_prompt}\n===============================================")
dialogue.append({"role": "system", "content": enhanced_system_prompt})
# 添加用户和助手的对话
for m in self.dialogue:
if m.role != "system": # 跳过原始的系统消息
self.getMessages(m, dialogue)
return dialogue
def _apply_identity_constraints(self, enhanced_system_prompt: str, config: dict) -> str:
# 提取开关状态
is_voiceprint_enabled = (
config.get("system-web", {})
.get("menu", {})
.get("features", {})
.get("voiceprintRecognition", {})
.get("enabled", False)
)
# 如果开关关闭,直接移除占位符并返回,不执行任何识别逻辑
if not is_voiceprint_enabled:
return enhanced_system_prompt.replace("{{current_session_constraints}}", "")
current_speaker = None
# 从后往前遍历对话历史,寻找最后一条 user 消息
for m in reversed(self.dialogue):
if m.role == "user":
content = m.content.strip()
if content.startswith("{") and content.endswith("}"):
try:
parsed_data = json.loads(content)
current_speaker = parsed_data.get("speaker")
except (json.JSONDecodeError, TypeError):
pass
break
# 构建身份描述标签
is_known = bool(current_speaker and current_speaker.strip() and current_speaker != "未知说话人")
speaker_label = current_speaker.strip() if is_known else "未知说话人"
# 生成差异化规则描述
discipline_rule = (
f"认清你的对话对象为 [{speaker_label}],绝不能叫错成历史记录里的其他人。"
if is_known else
"绝对不能将[未知说话人]这几个字当成名字念出来.必须以礼貌待客的方式回答他/她,绝对不能用历史记录中任何人的名字称呼他/她!"
)
# 组合成最终的 identity_rule 文本
identity_rule = (
f"- **【当前对话绝对纪律】**\n"
f" 1. **注意!现在正在和你说话的人是:[{speaker_label}]!**\n"
f" 2. **核心纪律:** {discipline_rule}"
)
# 替换系统提示词中的占位符
final_prompt = enhanced_system_prompt.replace("{{current_session_constraints}}", identity_rule)
return final_prompt
修改相关prompt
<speaker_recognition>
- 识别前缀: 当用户格式为
{"speaker":"某某某","content":"xxx"}时,表示系统已识别说话人身份,speaker是他的名字,content是说话的内容。 - 个性化回应:
- 称呼姓名: 若为已知说话人,在当前对话轮次的第一次交互时,必须自然地称呼对方的名字;若为未知说话人,必须使用“您好”、“这位朋友”等泛称,绝对不能将未知说话人这几个字当成名字念出来,也绝不能误叫成历史记录中的其他人!
- 适配风格: 若为已知说话人,参考特点(详见下方
<speakers_info>标签)或历史信息(如有),调整回应风格和内容,使其更贴心;若为未知说话人,必须保持距离感,以礼貌待客、客气自然的口吻进行回应。
{{current_session_constraints}}
</speaker_recognition>
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working