Spaces:
Paused
Paused
| "use client"; | |
| import { FormEvent, useEffect, useRef, useState } from 'react'; | |
| import { FileLoader } from '../components/FileLoader'; | |
| import styles from './page.module.css'; | |
| import { useChat } from 'ai/react'; | |
| const Home: React.FC = () => { | |
| // eslint-disable-next-line no-unused-vars | |
| const [isWorkerLoading, setIsWorkerLoading] = useState(false); | |
| const [searchInProgress, setSearchInProgress] = useState(false); | |
| const [searchIsLoading, setIsLoading] = useState(false); | |
| const [fileText, setFileText] = useState<string>(''); | |
| const embeddingsWorkerRef = useRef<Worker | null>(null); | |
| const { isLoading, messages, input, handleInputChange, handleSubmit } = useChat(); | |
| useEffect(() => { | |
| if (typeof window === 'undefined') return; | |
| const EmbeddingsWorker = require('worker-loader!../components/embeddingsWorker.js').default; | |
| embeddingsWorkerRef.current = new EmbeddingsWorker(); | |
| return () => { | |
| embeddingsWorkerRef.current?.terminate(); | |
| }; | |
| }, []); | |
| useEffect(() => { | |
| if (fileText && embeddingsWorkerRef.current) { | |
| embeddingsWorkerRef.current.postMessage({ | |
| action: 'addDocumentsToStore', | |
| documents: [fileText] | |
| }); | |
| } | |
| }, [fileText]); | |
| const handleSearch = () => { | |
| return new Promise((resolve) => { | |
| const handleMessage = (event: any) => { | |
| if (event.data.action === 'searchResults') { | |
| embeddingsWorkerRef.current?.removeEventListener('message', handleMessage); | |
| setSearchInProgress(false); | |
| resolve(event.data.results); | |
| } | |
| }; | |
| embeddingsWorkerRef.current?.addEventListener('message', handleMessage); | |
| embeddingsWorkerRef.current?.postMessage({ | |
| action: 'searchSimilarDocuments', | |
| query: input, | |
| topK: 5 | |
| }); | |
| }); | |
| }; | |
| const modifiedHandleSubmit = async (e: FormEvent<HTMLFormElement>) => { | |
| e.preventDefault(); | |
| if (input.trim() === '' || searchInProgress) { | |
| return; // Prevent empty submissions or when a search is already in progress | |
| } | |
| setSearchInProgress(true); | |
| try { | |
| const results = await handleSearch(); | |
| const serializedResults = JSON.stringify(results); | |
| const chatRequestOptions = { | |
| data: { vectorStoreResults: serializedResults }, | |
| }; | |
| handleSubmit(e, chatRequestOptions); | |
| } catch (error) { | |
| console.error('Error during search:', error); | |
| setSearchInProgress(false); | |
| } | |
| }; | |
| return ( | |
| <main className={styles.main}> | |
| <div className={styles.description}> | |
| <p> | |
| Upload a PDF to start the analysis. | |
| </p> | |
| <FileLoader setFileText={setFileText} /> | |
| </div> | |
| {fileText && ( | |
| <div className={styles.center}> | |
| <p>Processed Text Complete</p> | |
| </div> | |
| )} | |
| {isLoading || searchIsLoading && ( | |
| <div className={styles.spinner}> | |
| <div>...</div> | |
| </div> | |
| )} | |
| <div className={styles.chatContainer}> | |
| <div className={styles.messagesContainer}> | |
| {messages.map(m => ( | |
| <div key={m.id} className={m.role === 'user' ? styles.userMessage : styles.aiMessage}> | |
| <span className={styles.messageRole}>{m.role === 'user' ? 'You: ' : 'AI: '}</span> | |
| <span className={styles.messageContent}>{m.content}</span> | |
| </div> | |
| ))} | |
| </div> | |
| <form onSubmit={modifiedHandleSubmit} className={styles.chatForm}> | |
| <input | |
| className={styles.chatInput} | |
| value={input} | |
| onChange={handleInputChange} | |
| placeholder="Say something..." | |
| /> | |
| {(searchInProgress || isLoading) ? <button type="submit" disabled={true} className={styles.sendButton}>Loading</button> : <button type="submit" className={styles.sendButton}>Send</button>} | |
| </form> | |
| </div> | |
| </main> | |
| ); | |
| } | |
| export default Home; | |