aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA.J. Shulman <Shulman.aj@gmail.com>2024-05-30 13:58:40 -0400
committerA.J. Shulman <Shulman.aj@gmail.com>2024-05-30 13:58:40 -0400
commit7ff649c6582b7e00dcf2d7fe607699f850310ba0 (patch)
tree681ca2195a948ee86b556e6a4ba49b833f298ada
parentf07a80b23080d01411f47f331854adb3cc89e92f (diff)
fixing chatbox features
still messages appear weird when using code interpreter and now doesn't detect file links
-rw-r--r--src/client/views/collections/CollectionNoteTakingViewColumn.tsx12
-rw-r--r--src/client/views/nodes/ChatBox/ChatBox.tsx101
-rw-r--r--src/client/views/nodes/ChatBox/MessageComponent.tsx37
-rw-r--r--src/client/views/nodes/ChatBox/types.ts1
-rw-r--r--src/server/ApiManagers/AssistantManager.ts7
5 files changed, 70 insertions, 88 deletions
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 44ab1968d..2c6257cf2 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -1,6 +1,6 @@
/* eslint-disable jsx-a11y/control-has-associated-label */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, makeObservable, observable } from 'mobx';
+import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { lightOrDark, returnEmptyString } from '../../../ClientUtils';
@@ -88,12 +88,16 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV
};
componentDidMount(): void {
- this._ele && this.props.refList.push(this._ele);
+ runInAction(() => {
+ this._ele && this.props.refList.push(this._ele);
+ });
}
componentWillUnmount() {
- this._ele && this.props.refList.splice(this._props.refList.indexOf(this._ele), 1);
- this._ele = null;
+ runInAction(() => {
+ this._ele && this.props.refList.splice(this._props.refList.indexOf(this._ele), 1);
+ this._ele = null;
+ });
}
@undoBatch
diff --git a/src/client/views/nodes/ChatBox/ChatBox.tsx b/src/client/views/nodes/ChatBox/ChatBox.tsx
index 880c332ac..4c1550321 100644
--- a/src/client/views/nodes/ChatBox/ChatBox.tsx
+++ b/src/client/views/nodes/ChatBox/ChatBox.tsx
@@ -34,7 +34,6 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable linked_docs_to_add: Doc[] = [];
private openai: OpenAI;
- private interim_history: string = '';
private assistantID: string = '';
private threadID: string = '';
private _oldWheel: any;
@@ -74,13 +73,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
},
};
reaction(
- () => this.history.map((msg: AssistantMessage) => ({ role: msg.role, text: msg.text, image: msg.image, tool_logs: msg.tool_logs, links: msg.links })),
+ () => this.history.map((msg: AssistantMessage) => ({ role: msg.role, text: msg.text, image: msg.image, tool_logs: msg.tool_logs })),
serializableHistory => {
this.dataDoc.data = JSON.stringify(serializableHistory);
}
);
}
+ @action
toggleToolLogs = (index: number) => {
this.expandedLogIndex = this.expandedLogIndex === index ? null : index;
};
@@ -101,6 +101,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
initializeOpenAI() {
+ //console.log(process.env._CLIENT_OPENAI_KEY);
const configuration: ClientOptions = {
apiKey: process.env.OPENAI_KEY,
dangerouslyAllowBrowser: true,
@@ -114,11 +115,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
- createLink = (linkInfo: string, startIndex: number, endIndex: number, linkType: ANNOTATION_LINK_TYPE, annotationIndex: number = 0) => {
- const text = this.interim_history;
- const subString = this.current_message?.text.substring(startIndex, endIndex) ?? '';
+ createLink = (linkInfo: string, annotationText: string, linkType: ANNOTATION_LINK_TYPE) => {
+ console.log(this.current_message);
+ const text = this.current_message?.text;
+ console.log(text);
+
+ const subString = annotationText;
if (!text) return;
- const textToDisplay = `${annotationIndex}`;
+ const textToDisplay = `DASHLINK`;
let fileInfo = linkInfo;
const fileName = subString.split('/')[subString.split('/').length - 1];
if (linkType === ANNOTATION_LINK_TYPE.DOWNLOAD_FILE) {
@@ -127,17 +131,9 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const formattedLink = `[${textToDisplay}](${fileInfo}~~~${linkType})`;
console.log(formattedLink);
- const newText = text.replace(subString, formattedLink);
+ const newText = text.split(subString).join(formattedLink);
runInAction(() => {
- this.interim_history = newText;
- console.log(newText);
- this.current_message?.links?.push({
- start: startIndex,
- end: endIndex,
- url: linkType === ANNOTATION_LINK_TYPE.DOWNLOAD_FILE ? fileName : linkInfo,
- id: linkType === ANNOTATION_LINK_TYPE.DOWNLOAD_FILE ? linkInfo : undefined,
- link_type: linkType,
- });
+ if (this.current_message) this.current_message.text = newText;
});
};
@@ -192,8 +188,10 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
await this.createAssistant();
console.log('Assistant and thread created:', this.assistantID, this.threadID);
}
+
let currentText: string = '';
let currentToolCallMessage: string = '';
+ let current_message_id: string | null = null;
// Send the user's input to the assistant
await this.openai.beta.threads.messages.create(this.threadID, {
@@ -207,14 +205,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
assistant_id: this.assistantID,
})
.on('runStepCreated', (runStep: RunStep) => {
- currentText = '';
runInAction(() => {
- this.current_message = { role: ASSISTANT_ROLE.ASSISTANT, text: currentText, tool_logs: '', links: [] };
+ this.isLoading = true;
+ //intentionally don't merge run steps' messages and keep them as seperate messages on the interface
+ this.current_message = { role: ASSISTANT_ROLE.ASSISTANT, text: '', tool_logs: '' };
});
- this.isLoading = true;
})
.on('toolCallDelta', (toolCallDelta, snapshot) => {
- this.isLoading = false;
+ runInAction(() => (this.isLoading = false));
if (toolCallDelta.type === 'code_interpreter') {
if (toolCallDelta.code_interpreter?.input) {
currentToolCallMessage += toolCallDelta.code_interpreter.input;
@@ -243,31 +241,44 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
currentText += textDelta.value;
runInAction(() => {
if (this.current_message) {
- // this.current_message = {...this.current_message, text: current_text};
this.current_message.text = currentText;
}
});
})
- .on('messageDone', async event => {
- console.log(event);
- const textItem = event.content.find(item => item.type === 'text');
+ .on('messageDone', async message => {
+ console.log(this.current_message);
+ const textItem = message.content.find(item => item.type === 'text');
if (textItem && textItem.type === 'text') {
const { text } = textItem;
console.log(text.value);
try {
runInAction(() => {
- this.interim_history = text.value;
+ if (this.current_message) {
+ this.current_message.text = text.value;
+ }
});
} catch (e) {
console.error('Error parsing JSON response:', e);
}
+ console.log(this.current_message);
const { annotations } = text;
console.log('Annotations: ' + annotations);
- let index = 0;
- annotations.forEach(async annotation => {
- console.log(' ' + annotation);
- console.log(' ' + annotation.text);
+ const uniqueAnnotations = annotations.filter(
+ (annotation => {
+ const seenAnnotationTexts = new Set<string>();
+ return annotation => {
+ if (seenAnnotationTexts.has(annotation.text)) {
+ return false;
+ } else {
+ seenAnnotationTexts.add(annotation.text);
+ return true;
+ }
+ };
+ })()
+ );
+
+ uniqueAnnotations.forEach(async annotation => {
if (annotation.type === 'file_path') {
const { file_path: filePath } = annotation;
const fileToDownload = filePath.file_id;
@@ -275,40 +286,38 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
if (filePath) {
console.log(filePath);
console.log(fileToDownload);
- this.createLink(fileToDownload, annotation.start_index, annotation.end_index, ANNOTATION_LINK_TYPE.DOWNLOAD_FILE);
+ console.log(annotation.text);
+ this.createLink(fileToDownload, annotation.text, ANNOTATION_LINK_TYPE.DOWNLOAD_FILE);
}
} else {
const { file_citation: fileCitation } = annotation;
if (fileCitation) {
const citedFile = await this.openai.files.retrieve(fileCitation.file_id);
const citationUrl = citedFile.filename;
- this.createLink(citationUrl, annotation.start_index, annotation.end_index, ANNOTATION_LINK_TYPE.DASH_DOC, index);
- index++;
+ console.log(annotation.text);
+ console.log(this.current_message + 'fewjfjec');
+ this.createLink(citationUrl, annotation.text, ANNOTATION_LINK_TYPE.DASH_DOC);
}
}
});
- runInAction(() => {
- if (this.current_message) {
- console.log('current message: ' + this.current_message.text);
- this.current_message.text = this.interim_history;
- this.history.push({ ...this.current_message });
- this.current_message = undefined;
- }
- });
}
+ runInAction(() => {
+ if (this.current_message?.text) {
+ this.history.push({ ...this.current_message });
+ //this.current_message = undefined;
+ }
+ });
})
- .on('toolCallDone', toolCall => {
+ .on('toolCallDone', async toolCall => {
runInAction(() => {
- if (this.current_message && currentToolCallMessage) {
- this.current_message.tool_logs = currentToolCallMessage;
+ if (this.current_message?.tool_logs) {
+ this.history.push({ ...this.current_message });
+ //this.current_message = undefined;
}
});
})
.on('imageFileDone', (content: ImageFile, snapshot: Message) => {
console.log('Image file done:', content);
- })
- .on('end', () => {
- console.log('Streaming done');
});
};
diff --git a/src/client/views/nodes/ChatBox/MessageComponent.tsx b/src/client/views/nodes/ChatBox/MessageComponent.tsx
index fced0b4d5..ef6ce83b5 100644
--- a/src/client/views/nodes/ChatBox/MessageComponent.tsx
+++ b/src/client/views/nodes/ChatBox/MessageComponent.tsx
@@ -3,8 +3,8 @@ import React from 'react';
import { observer } from 'mobx-react';
import { MathJax, MathJaxContext } from 'better-react-mathjax';
import ReactMarkdown from 'react-markdown';
-import { TbCircle0Filled, TbCircle1Filled, TbCircle2Filled, TbCircle3Filled, TbCircle4Filled, TbCircle5Filled, TbCircle6Filled, TbCircle7Filled, TbCircle8Filled, TbCircle9Filled } from 'react-icons/tb';
import { AssistantMessage } from './types';
+import { TbInfoCircleFilled } from 'react-icons/tb';
interface MessageComponentProps {
message: AssistantMessage;
@@ -29,40 +29,7 @@ const MessageComponent: React.FC<MessageComponentProps> = function ({ message, t
const url = matches ? matches[1] : href;
const linkType = matches ? matches[2] : null;
if (linkType === 'citation') {
- switch (children) {
- case '0':
- children = <TbCircle0Filled />;
- break;
- case '1':
- children = <TbCircle1Filled />;
- break;
- case '2':
- children = <TbCircle2Filled />;
- break;
- case '3':
- children = <TbCircle3Filled />;
- break;
- case '4':
- children = <TbCircle4Filled />;
- break;
- case '5':
- children = <TbCircle5Filled />;
- break;
- case '6':
- children = <TbCircle6Filled />;
- break;
- case '7':
- children = <TbCircle7Filled />;
- break;
- case '8':
- children = <TbCircle8Filled />;
- break;
- case '9':
- children = <TbCircle9Filled />;
- break;
- default:
- break;
- }
+ children = <TbInfoCircleFilled />;
}
// console.log(linkType)
const style = {
diff --git a/src/client/views/nodes/ChatBox/types.ts b/src/client/views/nodes/ChatBox/types.ts
index 8212a7050..cfda0d40e 100644
--- a/src/client/views/nodes/ChatBox/types.ts
+++ b/src/client/views/nodes/ChatBox/types.ts
@@ -19,5 +19,4 @@ export interface AssistantMessage {
quote?: string;
image?: string;
tool_logs?: string;
- links?: { start: number; end: number; url: string; id?: string; link_type: ANNOTATION_LINK_TYPE }[];
}
diff --git a/src/server/ApiManagers/AssistantManager.ts b/src/server/ApiManagers/AssistantManager.ts
index 82e48167a..f2ea83310 100644
--- a/src/server/ApiManagers/AssistantManager.ts
+++ b/src/server/ApiManagers/AssistantManager.ts
@@ -4,7 +4,7 @@ import OpenAI from 'openai';
import * as path from 'path';
import { promisify } from 'util';
import * as uuid from 'uuid';
-import { filesDirectory, publicDirectory } from '..';
+import { filesDirectory, publicDirectory } from '../SocketData';
import { Method } from '../RouteManager';
import ApiManager, { Registration } from './ApiManager';
@@ -36,7 +36,10 @@ const readFileAsync = promisify(fs.readFile);
export default class AssistantManager extends ApiManager {
protected initialize(register: Registration): void {
- const openai = new OpenAI({ apiKey: process.env.OPENAI_KEY, dangerouslyAllowBrowser: true });
+ const openai = new OpenAI({
+ apiKey: process.env._CLIENT_OPENAI_KEY, // Use client key so don't have to set key seperately for client and server.
+ dangerouslyAllowBrowser: true,
+ });
register({
method: Method.POST,