diff options
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/views/nodes/ChatBox/ChatBox.tsx | 29 | ||||
| -rw-r--r-- | src/client/views/nodes/ChatBox/ProgressBar.scss | 51 | ||||
| -rw-r--r-- | src/client/views/nodes/ChatBox/ProgressBar.tsx | 17 | ||||
| -rw-r--r-- | src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts | 60 |
4 files changed, 138 insertions, 19 deletions
diff --git a/src/client/views/nodes/ChatBox/ChatBox.tsx b/src/client/views/nodes/ChatBox/ChatBox.tsx index 345bfd8d1..7e238e28b 100644 --- a/src/client/views/nodes/ChatBox/ChatBox.tsx +++ b/src/client/views/nodes/ChatBox/ChatBox.tsx @@ -23,6 +23,7 @@ import { chunk } from 'lodash'; import { DocUtils } from '../../../documents/DocUtils'; import { createRef } from 'react'; import { ClientUtils } from '../../../../ClientUtils'; +import { ProgressBar } from './ProgressBar'; dotenv.config(); @@ -33,6 +34,8 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @observable isLoading: boolean = false; @observable isUploadingDocs: boolean = false; + @observable uploadProgress: number = 0; // Track progress percentage + @observable currentStep: string = ''; // Track current step name @observable expandedScratchpadIndex: number | null = null; @observable inputValue: string = ''; @observable private linked_docs_to_add: ObservableSet<Doc> = observable.set(); @@ -73,7 +76,23 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @action addDocToVectorstore = async (newLinkedDoc: Doc) => { - await this.vectorstore.addAIDoc(newLinkedDoc); + this.isUploadingDocs = true; + this.uploadProgress = 0; + this.currentStep = 'Initializing...'; + + await this.vectorstore.addAIDoc(newLinkedDoc, this.updateProgress); + + runInAction(() => { + this.isUploadingDocs = false; + this.uploadProgress = 0; + this.currentStep = ''; + }); + }; + + @action + updateProgress = (progress: number, step: string) => { + this.uploadProgress = progress; + this.currentStep = step; }; @action @@ -481,6 +500,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { <div className="chat-box"> {this.isUploadingDocs && ( <div className="uploading-overlay"> + <div className="progress-container"> + <ProgressBar progress={this.uploadProgress} /> + <div className="step-name">{this.currentStep}</div> + </div> + </div> + )} + {this.isUploadingDocs && ( + <div className="uploading-overlay"> <div className="spinner"></div> </div> )} diff --git a/src/client/views/nodes/ChatBox/ProgressBar.scss b/src/client/views/nodes/ChatBox/ProgressBar.scss new file mode 100644 index 000000000..dcde666de --- /dev/null +++ b/src/client/views/nodes/ChatBox/ProgressBar.scss @@ -0,0 +1,51 @@ +.progress-circle { + position: relative; + width: 120px; + height: 120px; +} + +.progress-ring { + transform: rotate(-90deg); + position: absolute; + top: 0; + left: 0; +} + +.progress-ring__circle { + transition: 0.35s stroke-dashoffset; + transform: rotate(-90deg); + transform-origin: 50% 50%; +} + +.progress-text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 24px; + font-weight: bold; + color: #000; +} + +.uploading-overlay { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(255, 255, 255, 0.8); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; +} + +.progress-container { + text-align: center; +} + +.step-name { + margin-top: 10px; + font-size: 18px; + color: #333; +} diff --git a/src/client/views/nodes/ChatBox/ProgressBar.tsx b/src/client/views/nodes/ChatBox/ProgressBar.tsx new file mode 100644 index 000000000..765ddbef5 --- /dev/null +++ b/src/client/views/nodes/ChatBox/ProgressBar.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import './ProgressBar.scss'; // Create this CSS file for styling + +interface ProgressBarProps { + progress: number; +} + +export const ProgressBar: React.FC<ProgressBarProps> = ({ progress }) => { + return ( + <div className="progress-circle"> + <svg className="progress-ring" width="120" height="120"> + <circle className="progress-ring__circle" stroke="currentColor" strokeWidth="4" fill="transparent" r="56" cx="60" cy="60" style={{ strokeDasharray: 352, strokeDashoffset: 352 - (progress / 100) * 352 }} /> + </svg> + <div className="progress-text">{Math.round(progress)}%</div> + </div> + ); +}; diff --git a/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts b/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts index 4383bb72d..388574bff 100644 --- a/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts +++ b/src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts @@ -60,10 +60,11 @@ export class Vectorstore { this.index = this.pinecone.Index(this.indexName); } - async addAIDoc(doc: Doc) { + async addAIDoc(doc: Doc, progressCallback: (progress: number, step: string) => void) { console.log('Adding AI Document:', doc); const ai_document_status: string = StrCast(doc.ai_document_status); - if (ai_document_status !== undefined && ai_document_status !== null && ai_document_status !== '' && ai_document_status !== ' ' && ai_document_status !== '{}') { + + if (ai_document_status !== undefined && ai_document_status !== null && ai_document_status.trim() !== '' && ai_document_status !== '{}') { if (ai_document_status === 'IN PROGRESS') { console.log('Already in progress.'); return; @@ -72,31 +73,54 @@ export class Vectorstore { } else { doc.ai_document_status = 'PROGRESS'; console.log(doc); - console.log(PDFCast(doc.data)?.url?.pathname); - console.log(CsvCast(doc.data)?.url?.pathname); const local_file_path: string = CsvCast(doc.data)?.url?.pathname ?? PDFCast(doc.data)?.url?.pathname; console.log('Local File Path:', local_file_path); - if (local_file_path !== undefined || local_file_path !== null || local_file_path !== '') { - const { document_json } = await Networking.PostToServer('/createDocument', { file_path: local_file_path }); - console.log('Document JSON:', document_json); - //const ai_document: AI_Document = convertToAIDocument(document_json); - this.documents.push(document_json); - await this.indexDocument(JSON.parse(JSON.stringify(document_json, (key, value) => (value === null || value === undefined ? undefined : value)))); - console.log(`Document added: ${document_json.file_name}`); - doc.summary = document_json.summary; - doc.ai_doc_id = document_json.doc_id; - this._doc_ids.push(document_json.doc_id); - doc.ai_purpose = document_json.purpose; - if (doc.vectorstore_id === undefined || doc.vectorstore_id === null || doc.vectorstore_id === '' || doc.vectorstore_id === '[]') { + + if (local_file_path) { + // Start the document creation process + const response = await Networking.PostToServer('/createDocument', { file_path: local_file_path }); + const jobId = response.job_id; + + // Poll the server for progress updates + let result: any = null; + + while (!result) { + await new Promise(resolve => setTimeout(resolve, 5000)); // Polling interval + + const progressResponse = JSON.parse(await Networking.FetchFromServer(`/getProgress/${jobId}`)); + if (progressResponse) { + const progress = progressResponse.progress; + const step = progressResponse.step; + progressCallback(progress, step); + } + + const resultResponse = JSON.parse(await Networking.FetchFromServer(`/getResult/${jobId}`)); + if (resultResponse.status === 200) { + result = resultResponse.data; + } + } + + // Process the final document result + console.log('Document JSON:', result); + this.documents.push(result); + await this.indexDocument(JSON.parse(JSON.stringify(result, (key, value) => (value === null || value === undefined ? undefined : value)))); + console.log(`Document added: ${result.file_name}`); + doc.summary = result.summary; + doc.ai_doc_id = result.doc_id; + this._doc_ids.push(result.doc_id); + doc.ai_purpose = result.purpose; + + if (!doc.vectorstore_id) { doc.vectorstore_id = JSON.stringify([this._id]); } else { doc.vectorstore_id = JSON.stringify(JSON.parse(StrCast(doc.vectorstore_id)).concat([this._id])); } - if (doc.chunk_simpl === undefined || doc.chunk_simpl === null || doc.chunk_simpl === '' || doc.chunk_simpl === '[]') { + + if (!doc.chunk_simpl) { doc.chunk_simpl = JSON.stringify({ chunks: [] }); } - document_json.chunks.forEach((chunk: RAGChunk) => { + result.chunks.forEach((chunk: RAGChunk) => { const chunkToAdd = { chunkId: chunk.id, startPage: chunk.metadata.start_page, |
