diff --git a/backend/apps/chat/api/chat.py b/backend/apps/chat/api/chat.py index 49e1b43d..028567a3 100644 --- a/backend/apps/chat/api/chat.py +++ b/backend/apps/chat/api/chat.py @@ -175,8 +175,13 @@ async def start_chat(session: SessionDep, current_user: CurrentUser, create_chat async def start_chat(session: SessionDep, current_user: CurrentUser, current_assistant: CurrentAssistant, create_chat_obj: CreateChat = CreateChat(origin=2)): try: - return create_chat(session, current_user, create_chat_obj, create_chat_obj and create_chat_obj.datasource, - current_assistant) + # create_chat 内会经 AssistantOutDsFactory.get_instance 同步请求宿主 API + # (requests.get,默认 10s 超时),必须放工作线程执行,避免阻塞事件循环(Issue #1288) + def inner(): + return create_chat(session, current_user, create_chat_obj, create_chat_obj and create_chat_obj.datasource, + current_assistant) + + return await asyncio.to_thread(inner) except Exception as e: raise HTTPException( status_code=500, diff --git a/backend/apps/chat/task/llm.py b/backend/apps/chat/task/llm.py index 55a01b01..cd6fc203 100644 --- a/backend/apps/chat/task/llm.py +++ b/backend/apps/chat/task/llm.py @@ -1,3 +1,4 @@ +import asyncio import concurrent import json import os @@ -235,7 +236,10 @@ async def create(cls, *args, **kwargs): specialized_model_id = args[2].custom_model print("use custom model: id[" + specialized_model_id + "]") config: LLMConfig = await get_default_config(specialized_model_id) - instance = cls(*args, **kwargs, config=config) + # 构造函数可能同步调用宿主 API(type==1 高级应用动态数据源, + # LLMService.__init__ -> AssistantOutDsFactory.get_instance -> requests.get), + # 必须在工作线程执行,避免阻塞事件循环(Issue #1288) + instance = await asyncio.to_thread(cls, *args, **kwargs, config=config) chat_params: list[SysArgModel] = await get_groups(args[0], "chat") for config in chat_params: diff --git a/backend/apps/system/api/assistant.py b/backend/apps/system/api/assistant.py index d35da977..663426b5 100644 --- a/backend/apps/system/api/assistant.py +++ b/backend/apps/system/api/assistant.py @@ -1,3 +1,4 @@ +import asyncio import json import os from datetime import datetime, timedelta, timezone @@ -285,7 +286,12 @@ async def ds(session: SessionDep, current_assistant: CurrentAssistant): } for ds in db_ds_list] if current_assistant.type == 1: - out_ds_instance: AssistantOutDs = AssistantOutDsFactory.get_instance(current_assistant) + # 构造 AssistantOutDs 会同步请求宿主 API(requests.get,默认 10s 超时), + # 必须在工作线程执行,避免阻塞事件循环导致宿主回调死锁(Issue #1288) + def inner(): + return AssistantOutDsFactory.get_instance(current_assistant) + + out_ds_instance: AssistantOutDs = await asyncio.to_thread(inner) return [ { "id": str(ds.id),