import { useEffect, useRef, useState } from "react"; import { FileUpload } from "./FileUpload"; function Message({ message, role }: Message) { return (
      {message}
    
); } interface Message { message: string; role: "user" | "assistant"; } function App() { const scrollUpRef = useRef(false); const [result, setResult] = useState(""); const [error, setError] = useState(""); const [isStreaming, setIsStreaming] = useState(false); const [messages, setMessages] = useState([]); const [isFileUploaded, setIsFileUploaded] = useState(false); useEffect(() => { function handleWheel(event: WheelEvent) { if (isStreaming && event.deltaY < 0) { scrollUpRef.current = true; } } document.body.addEventListener("wheel", handleWheel); return () => { document.body.removeEventListener("wheel", handleWheel); }; }, [isStreaming]); const onKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); e.currentTarget.form?.requestSubmit(); } }; async function onSubmit(e: React.FormEvent) { e.preventDefault(); const form = e.currentTarget; const formData = new FormData(form); const msg = formData.get("msg") as string; const scrollingElement = document.scrollingElement; if (msg.trim() === "") return; scrollUpRef.current = false; scrollingElement?.scrollTo({ behavior: "smooth", top: scrollingElement?.scrollHeight, }); setIsStreaming(true); setMessages((prev) => [ ...prev, { message: msg, role: "user", }, ]); try { const session_id = sessionStorage.getItem("session_id"); const response = await fetch(form.action, { method: "POST", headers: session_id ? { "X-Session-ID": session_id, } : undefined, body: msg, }); let result = ""; const reader = response.body?.getReader(); const decoder = new TextDecoder(); form.msg.value = ""; await reader?.read().then(function processText(msg): Promise { const { value, done } = msg; const chunk = decoder.decode(value, { stream: true }); const scrollingElement = document.scrollingElement; if (done) { setResult(""); setMessages((prev) => [ ...prev, { message: result, role: "assistant", }, ]); if (scrollingElement) { scrollingElement.scrollTop = scrollingElement?.scrollHeight; } return Promise.resolve(); } result += chunk; setResult(result); if (!scrollUpRef.current && scrollingElement) { scrollingElement.scrollTop = scrollingElement.scrollHeight; } // Read some more, and call this function again return reader.read().then(processText); }); } catch (error) { setError("Error submitting message"); console.error("Error submitting message", error); } finally { setIsStreaming(false); } } return (
{!isFileUploaded && (

DocTalk

Talk to your documents.

Built with{" "} OpenAI ,{" "} FastAPI ,{" "} Qdrant ,{" "} React ,{" "} Vite , and{" "} TailwindCSS
)}
{messages.map(({ message, role }) => ( ))} {result && } {error &&

{error}

}
{isFileUploaded && (
)}
); } export default App;