From 6d007176552106ac07f6ab58c5049c002e526f4f Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Sun, 9 Nov 2025 21:57:30 +0800 Subject: [PATCH] feat: add streaming support with toggle in chat interface and adjust layout for mobile --- .../process_stage/method/llm_request.py | 10 +- .../sources/webchat/webchat_adapter.py | 3 + astrbot/dashboard/routes/chat.py | 3 + dashboard/src/components/chat/Chat.vue | 236 ++++++++++++++---- dashboard/src/components/chat/MessageList.vue | 2 +- .../components/chat/ProviderModelSelector.vue | 7 +- .../src/i18n/locales/en-US/features/chat.json | 6 + .../src/i18n/locales/zh-CN/features/chat.json | 6 + dashboard/src/layouts/full/FullLayout.vue | 15 +- dashboard/src/scss/layout/_container.scss | 2 +- dashboard/src/views/ChatPage.vue | 2 +- 11 files changed, 236 insertions(+), 56 deletions(-) diff --git a/astrbot/core/pipeline/process_stage/method/llm_request.py b/astrbot/core/pipeline/process_stage/method/llm_request.py index 03352cc40..5974cd519 100644 --- a/astrbot/core/pipeline/process_stage/method/llm_request.py +++ b/astrbot/core/pipeline/process_stage/method/llm_request.py @@ -429,6 +429,10 @@ class LLMRequestSubStage(Stage): logger.error(f"选择的提供商类型无效({type(provider)}),跳过 LLM 请求处理。") return + streaming_response = self.streaming_response + if (enable_streaming := event.get_extra("enable_streaming")) is not None: + streaming_response = bool(enable_streaming) + if event.get_extra("provider_request"): req = event.get_extra("provider_request") assert isinstance(req, ProviderRequest), ( @@ -548,7 +552,7 @@ class LLMRequestSubStage(Stage): provider=provider, first_provider_request=req, curr_provider_request=req, - streaming=self.streaming_response, + streaming=streaming_response, event=event, ) await agent_runner.reset( @@ -560,10 +564,10 @@ class LLMRequestSubStage(Stage): ), tool_executor=FunctionToolExecutor(), agent_hooks=MAIN_AGENT_HOOKS, - streaming=self.streaming_response, + streaming=streaming_response, ) - if self.streaming_response: + if streaming_response: # 流式响应 event.set_result( MessageEventResult() diff --git a/astrbot/core/platform/sources/webchat/webchat_adapter.py b/astrbot/core/platform/sources/webchat/webchat_adapter.py index ad6a50775..ff5482f58 100644 --- a/astrbot/core/platform/sources/webchat/webchat_adapter.py +++ b/astrbot/core/platform/sources/webchat/webchat_adapter.py @@ -163,6 +163,9 @@ class WebChatAdapter(Platform): _, _, payload = message.raw_message # type: ignore message_event.set_extra("selected_provider", payload.get("selected_provider")) message_event.set_extra("selected_model", payload.get("selected_model")) + message_event.set_extra( + "enable_streaming", payload.get("enable_streaming", True) + ) self.commit_event(message_event) diff --git a/astrbot/dashboard/routes/chat.py b/astrbot/dashboard/routes/chat.py index 5156e14e5..d7afcbc17 100644 --- a/astrbot/dashboard/routes/chat.py +++ b/astrbot/dashboard/routes/chat.py @@ -125,6 +125,8 @@ class ChatRoute(Route): audio_url = post_data.get("audio_url") selected_provider = post_data.get("selected_provider") selected_model = post_data.get("selected_model") + enable_streaming = post_data.get("enable_streaming", True) # 默认为 True + if not message and not image_url and not audio_url: return ( Response() @@ -224,6 +226,7 @@ class ChatRoute(Route): "audio_url": audio_url, "selected_provider": selected_provider, "selected_model": selected_model, + "enable_streaming": enable_streaming, }, ), ) diff --git a/dashboard/src/components/chat/Chat.vue b/dashboard/src/components/chat/Chat.vue index 955797cbd..26c7df563 100644 --- a/dashboard/src/components/chat/Chat.vue +++ b/dashboard/src/components/chat/Chat.vue @@ -1,55 +1,70 @@