diff --git a/Makefile b/Makefile index d2adb3a7f..8712a0aeb 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ run_frontend: cd src/frontend && npm start run_backend: - poetry run uvicorn langflow.main:app --port 5003 --reload --log-level debug + poetry run uvicorn langflow.main:app --port 7860 --reload --log-level debug build_frontend: cd src/frontend && CI='' npm run build diff --git a/src/frontend/src/modals/chatModal/index.tsx b/src/frontend/src/modals/chatModal/index.tsx index 5b3810796..c3eefaf6c 100644 --- a/src/frontend/src/modals/chatModal/index.tsx +++ b/src/frontend/src/modals/chatModal/index.tsx @@ -1,8 +1,8 @@ import { Dialog, Transition } from "@headlessui/react"; import { - ChatBubbleOvalLeftEllipsisIcon, - LockClosedIcon, - PaperAirplaneIcon, + ChatBubbleOvalLeftEllipsisIcon, + LockClosedIcon, + PaperAirplaneIcon, } from "@heroicons/react/24/outline"; import { Fragment, useContext, useEffect, useRef, useState } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; @@ -20,311 +20,313 @@ import ChatInput from "./chatInput"; const _ = require("lodash"); export default function ChatModal({ - flow, - open, - setOpen, + flow, + open, + setOpen, }: { - open: boolean; - setOpen: Function; - flow: FlowType; + open: boolean; + setOpen: Function; + flow: FlowType; }) { - const { updateFlow } = useContext(TabsContext); - const [chatValue, setChatValue] = useState(""); - const [chatHistory, setChatHistory] = useState([]); - const { reactFlowInstance } = useContext(typesContext); - const { setErrorData, setNoticeData } = useContext(alertContext); - const [ws, setWs] = useState(null); - const [lockChat, setLockChat] = useState(false); - const addChatHistory = ( - message: string, - isSend: boolean, - thought?: string, - files?: Array - ) => { - setChatHistory((old) => { - let newChat = _.cloneDeep(old); - if (files) { - newChat.push({ message, isSend, files,thought }); - } else if (thought) { - newChat.push({ message, isSend, thought }); - } else { - newChat.push({ message, isSend }); - } - return newChat; - }); - }; + const { updateFlow } = useContext(TabsContext); + const [chatValue, setChatValue] = useState(""); + const [chatHistory, setChatHistory] = useState([]); + const { reactFlowInstance } = useContext(typesContext); + const { setErrorData, setNoticeData } = useContext(alertContext); + const [ws, setWs] = useState(null); + const [lockChat, setLockChat] = useState(false); + const addChatHistory = ( + message: string, + isSend: boolean, + thought?: string, + files?: Array + ) => { + setChatHistory((old) => { + let newChat = _.cloneDeep(old); + if (files) { + newChat.push({ message, isSend, files, thought }); + } else if (thought) { + newChat.push({ message, isSend, thought }); + } else { + newChat.push({ message, isSend }); + } + return newChat; + }); + }; - function connectWS() { - const newWs = new WebSocket(`ws://127.0.0.1:5003/chat/${flow.id}`); - newWs.onopen = () => { - console.log("WebSocket connection established!"); - }; - newWs.onmessage = (event) => { - try { - setLockChat(false); - const data = JSON.parse(event.data); - console.log("Received data:", data); - //get chat history - if (Array.isArray(data)) { - console.log(data); + function connectWS() { + const newWs = new WebSocket(`ws://127.0.0.1:7860/chat/${flow.id}`); + newWs.onopen = () => { + console.log("WebSocket connection established!"); + }; + newWs.onmessage = (event) => { + try { + setLockChat(false); + const data = JSON.parse(event.data); + console.log("Received data:", data); + //get chat history + if (Array.isArray(data)) { + console.log(data); - setChatHistory((_) => { - let newChatHistory: ChatMessageType[] = []; - data.forEach( - (chatItem: { - intermediate_steps?: "string"; - is_bot: boolean; - message: string; - type: string; - files?: Array; - }) => { - if (chatItem.message) { - newChatHistory.push( - chatItem.files - ? { - isSend: !chatItem.is_bot, - message: chatItem.message, - thought: chatItem.intermediate_steps, - files: chatItem.files, - } - : { - isSend: !chatItem.is_bot, - message: chatItem.message, - thought: chatItem.intermediate_steps, - } - ); - } - } - ); - return newChatHistory; - }); - } - if (data.type === "end") { - if (data.files) { - addChatHistory( - data.message, - false, - data.intermediate_steps, - data.files - ); - } else { - addChatHistory(data.message, false, data.intermediate_steps); - } - } - if (data.type == "file") { - console.log(data); - } - } catch (error) { - if(event.data!=="Error: 1005"){ - setErrorData({ title: event.data }); + setChatHistory((_) => { + let newChatHistory: ChatMessageType[] = []; + data.forEach( + (chatItem: { + intermediate_steps?: "string"; + is_bot: boolean; + message: string; + type: string; + files?: Array; + }) => { + if (chatItem.message) { + newChatHistory.push( + chatItem.files + ? { + isSend: !chatItem.is_bot, + message: chatItem.message, + thought: chatItem.intermediate_steps, + files: chatItem.files, + } + : { + isSend: !chatItem.is_bot, + message: chatItem.message, + thought: chatItem.intermediate_steps, + } + ); + } + } + ); + return newChatHistory; + }); + } + if (data.type === "end") { + if (data.files) { + addChatHistory( + data.message, + false, + data.intermediate_steps, + data.files + ); + } else { + addChatHistory(data.message, false, data.intermediate_steps); + } + } + if (data.type == "file") { + console.log(data); + } + } catch (error) { + if (event.data !== "Error: 1005") { + setErrorData({ title: event.data }); + } + } + }; + newWs.onclose = (_) => { + if (open) { + setLockChat(false); + setTimeout(() => { + connectWS(); + }, 100); + } + }; + setWs(newWs); - } - } - }; - newWs.onclose = (_) => { - if (open) { - setLockChat(false); - setTimeout(() => { - connectWS(); - }, 100); - } - }; - setWs(newWs); + return newWs; + } - return newWs; - } + useEffect(() => { + let newWs = connectWS(); + return () => { + newWs.close(); + }; + }, []); - useEffect(() => { - let newWs = connectWS(); - return () => { - newWs.close(); - }; - }, []); + async function sendAll(data: sendAllProps) { + if (ws) { + ws.send(JSON.stringify(data)); + } + } - async function sendAll(data: sendAllProps) { - if (ws) { - ws.send(JSON.stringify(data)); - } - } + useEffect(() => { + if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" }); + }, [chatHistory]); - useEffect(() => { - if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" }); - }, [chatHistory]); + useEffect(() => { + if (ws && ws.readyState === ws.CLOSED) { + setLockChat(false); + } + }, [lockChat]); - useEffect(() => { - if (ws && ws.readyState === ws.CLOSED) { - setLockChat(false); - } - }, [lockChat]); + function validateNode(n: NodeType): Array { + if (!n.data?.node?.template || !Object.keys(n.data.node.template)) { + setNoticeData({ + title: + "We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", + }); + return []; + } - function validateNode(n: NodeType): Array { - if (!n.data?.node?.template || !Object.keys(n.data.node.template)) { - setNoticeData({ - title: - "We've noticed a potential issue with a node in the flow. Please review it and, if necessary, submit a bug report with your exported flow file. Thank you for your help!", - }); - return []; - } + const { + type, + node: { template }, + } = n.data; - const { - type, - node: { template }, - } = n.data; + return Object.keys(template).reduce( + (errors: Array, t) => + errors.concat( + template[t].required && + template[t].show && + (!template[t].value || template[t].value === "") && + !reactFlowInstance + .getEdges() + .some( + (e) => + e.targetHandle.split("|")[1] === t && + e.targetHandle.split("|")[2] === n.id + ) + ? [ + `${type} is missing ${ + template.display_name + ? template.display_name + : snakeToNormalCase(template[t].name) + }.`, + ] + : [] + ), + [] as string[] + ); + } - return Object.keys(template).reduce( - (errors: Array, t) => - errors.concat( - template[t].required && - template[t].show && - (!template[t].value || template[t].value === "") && - !reactFlowInstance - .getEdges() - .some( - (e) => - e.targetHandle.split("|")[1] === t && - e.targetHandle.split("|")[2] === n.id - ) - ? [ - `${type} is missing ${ - template.display_name - ? template.display_name - : snakeToNormalCase(template[t].name) - }.`, - ] - : [] - ), - [] as string[] - ); - } + function validateNodes() { + return reactFlowInstance + .getNodes() + .flatMap((n: NodeType) => validateNode(n)); + } - function validateNodes() { - return reactFlowInstance - .getNodes() - .flatMap((n: NodeType) => validateNode(n)); - } + const ref = useRef(null); - const ref = useRef(null); + function sendMessage() { + if (chatValue !== "") { + let nodeValidationErrors = validateNodes(); + if (nodeValidationErrors.length === 0) { + setLockChat(true); + let message = chatValue; + setChatValue(""); + addChatHistory(message, true); - function sendMessage() { - if (chatValue !== "") { - let nodeValidationErrors = validateNodes(); - if (nodeValidationErrors.length === 0) { - setLockChat(true); - let message = chatValue; - setChatValue(""); - addChatHistory(message, true); + sendAll({ + ...reactFlowInstance.toObject(), + message, + chatHistory, + name: flow.name, + description: flow.description, + }); + } else { + setErrorData({ + title: "Oops! Looks like you missed some required information:", + list: nodeValidationErrors, + }); + } + } else { + setErrorData({ + title: "Error sending message", + list: ["The message cannot be empty."], + }); + } + } + function clearChat() { + setChatHistory([]); + ws.send(JSON.stringify({ clear_history: true })); + } - sendAll({ - ...reactFlowInstance.toObject(), - message, - chatHistory, - name: flow.name, - description: flow.description, - }); - } else { - setErrorData({ - title: "Oops! Looks like you missed some required information:", - list: nodeValidationErrors, - }); - } - } else { - setErrorData({ - title: "Error sending message", - list: ["The message cannot be empty."], - }); - } - } - function clearChat() { - setChatHistory([]); - ws.send(JSON.stringify({ clear_history: true })); - } + const { closePopUp } = useContext(PopUpContext); + function setModalOpen(x: boolean) { + setOpen(x); + if (x === false) { + setTimeout(() => { + closePopUp(); + }, 300); + } + } + return ( + + + +
+ - const { closePopUp } = useContext(PopUpContext); - function setModalOpen(x: boolean) { - setOpen(x); - if (x === false) { - setTimeout(() => { - closePopUp(); - }, 300); - } - } - return ( - - - -
- - -
-
- - -
- -
-
- {chatHistory.length > 0 ? ( - chatHistory.map((c, i) => ) - ) : ( -
- - 👋 LangFlow Chat - -
-
- - Start a conversation and click the agent’s thoughts{" "} - - - {" "} - to inspect the chaining process. - -
-
- )} -
-
-
-
- -
-
-
-
-
-
-
-
- ); +
+
+ + +
+ +
+
+ {chatHistory.length > 0 ? ( + chatHistory.map((c, i) => ) + ) : ( +
+ + 👋{" "} + + LangFlow Chat + + +
+
+ + Start a conversation and click the agent’s thoughts{" "} + + + {" "} + to inspect the chaining process. + +
+
+ )} +
+
+
+
+ +
+
+
+
+
+
+
+
+ ); }