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