mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-14 14:31:00 +00:00
feat: add back streaming switch for web chat
This commit is contained in:
@@ -65,6 +65,10 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter)
|
|||||||
outbound_message_queue: asyncio.Queue = pydantic.Field(default_factory=asyncio.Queue, exclude=True)
|
outbound_message_queue: asyncio.Queue = pydantic.Field(default_factory=asyncio.Queue, exclude=True)
|
||||||
"""后端主动推送消息的队列"""
|
"""后端主动推送消息的队列"""
|
||||||
|
|
||||||
|
# 流式输出开关
|
||||||
|
stream_enabled: bool = pydantic.Field(default=True, exclude=True)
|
||||||
|
"""是否启用流式输出"""
|
||||||
|
|
||||||
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger, **kwargs):
|
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger, **kwargs):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
config=config,
|
config=config,
|
||||||
@@ -77,6 +81,7 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter)
|
|||||||
|
|
||||||
self.bot_account_id = 'websocketbot'
|
self.bot_account_id = 'websocketbot'
|
||||||
self.outbound_message_queue = asyncio.Queue()
|
self.outbound_message_queue = asyncio.Queue()
|
||||||
|
self.stream_enabled = True
|
||||||
|
|
||||||
async def send_message(
|
async def send_message(
|
||||||
self,
|
self,
|
||||||
@@ -212,8 +217,8 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter)
|
|||||||
return message_data.model_dump()
|
return message_data.model_dump()
|
||||||
|
|
||||||
async def is_stream_output_supported(self) -> bool:
|
async def is_stream_output_supported(self) -> bool:
|
||||||
"""WebSocket始终支持流式输出"""
|
"""根据stream_enabled标志返回是否支持流式输出"""
|
||||||
return True
|
return self.stream_enabled
|
||||||
|
|
||||||
def register_listener(
|
def register_listener(
|
||||||
self,
|
self,
|
||||||
@@ -314,11 +319,16 @@ class WebSocketAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter)
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
connection: WebSocket连接对象
|
connection: WebSocket连接对象
|
||||||
message_data: 消息数据
|
message_data: 消息数据,包含:
|
||||||
|
- message: 消息链
|
||||||
|
- stream: 是否启用流式输出 (可选,默认True)
|
||||||
"""
|
"""
|
||||||
pipeline_uuid = connection.pipeline_uuid
|
pipeline_uuid = connection.pipeline_uuid
|
||||||
session_type = connection.session_type
|
session_type = connection.session_type
|
||||||
|
|
||||||
|
# 获取stream参数,默认为True
|
||||||
|
self.stream_enabled = message_data.get('stream', True)
|
||||||
|
|
||||||
# 选择会话
|
# 选择会话
|
||||||
use_session = self.websocket_group_session if session_type == 'group' else self.websocket_person_session
|
use_session = self.websocket_group_session if session_type == 'group' else self.websocket_person_session
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { DialogContent } from '@/components/ui/dialog';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import {
|
import {
|
||||||
Message,
|
Message,
|
||||||
@@ -60,6 +61,7 @@ export default function DebugDialog({
|
|||||||
const [rawModeMessages, setRawModeMessages] = useState<Set<string>>(
|
const [rawModeMessages, setRawModeMessages] = useState<Set<string>>(
|
||||||
new Set(),
|
new Set(),
|
||||||
);
|
);
|
||||||
|
const [streamOutput, setStreamOutput] = useState(true);
|
||||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const popoverRef = useRef<HTMLDivElement>(null);
|
const popoverRef = useRef<HTMLDivElement>(null);
|
||||||
@@ -384,7 +386,7 @@ export default function DebugDialog({
|
|||||||
|
|
||||||
// 通过WebSocket发送消息
|
// 通过WebSocket发送消息
|
||||||
// 不在本地添加消息,等待后端广播回来(带有正确的ID)
|
// 不在本地添加消息,等待后端广播回来(带有正确的ID)
|
||||||
wsClientRef.current.sendMessage(messageChain);
|
wsClientRef.current.sendMessage(messageChain, streamOutput);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to send message:', error);
|
console.error('Failed to send message:', error);
|
||||||
toast.error(t('pipelines.debugDialog.sendFailed'));
|
toast.error(t('pipelines.debugDialog.sendFailed'));
|
||||||
@@ -897,7 +899,18 @@ export default function DebugDialog({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="p-4 pb-0 bg-white dark:bg-black flex gap-2">
|
<div className="p-4 pb-0 bg-white dark:bg-black flex gap-2">
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2 items-center">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span className="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
{t('pipelines.debugDialog.streamOutput')}
|
||||||
|
</span>
|
||||||
|
<Switch
|
||||||
|
checked={streamOutput}
|
||||||
|
onCheckedChange={setStreamOutput}
|
||||||
|
disabled={!isConnected}
|
||||||
|
className="data-[state=checked]:bg-[#2288ee]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<input
|
<input
|
||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
type="file"
|
type="file"
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ export class WebSocketClient {
|
|||||||
*/
|
*/
|
||||||
public sendMessage(
|
public sendMessage(
|
||||||
messageChain: Array<{ type: string; text?: string; target?: string }>,
|
messageChain: Array<{ type: string; text?: string; target?: string }>,
|
||||||
|
stream: boolean = true,
|
||||||
) {
|
) {
|
||||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
||||||
throw new Error('WebSocket未连接');
|
throw new Error('WebSocket未连接');
|
||||||
@@ -212,6 +213,7 @@ export class WebSocketClient {
|
|||||||
const message = {
|
const message = {
|
||||||
type: 'message',
|
type: 'message',
|
||||||
message: messageChain,
|
message: messageChain,
|
||||||
|
stream: stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.ws.send(JSON.stringify(message));
|
this.ws.send(JSON.stringify(message));
|
||||||
|
|||||||
@@ -535,6 +535,7 @@ const enUS = {
|
|||||||
loadPipelinesFailed: 'Failed to load pipelines',
|
loadPipelinesFailed: 'Failed to load pipelines',
|
||||||
atTips: 'Mention the bot',
|
atTips: 'Mention the bot',
|
||||||
streaming: 'Streaming',
|
streaming: 'Streaming',
|
||||||
|
streamOutput: 'Stream',
|
||||||
connected: 'WebSocket connected',
|
connected: 'WebSocket connected',
|
||||||
disconnected: 'WebSocket disconnected',
|
disconnected: 'WebSocket disconnected',
|
||||||
connectionError: 'WebSocket connection error',
|
connectionError: 'WebSocket connection error',
|
||||||
|
|||||||
@@ -538,6 +538,7 @@ const jaJP = {
|
|||||||
loadPipelinesFailed: 'パイプラインの読み込みに失敗しました',
|
loadPipelinesFailed: 'パイプラインの読み込みに失敗しました',
|
||||||
atTips: 'ボットをメンション',
|
atTips: 'ボットをメンション',
|
||||||
streaming: 'ストリーミング',
|
streaming: 'ストリーミング',
|
||||||
|
streamOutput: 'ストリーム',
|
||||||
connected: 'WebSocket接続済み',
|
connected: 'WebSocket接続済み',
|
||||||
disconnected: 'WebSocket未接続',
|
disconnected: 'WebSocket未接続',
|
||||||
connectionError: 'WebSocket接続エラー',
|
connectionError: 'WebSocket接続エラー',
|
||||||
|
|||||||
@@ -517,6 +517,7 @@ const zhHans = {
|
|||||||
loadPipelinesFailed: '加载流水线失败',
|
loadPipelinesFailed: '加载流水线失败',
|
||||||
atTips: '提及机器人',
|
atTips: '提及机器人',
|
||||||
streaming: '流式传输',
|
streaming: '流式传输',
|
||||||
|
streamOutput: '流式',
|
||||||
connected: 'WebSocket已连接',
|
connected: 'WebSocket已连接',
|
||||||
disconnected: 'WebSocket未连接',
|
disconnected: 'WebSocket未连接',
|
||||||
connectionError: 'WebSocket连接错误',
|
connectionError: 'WebSocket连接错误',
|
||||||
|
|||||||
@@ -515,6 +515,7 @@ const zhHant = {
|
|||||||
loadPipelinesFailed: '載入流程線失敗',
|
loadPipelinesFailed: '載入流程線失敗',
|
||||||
atTips: '提及機器人',
|
atTips: '提及機器人',
|
||||||
streaming: '串流傳輸',
|
streaming: '串流傳輸',
|
||||||
|
streamOutput: '串流',
|
||||||
connected: 'WebSocket已連接',
|
connected: 'WebSocket已連接',
|
||||||
disconnected: 'WebSocket未連接',
|
disconnected: 'WebSocket未連接',
|
||||||
connectionError: 'WebSocket連接錯誤',
|
connectionError: 'WebSocket連接錯誤',
|
||||||
|
|||||||
Reference in New Issue
Block a user