Skip to content

[Bug] 声纹识别不精准,llm识别出现幻觉 #3054

@ccIsNoob

Description

@ccIsNoob

🐛 问题描述

张三说话,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>

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions