aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/views/nodes/ChatBox/ChatBox.tsx29
-rw-r--r--src/client/views/nodes/ChatBox/ProgressBar.scss51
-rw-r--r--src/client/views/nodes/ChatBox/ProgressBar.tsx17
-rw-r--r--src/client/views/nodes/ChatBox/vectorstore/Vectorstore.ts60
-rw-r--r--src/server/ApiManagers/AssistantManager.ts25
5 files changed, 161 insertions, 21 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,
diff --git a/src/server/ApiManagers/AssistantManager.ts b/src/server/ApiManagers/AssistantManager.ts
index 0456c730b..54d78cd15 100644
--- a/src/server/ApiManagers/AssistantManager.ts
+++ b/src/server/ApiManagers/AssistantManager.ts
@@ -206,10 +206,16 @@ export default class AssistantManager extends ApiManager {
const jobId = response.data.job_id;
- // Poll for results
+ let progress;
let result;
while (!result) {
- await new Promise(resolve => setTimeout(resolve, 5000)); // Wait for 1 second
+ await new Promise(resolve => setTimeout(resolve, 5000)); // Wait for 5 seconds
+ const progressResponse = await axios.get(`http://localhost:8080/getProgress/${jobId}`);
+ const progress = progressResponse.data;
+
+ // Accessing the correct keys
+ console.log(`Current step: ${progress.step}, Progress within step: ${progress.progress}%`);
+
const resultResponse = await axios.get(`http://localhost:8080/getResult/${jobId}`);
if (resultResponse.status === 200) {
result = resultResponse.data;
@@ -256,6 +262,21 @@ export default class AssistantManager extends ApiManager {
});
register({
+ method: Method.GET,
+ subscription: '/getProgress/:jobId',
+ secureHandler: async ({ req, res }) => {
+ const { jobId } = req.params;
+ try {
+ const progressResponse = await axios.get(`http://localhost:8080/getProgress/${jobId}`);
+ res.json(progressResponse.data);
+ } catch (error) {
+ console.error('Error getting progress:', error);
+ res.status(500).send({ error: 'Failed to get progress', details: JSON.parse(error as string).message });
+ }
+ },
+ });
+
+ register({
method: Method.POST,
subscription: '/formatChunks',
secureHandler: async ({ req, res }) => {