diff options
author | A.J. Shulman <Shulman.aj@gmail.com> | 2024-07-11 10:21:56 -0400 |
---|---|---|
committer | A.J. Shulman <Shulman.aj@gmail.com> | 2024-07-11 10:21:56 -0400 |
commit | e0e4871224e626240dc899c653cd0eb9f54c3693 (patch) | |
tree | 36067e21ee81d47977e971e8f9ebced9c7ebeef2 /src | |
parent | f82343158f423fdca136a639ec61c1e8d93b5467 (diff) |
working with new documents
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/ChatBox/Agent.ts | 12 | ||||
-rw-r--r-- | src/client/views/nodes/ChatBox/ChatBox.tsx | 68 | ||||
-rw-r--r-- | src/client/views/nodes/ChatBox/tools/WikipediaTool.ts | 20 | ||||
-rw-r--r-- | src/server/ApiManagers/AssistantManager.ts | 27 |
4 files changed, 82 insertions, 45 deletions
diff --git a/src/client/views/nodes/ChatBox/Agent.ts b/src/client/views/nodes/ChatBox/Agent.ts index 63363ab0b..6757b2ce8 100644 --- a/src/client/views/nodes/ChatBox/Agent.ts +++ b/src/client/views/nodes/ChatBox/Agent.ts @@ -27,6 +27,11 @@ export class Agent { }; } + private refreshSummaries(): void { + this.summaries = this.vectorstore ? this.vectorstore.getSummaries() : 'No documents available.'; + this.tools.rag = new RAGTool(this.vectorstore, this.summaries); + } + private formatChatHistory(): string { let history = '<chat_history>\n'; for (const message of this.messages) { @@ -41,7 +46,7 @@ export class Agent { } async askAgent(question: string, maxTurns: number = 8): Promise<string> { - this.tools.rag = new RAGTool(this.vectorstore, this.vectorstore ? this.vectorstore.getSummaries() : 'No documents available.'); + this.refreshSummaries(); console.log(`Starting query: ${question}`); this.messages.push({ role: 'user', content: question }); const chatHistory = this.formatChatHistory(); @@ -98,7 +103,7 @@ export class Agent { try { const observation = await this.processAction(currentAction, step[key]); const nextPrompt = [{ type: 'text', text: '<observation>' }, ...observation, { type: 'text', text: '</observation>' }]; - console.log('Action result: ' + observation); + console.log(observation); this.interMessages.push({ role: 'user', content: nextPrompt }); break; } catch (error) { @@ -114,11 +119,12 @@ export class Agent { const answerContent = builder.build({ answer: step[key] }); this.messages.push({ role: 'assistant', content: answerContent }); this.interMessages = []; + console.log(this.messages); return answerContent; } } } - + console.log(this.messages); console.log('Reached maximum turns. Ending query.'); return '<error>Reached maximum turns without finding an answer</error>'; } diff --git a/src/client/views/nodes/ChatBox/ChatBox.tsx b/src/client/views/nodes/ChatBox/ChatBox.tsx index 2ce1ebdd2..64ab2888b 100644 --- a/src/client/views/nodes/ChatBox/ChatBox.tsx +++ b/src/client/views/nodes/ChatBox/ChatBox.tsx @@ -1,4 +1,4 @@ -import { action, makeObservable, observable, observe, reaction, runInAction } from 'mobx'; +import { action, computed, makeObservable, observable, observe, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import OpenAI, { ClientOptions } from 'openai'; import * as React from 'react'; @@ -18,6 +18,7 @@ import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentVie import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; import { Agent } from './Agent'; import dotenv from 'dotenv'; +import { DocData } from '../../../../fields/DocSymbols'; dotenv.config(); @observer @@ -30,7 +31,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { @observable expandedScratchpadIndex: number | null = null; @observable linked_docs_to_add: Doc[] = []; @observable inputValue: string = ''; + @observable private _visibleDocs: Doc[] = []; private openai: OpenAI; + private vectorstore_id: string; private documents: AI_Document[] = []; private _oldWheel: any; private vectorstore: Vectorstore; @@ -46,7 +49,6 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this.openai = this.initializeOpenAI(); this.history = [{ role: ASSISTANT_ROLE.ASSISTANT, text: 'Welcome to the Document Analyser Assistant! Link a document or ask questions to get started.' }]; this.openai = this.initializeOpenAI(); - this.getOtherDocs(); this.vectorstore = new Vectorstore(); this.agent = new Agent(this.vectorstore); // Initialize the Agent @@ -59,22 +61,20 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { } @action - getOtherDocs = async () => { - const visible_docs = (CollectionFreeFormDocumentView.from(this._props.DocumentView?.())?._props.parent as CollectionFreeFormView)?.childDocs - .filter(doc => doc != this.Document) - .map(d => DocCast(d?.annotationOn, d)) - .filter(d => d); - + addAIDocs = async (visible_docs: Doc[]) => { console.log('All Docs:', visible_docs); - visible_docs?.forEach(async doc => { - const local_file_path: string = CsvCast(doc.data, PDFCast(doc.data)).url?.pathname; - if (local_file_path) { - const { document_json } = await Networking.PostToServer('/createDocument', { file_path: local_file_path }); - const ai_document: AI_Document = convertToAIDocument(document_json); - this.documents.push(ai_document); - await this.vectorstore.addDocument(ai_document); - doc['ai_document'] = document_json; + if (doc[DocData].ai_document) { + this.documents.push(convertToAIDocument(JSON.parse(StrCast(doc[DocData].ai_document)))); + } else { + const local_file_path: string = CsvCast(doc.data, PDFCast(doc.data))?.url?.pathname; + if (local_file_path) { + const { document_json } = await Networking.PostToServer('/createDocument', { file_path: local_file_path }); + const ai_document: AI_Document = convertToAIDocument(document_json); + this.documents.push(ai_document); + await this.vectorstore.addDocument(ai_document); + doc[DocData].ai_document = JSON.stringify(document_json); + } } }); this.isInitializing = false; @@ -120,8 +120,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { textInput.value = ''; runInAction(() => { this.history.push({ role: ASSISTANT_ROLE.USER, text: trimmedText }); + this.isLoading = true; }); - this.isLoading = true; + const response = await this.agent.askAgent(trimmedText); // Use the chatbot to get the response runInAction(() => { this.history.push(this.parseAssistantResponse(response)); @@ -133,7 +134,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { this.history.push({ role: ASSISTANT_ROLE.ASSISTANT, text: 'Sorry, I encountered an error while processing your request.' }); }); } finally { - this.isLoading = false; + runInAction(() => { + this.isLoading = false; + }); } } }; @@ -236,20 +239,15 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { } } reaction( - () => { - const linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.Document) - .map(d => DocCast(LinkManager.getOppositeAnchor(d, this.Document))) - .map(d => DocCast(d?.annotationOn, d)) - .filter(d => d); - return linkedDocs; - }, - linked => this.linked_docs_to_add.push(...linked.filter(linkedDoc => !this.linked_docs_to_add.includes(linkedDoc))) + () => this.visibleDocs, + visibleDocs => { + this._visibleDocs = visibleDocs; + } ); - observe( // right now this skips during initialization which is necessary because it would be blank // However, it will upload the same link twice when it is - this.linked_docs_to_add, + this._visibleDocs, change => { // observe pushes/splices on a user link DB 'data' field (should only happen for local changes) switch (change.type as any) { @@ -257,9 +255,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { if ((change as any).addedCount > 0) { // maybe check here if its already in the urls datadoc array so doesn't add twice console.log((change as any).added as Doc[]); - ((change as any).added as Doc[]).forEach(doc => { - this.uploadNewDocument(doc); - }); + this.addAIDocs((change as any).added as Doc[]); } // (change as any).removed.forEach((link: any) => remLinkFromDoc(toRealField(link))); break; @@ -269,6 +265,16 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { }, true ); + runInAction(() => { + if (!this._visibleDocs.length) { + this.isInitializing = false; + } + }); + } + + @computed + get visibleDocs() { + return (CollectionFreeFormDocumentView.from(this._props.DocumentView?.())?._props.parent as CollectionFreeFormView)?.childDocs.filter(doc => doc != this.Document) ?? []; } @action diff --git a/src/client/views/nodes/ChatBox/tools/WikipediaTool.ts b/src/client/views/nodes/ChatBox/tools/WikipediaTool.ts index 8ef2830d4..e2c5009a1 100644 --- a/src/client/views/nodes/ChatBox/tools/WikipediaTool.ts +++ b/src/client/views/nodes/ChatBox/tools/WikipediaTool.ts @@ -1,3 +1,5 @@ +import { title } from 'process'; +import { Networking } from '../../../../Network'; import { BaseTool } from './BaseTool'; import axios from 'axios'; @@ -10,7 +12,7 @@ export class WikipediaTool extends BaseTool<{ title: string }> { title: { type: 'string', description: 'The title of the Wikipedia article to search', - required: 'true', + required: true, }, }, 'Provide simply the title you want to search on Wikipedia and nothing more. If re-using this tool, try a different title for different information.', @@ -19,15 +21,11 @@ export class WikipediaTool extends BaseTool<{ title: string }> { } async execute(args: { title: string }): Promise<any> { - const response = await axios.get('https://en.wikipedia.org/w/api.php', { - params: { - action: 'query', - list: 'search', - srsearch: args.title, - format: 'json', - }, - }); - const result = response.data.query.search[0].snippet; - return [{ type: 'text', text: result }]; + try { + const { text } = await Networking.PostToServer('/getWikipediaSummary', { title: args.title }); + return [{ type: 'text', text: text }]; + } catch (error) { + return [{ type: 'text', text: 'An error occurred while fetching the article.' }]; + } } } diff --git a/src/server/ApiManagers/AssistantManager.ts b/src/server/ApiManagers/AssistantManager.ts index 8a5f12c2b..d5a8ebeb3 100644 --- a/src/server/ApiManagers/AssistantManager.ts +++ b/src/server/ApiManagers/AssistantManager.ts @@ -150,6 +150,33 @@ export default class AssistantManager extends ApiManager { register({ method: Method.POST, + subscription: '/getWikipediaSummary', + secureHandler: async ({ req, res }) => { + const { title } = req.body; + try { + const response = await axios.get('https://en.wikipedia.org/w/api.php', { + params: { + action: 'query', + list: 'search', + srsearch: title, + format: 'json', + }, + }); + const summary = response.data.query.search[0].snippet; + if (!summary || summary.length === 0 || summary === '' || summary === ' ') { + res.send({ text: 'No article found with that title.' }); + } else { + res.send({ text: summary }); + } + } catch (error: any) { + console.error('Error retrieving article summary from Wikipedia:', error); + res.status(500).send({ error: 'Error retrieving article summary from Wikipedia.', details: error.message }); + } + }, + }); + + register({ + method: Method.POST, subscription: '/createDocument', secureHandler: async ({ req, res }) => { const { file_path } = req.body; |