👥 fix(assistants): Improve Error handling (#2012)

* feat: make assistants endpoint appendable since message state is not managed by LibreChat

* fix(ask): search currentMessages for thread_id if it's not defined

* refactor(abortMiddleware): remove use of `overrideProps` and spread unknown fields instead

* chore: remove console.log in `abortConversation`

* refactor(assistants): improve error handling/cancellation flow
This commit is contained in:
Danny Avila 2024-03-07 10:50:01 -05:00 committed by GitHub
parent d4fe8fc82d
commit 18edd2660b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 77 additions and 25 deletions

View file

@ -11,10 +11,10 @@ const {
} = require('~/server/services/Threads');
const { runAssistant, createOnTextProgress } = require('~/server/services/AssistantService');
const { addTitle, initializeClient } = require('~/server/services/Endpoints/assistant');
const { sendResponse, sendMessage } = require('~/server/utils');
const { createRun, sleep } = require('~/server/services/Runs');
const { getConvo } = require('~/models/Conversation');
const getLogStores = require('~/cache/getLogStores');
const { sendMessage } = require('~/server/utils');
const { logger } = require('~/config');
const router = express.Router();
@ -101,32 +101,52 @@ router.post('/', validateModel, buildEndpointOption, setHeaders, async (req, res
let completedRun;
const handleError = async (error) => {
const messageData = {
thread_id,
assistant_id,
conversationId,
parentMessageId,
sender: 'System',
user: req.user.id,
shouldSaveMessage: false,
messageId: responseMessageId,
endpoint: EModelEndpoint.assistants,
};
if (error.message === 'Run cancelled') {
return res.end();
}
if (error.message === 'Request closed' && completedRun) {
} else if (error.message === 'Request closed' && completedRun) {
return;
} else if (error.message === 'Request closed') {
logger.debug('[/assistants/chat/] Request aborted on close');
} else {
logger.error('[/assistants/chat/]', error);
}
logger.error('[/assistants/chat/]', error);
if (!openai || !thread_id || !run_id) {
return res.status(500).json({ error: 'The Assistant run failed to initialize' });
return sendResponse(res, messageData, 'The Assistant run failed to initialize');
}
await sleep(3000);
try {
const status = await cache.get(cacheKey);
if (status === 'cancelled') {
logger.debug('[/assistants/chat/] Run already cancelled');
return res.end();
}
await cache.delete(cacheKey);
const cancelledRun = await openai.beta.threads.runs.cancel(thread_id, run_id);
logger.debug('Cancelled run:', cancelledRun);
logger.debug('[/assistants/chat/] Cancelled run:', cancelledRun);
} catch (error) {
logger.error('[abortRun] Error cancelling run', error);
logger.error('[/assistants/chat/] Error cancelling run', error);
}
await sleep(2000);
let run;
try {
const run = await openai.beta.threads.runs.retrieve(thread_id, run_id);
run = await openai.beta.threads.runs.retrieve(thread_id, run_id);
await recordUsage({
...run.usage,
model: run.model,
@ -137,6 +157,7 @@ router.post('/', validateModel, buildEndpointOption, setHeaders, async (req, res
logger.error('[/assistants/chat/] Error fetching or processing run', error);
}
let finalEvent;
try {
const runMessages = await checkMessageGaps({
openai,
@ -146,22 +167,18 @@ router.post('/', validateModel, buildEndpointOption, setHeaders, async (req, res
latestMessageId: responseMessageId,
});
const finalEvent = {
finalEvent = {
title: 'New Chat',
final: true,
conversation: await getConvo(req.user.id, conversationId),
runMessages,
};
if (res.headersSent && finalEvent) {
return sendMessage(res, finalEvent);
}
res.json(finalEvent);
} catch (error) {
logger.error('[/assistants/chat/] Error finalizing error process', error);
return res.status(500).json({ error: 'The Assistant run failed' });
return sendResponse(res, messageData, 'The Assistant run failed');
}
return sendResponse(res, finalEvent);
};
try {
@ -172,10 +189,12 @@ router.post('/', validateModel, buildEndpointOption, setHeaders, async (req, res
});
if (convoId && !_thread_id) {
completedRun = true;
throw new Error('Missing thread_id for existing conversation');
}
if (!assistant_id) {
completedRun = true;
throw new Error('Missing assistant_id');
}