🚀 feat: Assistants Streaming (#2159)

* chore: bump openai to 4.29.0 and npm audit fix

* chore: remove unnecessary stream field from ContentData

* feat: new enum and types for AssistantStreamEvent

* refactor(AssistantService): remove stream field and add conversationId to text ContentData
> - return `finalMessage` and `text` on run completion
> - move `processMessages` to services/Threads to avoid circular dependencies with new stream handling
> - refactor(processMessages/retrieveAndProcessFile): add new `client` field to differentiate new RunClient type

* WIP: new assistants stream handling

* chore: stores messages to StreamRunManager

* chore: add additional typedefs

* fix: pass req and openai to StreamRunManager

* fix(AssistantService): pass openai as client to `retrieveAndProcessFile`

* WIP: streaming tool i/o, handle in_progress and completed run steps

* feat(assistants): process required actions with streaming enabled

* chore: condense early return check for useSSE useEffect

* chore: remove unnecessary comments and only handle completed tool calls when not function

* feat: add TTL for assistants run abort cacheKey

* feat: abort stream runs

* fix(assistants): render streaming cursor

* fix(assistants): hide edit icon as functionality is not supported

* fix(textArea): handle pasting edge cases; first, when onChange events wouldn't fire; second, when textarea wouldn't resize

* chore: memoize Conversations

* chore(useTextarea): reverse args order

* fix: load default capabilities when an azure is configured to support assistants, but `assistants` endpoint is not configured

* fix(AssistantSelect): update form assistant model on assistant form select

* fix(actions): handle azure strict validation for function names to fix crud for actions

* chore: remove content data debug log as it fires in rapid succession

* feat: improve UX for assistant errors mid-request

* feat: add tool call localizations and replace any domain separators from azure action names

* refactor(chat): error out tool calls without outputs during handleError

* fix(ToolService): handle domain separators allowing Azure use of actions

* refactor(StreamRunManager): types and throw Error if tool submission fails
This commit is contained in:
Danny Avila 2024-03-21 22:42:25 -04:00 committed by GitHub
parent ed64c76053
commit f427ad792a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 1503 additions and 330 deletions

View file

@ -1,6 +1,6 @@
{
"name": "librechat-data-provider",
"version": "0.5.0",
"version": "0.5.1",
"description": "data services for librechat apps",
"main": "dist/index.js",
"module": "dist/index.es.js",

View file

@ -527,3 +527,29 @@ export const defaultOrderQuery: {
} = {
order: 'asc',
};
export enum AssistantStreamEvents {
ThreadCreated = 'thread.created',
ThreadRunCreated = 'thread.run.created',
ThreadRunQueued = 'thread.run.queued',
ThreadRunInProgress = 'thread.run.in_progress',
ThreadRunRequiresAction = 'thread.run.requires_action',
ThreadRunCompleted = 'thread.run.completed',
ThreadRunFailed = 'thread.run.failed',
ThreadRunCancelling = 'thread.run.cancelling',
ThreadRunCancelled = 'thread.run.cancelled',
ThreadRunExpired = 'thread.run.expired',
ThreadRunStepCreated = 'thread.run.step.created',
ThreadRunStepInProgress = 'thread.run.step.in_progress',
ThreadRunStepCompleted = 'thread.run.step.completed',
ThreadRunStepFailed = 'thread.run.step.failed',
ThreadRunStepCancelled = 'thread.run.step.cancelled',
ThreadRunStepExpired = 'thread.run.step.expired',
ThreadRunStepDelta = 'thread.run.step.delta',
ThreadMessageCreated = 'thread.message.created',
ThreadMessageInProgress = 'thread.message.in_progress',
ThreadMessageCompleted = 'thread.message.completed',
ThreadMessageIncomplete = 'thread.message.incomplete',
ThreadMessageDelta = 'thread.message.delta',
ErrorEvent = 'error',
}

View file

@ -275,5 +275,9 @@ export const listConversationsByQuery = (
}
};
export const deleteAction = async (assistant_id: string, action_id: string): Promise<void> =>
request.delete(endpoints.assistants(`actions/${assistant_id}/${action_id}`));
export const deleteAction = async (
assistant_id: string,
action_id: string,
model: string,
): Promise<void> =>
request.delete(endpoints.assistants(`actions/${assistant_id}/${action_id}/${model}`));

View file

@ -186,6 +186,7 @@ export enum ContentTypes {
TEXT = 'text',
TOOL_CALL = 'tool_call',
IMAGE_FILE = 'image_file',
ERROR = 'error',
}
export enum StepTypes {
@ -236,6 +237,7 @@ export type ContentPart = (CodeToolCall | RetrievalToolCall | FunctionToolCall |
PartMetadata;
export type TMessageContentParts =
| { type: ContentTypes.ERROR; text: Text & PartMetadata }
| { type: ContentTypes.TEXT; text: Text & PartMetadata }
| {
type: ContentTypes.TOOL_CALL;
@ -243,16 +245,20 @@ export type TMessageContentParts =
}
| { type: ContentTypes.IMAGE_FILE; image_file: ImageFile & PartMetadata };
export type TContentData = TMessageContentParts & {
export type StreamContentData = TMessageContentParts & {
index: number;
};
export type TContentData = StreamContentData & {
messageId: string;
conversationId: string;
userMessageId: string;
thread_id: string;
index: number;
stream?: boolean;
};
export const actionDelimiter = '_action_';
export const actionDomainSeparator = '---';
export enum AuthTypeEnum {
ServiceHttp = 'service_http',

View file

@ -56,6 +56,7 @@ export type UpdateActionVariables = {
functions: FunctionTool[];
metadata: ActionMetadata;
action_id?: string;
model: string;
};
export type UploadAssistantAvatarOptions = {
@ -109,6 +110,7 @@ export type UpdateActionOptions = {
export type DeleteActionVariables = {
assistant_id: string;
action_id: string;
model: string;
};
export type DeleteActionOptions = {

View file

@ -8,7 +8,7 @@
"target": "es5",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"lib": ["es2017", "dom"],
"lib": ["es2017", "dom", "ES2021.String"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,