From 389e8559aaebbfb0e232c8ef1af118da09c047fc Mon Sep 17 00:00:00 2001 From: Rui Xu Date: Mon, 6 Apr 2026 21:49:28 +0800 Subject: [PATCH 1/2] fix: prevent duplicate TTS when LLM streams text before tool call --- main/xiaozhi-server/core/connection.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index d167bf1b..01a9ae01 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -1082,11 +1082,12 @@ class ConnectionHandler: f"工具调用统计更新: 当前轮次={current_turn}" ) - # 如需要大模型先处理一轮,添加相关处理后的日志情况 + # LLM 流式阶段已播报过的文本 + streamed_text = "" if len(response_message) > 0: - text_buff = "".join(response_message) - self.tts_MessageText = text_buff - self.dialogue.put(Message(role="assistant", content=text_buff)) + streamed_text = "".join(response_message) + self.tts_MessageText = streamed_text + self.dialogue.put(Message(role="assistant", content=streamed_text)) response_message.clear() # 收集所有工具调用的 Future @@ -1134,7 +1135,7 @@ class ConnectionHandler: # 统一处理工具调用结果 if tool_results: - self._handle_function_result(tool_results, depth=depth) + self._handle_function_result(tool_results, depth=depth, streamed_text=streamed_text) # 存储对话内容 if len(response_message) > 0: @@ -1194,7 +1195,7 @@ class ConnectionHandler: result = "、".join(datas) return result - def _handle_function_result(self, tool_results, depth): + def _handle_function_result(self, tool_results, depth, streamed_text=""): need_llm_tools = [] for result, tool_call_data in tool_results: @@ -1202,9 +1203,14 @@ class ConnectionHandler: Action.RESPONSE, Action.NOTFOUND, Action.ERROR, - ]: # 直接回复前端 + ]: text = result.response if result.response else result.result - self.tts.tts_one_sentence(self, ContentType.TEXT, content_detail=text) + if streamed_text: + self.logger.bind(tag=TAG).debug( + f"Skipping duplicate TTS for tool {tool_call_data['name']}, already streamed" + ) + else: + self.tts.tts_one_sentence(self, ContentType.TEXT, content_detail=text) self.dialogue.put(Message(role="assistant", content=text)) elif result.action == Action.REQLLM: # 收集需要 LLM 处理的工具 From 3436d50b43870144298f8796893264d81f384fe9 Mon Sep 17 00:00:00 2001 From: Sakura-RanChen <1908198662@qq.com> Date: Mon, 20 Apr 2026 10:40:08 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=8F=AA=E6=9C=89=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E4=B8=80=E8=87=B4=E7=9A=84=E6=97=B6=E5=80=99?= =?UTF-8?q?=E4=B8=8D=E8=BF=9B=E8=A1=8C=E5=90=88=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/xiaozhi-server/core/connection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/xiaozhi-server/core/connection.py b/main/xiaozhi-server/core/connection.py index dbbed278..b58ede82 100644 --- a/main/xiaozhi-server/core/connection.py +++ b/main/xiaozhi-server/core/connection.py @@ -1114,7 +1114,7 @@ class ConnectionHandler: if len(response_message) > 0: streamed_text = "".join(response_message) self.tts.store_tts_text(current_sentence_id, streamed_text) - self.dialogue.put(Message(role="assistant", content=text_buff)) + self.dialogue.put(Message(role="assistant", content=streamed_text)) response_message.clear() # 收集所有工具调用的 Future @@ -1232,7 +1232,7 @@ class ConnectionHandler: Action.ERROR, ]: text = result.response if result.response else result.result - if streamed_text: + if streamed_text and text in streamed_text: self.logger.bind(tag=TAG).debug( f"Skipping duplicate TTS for tool {tool_call_data['name']}, already streamed" )