From ed89c05245752bb631c2b1fb5d671b822756ce15 Mon Sep 17 00:00:00 2001 From: Sakura-RanChen <1908198662@qq.com> Date: Mon, 20 Jul 2026 14:48:26 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20intent=E9=98=BB=E5=A1=9E=E4=B8=BB?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/handle/intentHandler.py | 23 ++++++++++++++++--- .../providers/intent/intent_llm/intent_llm.py | 22 +++++++++++++----- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/main/xiaozhi-server/core/handle/intentHandler.py b/main/xiaozhi-server/core/handle/intentHandler.py index 4172653f..1a72d1d6 100644 --- a/main/xiaozhi-server/core/handle/intentHandler.py +++ b/main/xiaozhi-server/core/handle/intentHandler.py @@ -118,8 +118,17 @@ async def process_intent_result( 请根据以上信息回答用户的问题:{original_text}""" - response = conn.intent.replyResult(context_prompt, original_text) - speak_txt(conn, response) + # 使用异步调用避免阻塞事件循环,影响其他设备的音频播放 + try: + response = asyncio.run_coroutine_threadsafe( + conn.intent.replyResult(context_prompt, original_text), + conn.loop, + ).result() + except Exception as e: + conn.logger.bind(tag=TAG).error(f"LLM生成回复失败: {e}") + response = None + if response: + speak_txt(conn, response) conn.executor.submit(process_context_result) return True @@ -184,7 +193,15 @@ async def process_intent_result( elif result.action == Action.REQLLM: # 调用函数后再请求llm生成回复 text = result.result conn.dialogue.put(Message(role="tool", content=text)) - llm_result = conn.intent.replyResult(text, original_text) + # 使用异步调用避免阻塞事件循环,影响其他设备的音频播放 + try: + llm_result = asyncio.run_coroutine_threadsafe( + conn.intent.replyResult(text, original_text), + conn.loop, + ).result() + except Exception as e: + conn.logger.bind(tag=TAG).error(f"LLM生成回复失败: {e}") + llm_result = text if llm_result is None: llm_result = text speak_txt(conn, llm_result) diff --git a/main/xiaozhi-server/core/providers/intent/intent_llm/intent_llm.py b/main/xiaozhi-server/core/providers/intent/intent_llm/intent_llm.py index 669b21d3..cd150bc5 100644 --- a/main/xiaozhi-server/core/providers/intent/intent_llm/intent_llm.py +++ b/main/xiaozhi-server/core/providers/intent/intent_llm/intent_llm.py @@ -1,3 +1,4 @@ +import asyncio from typing import List, Dict, TYPE_CHECKING if TYPE_CHECKING: @@ -120,12 +121,18 @@ class IntentProvider(IntentProviderBase): ) return prompt - def replyResult(self, text: str, original_text: str): + async def replyResult(self, text: str, original_text: str): + """使用 asyncio.to_thread 避免阻塞事件循环""" try: - llm_result = self.llm.response_no_stream( + user_prompt = ( + "请根据以上内容,像人类一样说话的口吻回复用户,要求简洁,请直接返回结果。用户现在说:" + + original_text + ) + # 使用 to_thread 将同步阻塞调用放到线程池中执行,不阻塞事件循环 + llm_result = await asyncio.to_thread( + self.llm.response_no_stream, system_prompt=text, - user_prompt="请根据以上内容,像人类一样说话的口吻回复用户,要求简洁,请直接返回结果。用户现在说:" - + original_text, + user_prompt=user_prompt, ) return llm_result except Exception as e: @@ -207,8 +214,11 @@ class IntentProvider(IntentProviderBase): logger.bind(tag=TAG).debug(f"开始LLM意图识别调用, 模型: {model_info}") try: - intent = self.llm.response_no_stream( - system_prompt=prompt_music, user_prompt=user_prompt + # 使用 to_thread 将同步阻塞调用放到线程池中,避免阻塞事件循环 + intent = await asyncio.to_thread( + self.llm.response_no_stream, + system_prompt=prompt_music, + user_prompt=user_prompt, ) except Exception as e: logger.bind(tag=TAG).error(f"Error in intent detection LLM call: {e}")