-added switch between streaming response and not, to stop streaming while using dynamic input, as it require the full response to allow json schema extraction

- fixed auto page refresh after chat reset (quick line)
- added temporary isDynamicInput as static variable for development, later to be added as dynamic setting to workspace settings menue
This commit is contained in:
sherifButt 2024-03-08 17:51:23 +00:00
parent 4817424c1a
commit 5088d8471a
5 changed files with 77 additions and 47 deletions

View File

@ -56,6 +56,7 @@ export function SlashCommands({ showing, setShowing, sendCommand }) {
onClick={() => { onClick={() => {
setShowing(false); setShowing(false);
sendCommand("/reset", true); sendCommand("/reset", true);
window.location.reload();
}} }}
className="w-full hover:cursor-pointer hover:bg-zinc-700 px-2 py-2 rounded-xl flex flex-col justify-start" className="w-full hover:cursor-pointer hover:bg-zinc-700 px-2 py-2 rounded-xl flex flex-col justify-start"
> >

View File

@ -6,12 +6,18 @@ import handleChat from "@/utils/chat";
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import { SidebarMobileHeader } from "../../Sidebar"; import { SidebarMobileHeader } from "../../Sidebar";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { extractMetaData } from "@/utils/chat/extractMetaData";
export default function ChatContainer({ workspace, knownHistory = [] }) {
export default function ChatContainer({ workspace, knownHistory = [], isDynamicInput}) {
const { threadSlug = null } = useParams(); const { threadSlug = null } = useParams();
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
const [loadingResponse, setLoadingResponse] = useState(false); const [loadingResponse, setLoadingResponse] = useState(false);
const [chatHistory, setChatHistory] = useState(knownHistory); const [chatHistory, setChatHistory] = useState(knownHistory);
const [finalizedChatHistory, setFinalizedChatHistory] =
useState(knownHistory);
const [currentInputMeta, setCurrentInputMeta] = useState(null);
const handleMessageChange = (event) => { const handleMessageChange = (event) => {
setMessage(event.target.value); setMessage(event.target.value);
}; };
@ -33,6 +39,7 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
]; ];
setChatHistory(prevChatHistory); setChatHistory(prevChatHistory);
setFinalizedChatHistory(prevChatHistory);
setMessage(""); setMessage("");
setLoadingResponse(true); setLoadingResponse(true);
}; };
@ -100,6 +107,17 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
) )
); );
} }
if (isDynamicInput) {
const { remainingText, metaData } = extractMetaData(
_chatHistory[_chatHistory.length - 1].content
);
_chatHistory[_chatHistory.length - 1].content = remainingText;
setFinalizedChatHistory(_chatHistory);
setCurrentInputMeta(metaData);
console.log("metaData", metaData);
}
return; return;
} }
loadingResponse === true && fetchReply(); loadingResponse === true && fetchReply();
@ -113,7 +131,7 @@ export default function ChatContainer({ workspace, knownHistory = [] }) {
{isMobile && <SidebarMobileHeader />} {isMobile && <SidebarMobileHeader />}
<div className="flex flex-col h-full w-full md:mt-0 mt-[40px]"> <div className="flex flex-col h-full w-full md:mt-0 mt-[40px]">
<ChatHistory <ChatHistory
history={chatHistory} history={isDynamicInput ? finalizedChatHistory : chatHistory}
workspace={workspace} workspace={workspace}
sendCommand={sendCommand} sendCommand={sendCommand}
/> />

View File

@ -12,6 +12,8 @@ export default function WorkspaceChat({ loading, workspace }) {
const [history, setHistory] = useState([]); const [history, setHistory] = useState([]);
const [loadingHistory, setLoadingHistory] = useState(true); const [loadingHistory, setLoadingHistory] = useState(true);
const isDynamicInput = false;
useEffect(() => { useEffect(() => {
async function getHistory() { async function getHistory() {
if (loading) return; if (loading) return;
@ -26,13 +28,17 @@ export default function WorkspaceChat({ loading, workspace }) {
// TODO: add conditional if dynamic input is enabled in the workspace by default is false // TODO: add conditional if dynamic input is enabled in the workspace by default is false
// Append metadata to the chat history // Append metadata to the chat history
if (isDynamicInput) {
chatHistory = chatHistory.map((message) => { chatHistory = chatHistory.map((message) => {
if (message.role === "assistant") { if (message.role === "assistant") {
const { remainingText, metaData } = extractMetaData(message.content); const { remainingText, metaData } = extractMetaData(
message.content
);
return { ...message, content: remainingText, metaData }; return { ...message, content: remainingText, metaData };
} }
return message; return message;
}); });
}
setHistory(chatHistory); setHistory(chatHistory);
setLoadingHistory(false); setLoadingHistory(false);
@ -73,7 +79,7 @@ export default function WorkspaceChat({ loading, workspace }) {
} }
setEventDelegatorForCodeSnippets(); setEventDelegatorForCodeSnippets();
return <ChatContainer workspace={workspace} knownHistory={history} />; return <ChatContainer workspace={workspace} knownHistory={history} isDynamicInput={isDynamicInput} />;
} }
// Enables us to safely markdown and sanitize all responses without risk of injection // Enables us to safely markdown and sanitize all responses without risk of injection

View File

@ -5,6 +5,7 @@
*/ */
export const extractMetaData = (textResponse) => { export const extractMetaData = (textResponse) => {
console.log("textResponse", textResponse);
let remainingText = textResponse; let remainingText = textResponse;
let inString = false; let inString = false;
let char, prevChar; let char, prevChar;
@ -15,29 +16,30 @@ export const extractMetaData = (textResponse) => {
for (let i = 0; i < textResponse.length; i++) { for (let i = 0; i < textResponse.length; i++) {
char = textResponse[i]; char = textResponse[i];
if (char === '"' && prevChar !== '\\') inString = !inString; if (char === '"' && prevChar !== "\\") inString = !inString;
if (inString) continue; if (inString) continue;
if (char === '{' || char === '[') { if (char === "{" || char === "[") {
if (braceCount === 0 && bracketCount === 0) startIndex = i; if (braceCount === 0 && bracketCount === 0) startIndex = i;
if (char === '{') braceCount++; if (char === "{") braceCount++;
if (char === '[') bracketCount++; if (char === "[") bracketCount++;
} else if (char === '}' || char === ']') { } else if (char === "}" || char === "]") {
if (char === '}') braceCount--; if (char === "}") braceCount--;
if (char === ']') bracketCount--; if (char === "]") bracketCount--;
if (braceCount === 0 && bracketCount === 0 && startIndex !== null) { if (braceCount === 0 && bracketCount === 0 && startIndex !== null) {
let json = textResponse.substring(startIndex, i + 1); let json = textResponse.substring(startIndex, i + 1);
try { try {
let parsedJson = JSON.parse(json); let parsedJson = JSON.parse(json);
console.log("Parsed JSON:", parsedJson);
for (let key in parsedJson) { for (let key in parsedJson) {
if (parsedJson.hasOwnProperty(key)) { if (parsedJson.hasOwnProperty(key)) {
extractedObjects[key] = parsedJson[key]; extractedObjects[key] = parsedJson[key];
} }
} }
} catch (error) { } catch (error) {
console.error("Error parsing JSON:", error, 'in JSON:', json); console.error("Error parsing JSON:", error, "in JSON:", json);
} }
startIndex = null; startIndex = null;
} }
@ -47,7 +49,8 @@ export const extractMetaData = (textResponse) => {
// Remove any json objects from the text tat starts with ```json nad ends with ``` // Remove any json objects from the text tat starts with ```json nad ends with ```
const jsonRegex = /```json[\s\S]*?```/g; const jsonRegex = /```json[\s\S]*?```/g;
remainingText = remainingText.replace(jsonRegex, ''); remainingText = remainingText.replace(jsonRegex, "");
console.log("remainingText", remainingText);
console.log("extractedObjects", extractedObjects);
return { remainingText, metaData: extractedObjects }; return { remainingText, metaData: extractedObjects };
} }

View File

@ -97,6 +97,7 @@ export default function handleChat(
}); });
} }
setChatHistory([..._chatHistory]); setChatHistory([..._chatHistory]);
console.log("chunk: ", [..._chatHistory]);
} else if (type === "finalizeResponseStream") { } else if (type === "finalizeResponseStream") {
const chatIdx = _chatHistory.findIndex((chat) => chat.uuid === uuid); const chatIdx = _chatHistory.findIndex((chat) => chat.uuid === uuid);
if (chatIdx !== -1) { if (chatIdx !== -1) {
@ -108,6 +109,7 @@ export default function handleChat(
_chatHistory[chatIdx] = updatedHistory; _chatHistory[chatIdx] = updatedHistory;
} }
setChatHistory([..._chatHistory]); setChatHistory([..._chatHistory]);
console.log("final: ", [..._chatHistory]);
} }
} }