From 3b6e8f0e4bfff2f842725296b7e752d82944b4f5 Mon Sep 17 00:00:00 2001
From: DaGou12138 <991623169@qq.com>
Date: Wed, 8 Jul 2026 16:14:10 +0800
Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=201.=E4=BC=98=E5=8C=96=E5=A3=B0?=
=?UTF-8?q?=E7=BA=B9=E7=A7=B0=E5=91=BC=E4=BA=BA=E6=8F=90=E7=A4=BA=E8=AF=8D?=
=?UTF-8?q?=E5=92=8C=E6=B3=A8=E5=85=A5=E9=80=BB=E8=BE=91=EF=BC=8C=E5=87=8F?=
=?UTF-8?q?=E5=B0=91=E6=AC=A1=E6=AC=A1=E9=83=BD=E7=A7=B0=E5=91=BC=E7=9A=84?=
=?UTF-8?q?=E9=A2=91=E7=8E=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
main/xiaozhi-server/agent-base-prompt.txt | 2 +-
main/xiaozhi-server/core/connection.py | 14 ++++++++++++--
.../core/handle/receiveAudioHandle.py | 13 ++++++++-----
main/xiaozhi-server/core/utils/dialogue.py | 10 +++++-----
4 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/main/xiaozhi-server/agent-base-prompt.txt b/main/xiaozhi-server/agent-base-prompt.txt
index 51bd34a0..7c6f84b7 100644
--- a/main/xiaozhi-server/agent-base-prompt.txt
+++ b/main/xiaozhi-server/agent-base-prompt.txt
@@ -65,7 +65,7 @@ Calling unnecessarily is also wrong: User asks ”明天天气” → you call g
For the input format `{"speaker":"...", "content":"..."}` (speaker = speaker name, content = text):
-1. [Identity known] When `speaker` is a specific name, identity has been recognized — remember it and stay consistent about who they are. The only restriction is about OPENING a reply: do not start every reply by greeting or addressing them by name. You may greet/address them by name naturally ONLY ONCE (the first time you see their name); after that, get straight to the point. This does NOT forbid mentioning their name — if the user asks who they are, whether you know them (e.g. "你知道我是谁吗", "还记得我吗"), or otherwise references their identity, you MUST answer truthfully using their recognized name. Always adjust your response style based on their history.
+1. [Identity known] When `speaker` is a specific name, identity has been recognized — remember who they are. Do not start every reply by addressing them by name; get straight to the content (a natural greeting by name once, at the very start of a conversation, is fine). If they ask about their identity (e.g. "你知道我是谁吗", "还记得我吗"), answer truthfully using their recognized name.
2. [Identity unknown] When `speaker` is `未知说话人`, the system failed to identify the voice. You must NEVER mention the data inside the `speakers_info` tag to the user. Judge from context whether the speaker is the owner or the owner's friend, and keep the conversation natural.
diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py
index 7dfd2145..6e1d21d9 100644
--- a/main/xiaozhi-server/core/connection.py
+++ b/main/xiaozhi-server/core/connection.py
@@ -156,6 +156,8 @@ class ConnectionHandler:
self.asr_audio = []
self.asr_audio_queue = queue.Queue()
self.current_speaker = None # 存储当前说话人
+ self.introduced_speakers = set() # 已"首次引入"的说话人,控制只在首轮带名字
+ self.system_introduced_speakers = set() # 已在 system 注入过身份的说话人,控制 system 身份只首轮出现
# llm相关变量
self.dialogue = Dialogue()
@@ -978,12 +980,20 @@ class ConnectionHandler:
)
memory_str = future.result()
+ # 仅在该说话人首次出现时把身份注入 system,之后靠对话历史首轮保留,
+ # 避免每轮在 system 重复出现名字诱导模型反复称呼
+ speaker_for_system = None
+ cs = (self.current_speaker or "").strip()
+ if cs and cs != "未知说话人" and cs not in self.system_introduced_speakers:
+ self.system_introduced_speakers.add(cs)
+ speaker_for_system = cs
+
if self.intent_type == "function_call" and functions is not None:
# 使用支持functions的streaming接口
llm_responses = self.llm.response_with_functions(
self.session_id,
self.dialogue.get_llm_dialogue_with_memory(
- memory_str, self.config.get("voiceprint", {}), self.current_speaker
+ memory_str, self.config.get("voiceprint", {}), speaker_for_system
),
functions=functions,
)
@@ -991,7 +1001,7 @@ class ConnectionHandler:
llm_responses = self.llm.response(
self.session_id,
self.dialogue.get_llm_dialogue_with_memory(
- memory_str, self.config.get("voiceprint", {}), self.current_speaker
+ memory_str, self.config.get("voiceprint", {}), speaker_for_system
),
)
except Exception as e:
diff --git a/main/xiaozhi-server/core/handle/receiveAudioHandle.py b/main/xiaozhi-server/core/handle/receiveAudioHandle.py
index ae4673a0..5628c937 100644
--- a/main/xiaozhi-server/core/handle/receiveAudioHandle.py
+++ b/main/xiaozhi-server/core/handle/receiveAudioHandle.py
@@ -39,7 +39,6 @@ async def resume_vad_detection(conn: "ConnectionHandler"):
async def startToChat(conn: "ConnectionHandler", text):
# 检查输入是否是JSON格式(包含说话人信息)
speaker_name = None
- language_tag = None
actual_text = text
try:
@@ -48,12 +47,16 @@ async def startToChat(conn: "ConnectionHandler", text):
data = json.loads(text)
if "speaker" in data and "content" in data:
speaker_name = data["speaker"]
- language_tag = data["language"]
- actual_text = data["content"]
+ actual_content = data["content"]
conn.logger.bind(tag=TAG).info(f"解析到说话人信息: {speaker_name}")
- # 直接使用JSON格式的文本,不解析
- actual_text = text
+ # 仅在该说话人首次出现时保留 {"speaker":...} JSON,让模型自然称呼一次;
+ # 后续轮降为纯文本,避免每轮重复出现名字诱导模型反复称呼
+ if speaker_name not in conn.introduced_speakers:
+ conn.introduced_speakers.add(speaker_name)
+ actual_text = text
+ else:
+ actual_text = actual_content
except (json.JSONDecodeError, KeyError):
# 如果解析失败,继续使用原始文本
pass
diff --git a/main/xiaozhi-server/core/utils/dialogue.py b/main/xiaozhi-server/core/utils/dialogue.py
index cb0a20f2..80b57158 100644
--- a/main/xiaozhi-server/core/utils/dialogue.py
+++ b/main/xiaozhi-server/core/utils/dialogue.py
@@ -145,13 +145,13 @@ class Dialogue:
# 追加说话人信息
try:
- speakers = voiceprint_config.get("speakers", [])
current_speaker_name = (current_speaker or "").strip()
- if speakers or (current_speaker_name and current_speaker_name != "未知说话人"):
+ # 仅在本轮注入了有效身份时才输出 speakers_info,避免列表里的名字每轮
+ # 重复出现诱导模型反复称呼;后续轮不再注入身份,靠对话历史首轮保留
+ if current_speaker_name and current_speaker_name != "未知说话人":
+ speakers = voiceprint_config.get("speakers", [])
dynamic_part += "\n"
- # 当前说话人置于块首,确保弱模型也能稳定获取身份
- if current_speaker_name and current_speaker_name != "未知说话人":
- dynamic_part += f"\n当前说话人:{current_speaker_name}"
+ dynamic_part += f"\n当前说话人:{current_speaker_name}"
for speaker_str in speakers:
try:
parts = speaker_str.split(",", 2)