From dd9220842472f7fbd01e15666a6fdfb022d74350 Mon Sep 17 00:00:00 2001 From: ah7255703 Date: Mon, 19 Feb 2024 11:57:30 +0200 Subject: [PATCH 1/6] Update Copilot widget code --- copilot-widget/index.html | 2 +- copilot-widget/lib/contexts/Controller.tsx | 170 +++++++++++++-------- 2 files changed, 104 insertions(+), 68 deletions(-) diff --git a/copilot-widget/index.html b/copilot-widget/index.html index 5b23b0552..694d9a0ca 100644 --- a/copilot-widget/index.html +++ b/copilot-widget/index.html @@ -75,7 +75,7 @@

diff --git a/copilot-widget/lib/contexts/Controller.tsx b/copilot-widget/lib/contexts/Controller.tsx index af895c081..2da58c875 100644 --- a/copilot-widget/lib/contexts/Controller.tsx +++ b/copilot-widget/lib/contexts/Controller.tsx @@ -1,12 +1,19 @@ -import React, { ReactNode, useCallback, useEffect, useMemo, useState } from "react"; +import React, { + ReactNode, + useCallback, + useEffect, + useMemo, + useState, +} from "react"; import now from "../utils/timenow"; import { useConfigData } from "./ConfigData"; import { Message } from "@lib/types"; import { getId } from "@lib/utils/utils"; -import io from 'socket.io-client'; +import io from "socket.io-client"; import { useSessionId } from "@lib/hooks/useSessionId"; import { BotResponse, UserMessage } from "@lib/types/messageTypes"; import { createSafeContext } from "./create-safe-context"; +import { useWidgetState } from "./WidgetState"; export type FailedMessage = { message: Message; @@ -16,93 +23,124 @@ export type FailedMessage = { interface ChatContextData { messages: Message[]; conversationInfo: string | null; - sendMessage: (message: Extract) => void; + sendMessage: (message: Extract) => void; loading: boolean; failedMessage: FailedMessage | null; reset: () => void; setLastMessageId: (id: number | null) => void; lastMessageToVote: number | null; } -const [ - useChat, - ChatSafeProvider, -] = createSafeContext(); - +const [useChat, ChatSafeProvider] = createSafeContext(); const ChatProvider: React.FC<{ children: ReactNode }> = ({ children }) => { - const [currentMessagePair, setCurrentMessagePair] = useState<{ user: string; bot: string } | null>(null); + const [isOpen] = useWidgetState(); + const [currentMessagePair, setCurrentMessagePair] = useState<{ + user: string; + bot: string; + } | null>(null); const [messages, setMessages] = useState([]); const config = useConfigData(); const { sessionId } = useSessionId(config.token); const [conversationInfo, setConversationInfo] = useState(null); - const [lastMessageToVote, setLastMessageToVote] = useState(null); + const [lastMessageToVote, setLastMessageToVote] = useState( + null + ); const setLastMessageId = useCallback((id: number | null) => { - setLastMessageToVote(id) - }, []) - - const socket = useMemo(() => io(config.socketUrl, { - extraHeaders: { - "X-Bot-Token": config.token, - "X-Session-Id": sessionId, - }, - }), [config, sessionId]); + setLastMessageToVote(id); + }, []); + const socket = useMemo( + () => + io(config.socketUrl, { + autoConnect: false, + transports: ["websocket"], + extraHeaders: { + "X-Bot-Token": config.token, + "X-Session-Id": sessionId, + }, + }), + [config, sessionId] + ); + console.log(socket) + + useEffect(() => { + if (isOpen) { + socket.connect(); + } else { + socket.disconnect(); + } + }, [isOpen, socket]); const [failedMessage, setError] = useState(null); const loading = currentMessagePair !== null; const sendMessage = async (message: Extract) => { - // abort + // abort const userMessageId = getId(); const botMessageId = getId(); - const userMessage: UserMessage & { session_id: string, headers: Record } = { + const userMessage: UserMessage & { + session_id: string; + headers: Record; + } = { timestamp: now(), id: userMessageId, content: message.content, from: "user", session_id: sessionId, headers: config.headers ?? {}, - } - socket.emit('send_chat', userMessage); + }; + socket.emit("send_chat", userMessage); setCurrentMessagePair({ user: userMessageId, bot: botMessageId, - }) + }); createUserMessage(userMessage); - createEmptyBotMessage(botMessageId) + createEmptyBotMessage(botMessageId); }; - const createUserMessage = useCallback((message: Extract) => { - setMessages((m) => [...m, message]); - }, [setMessages]); + const createUserMessage = useCallback( + (message: Extract) => { + setMessages((m) => [...m, message]); + }, + [setMessages] + ); - const createEmptyBotMessage = useCallback((id: string) => { - setMessages((m) => [...m, { - timestamp: now(), - from: "bot", - id: id, - type: "text", - response: { - text: "" + const createEmptyBotMessage = useCallback( + (id: string) => { + setMessages((m) => [ + ...m, + { + timestamp: now(), + from: "bot", + id: id, + type: "text", + response: { + text: "", + }, + }, + ]); + }, + [setMessages] + ); + + const updateBotMessage = useCallback( + (id: string, text: string) => { + const botMessage = messages.find((m) => m.id === id) as BotResponse; + if (botMessage) { + // append the text to the bot message + const textt = botMessage.response.text + text; + botMessage.response.text = textt; + setMessages([...messages]); } - }]) - }, [setMessages]); - - const updateBotMessage = useCallback((id: string, text: string) => { - const botMessage = messages.find(m => m.id === id) as BotResponse - if (botMessage) { - // append the text to the bot message - const textt = botMessage.response.text + text - botMessage.response.text = textt - setMessages([...messages]) - } - }, [messages]) + }, + [messages] + ); useEffect(() => { socket.on(`${sessionId}_info`, (msg: string) => { - setConversationInfo(msg) - }) + setConversationInfo(msg); + }); return () => { socket.off(`${sessionId}_info`); @@ -110,37 +148,38 @@ const ChatProvider: React.FC<{ children: ReactNode }> = ({ children }) => { }, [sessionId, socket]); useEffect(() => { - const current = currentMessagePair + const current = currentMessagePair; // the content is the message.content from the server try { socket.on(sessionId, (content: string) => { if (current) { if (content === "|im_end|") { - setCurrentMessagePair(null) - return + setCurrentMessagePair(null); + return; } - setConversationInfo(null) - updateBotMessage(current.bot, content) + setConversationInfo(null); + updateBotMessage(current.bot, content); } }); - return () => { socket.off(sessionId) } + return () => { + socket.off(sessionId); + }; } catch (error) { - setConversationInfo(null) + setConversationInfo(null); } - }, [currentMessagePair, sessionId, socket, updateBotMessage]); useEffect(() => { socket.on(`${sessionId}_vote`, (content) => { - console.log(`${sessionId}_vote ==>`, content) + console.log(`${sessionId}_vote ==>`, content); if (content) { - setLastMessageToVote(content) + setLastMessageToVote(content); } }); return () => { socket.off(`${sessionId}_vote`); - setLastMessageToVote(null) + setLastMessageToVote(null); }; - }, [sessionId, socket]) + }, [sessionId, socket]); function reset() { setMessages([]); } @@ -153,16 +192,13 @@ const ChatProvider: React.FC<{ children: ReactNode }> = ({ children }) => { failedMessage, reset, setLastMessageId, - lastMessageToVote + lastMessageToVote, }; return ( - - {children} - + {children} ); }; - // eslint-disable-next-line react-refresh/only-export-components export { ChatProvider, useChat }; From c23276efa1e8d922ca08e6255229c0590352c4d5 Mon Sep 17 00:00:00 2001 From: shanurrahman Date: Mon, 19 Feb 2024 02:27:21 -0800 Subject: [PATCH 2/6] force websocket --- copilot-widget/index.html | 6 +++--- copilot-widget/lib/contexts/Controller.tsx | 2 ++ copilot-widget/lib/hooks/useInitialData.tsx | 2 +- llm-server/app.py | 13 ++++++------- llm-server/routes/chat/chat_dto.py | 1 + 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/copilot-widget/index.html b/copilot-widget/index.html index 694d9a0ca..c9285d408 100644 --- a/copilot-widget/index.html +++ b/copilot-widget/index.html @@ -75,9 +75,9 @@