From 296da7d2ac556588e045c2630465edcb84cd8e24 Mon Sep 17 00:00:00 2001 From: "Heather Logan (She/Her)" Date: Mon, 9 Oct 2023 15:19:31 +0100 Subject: [PATCH 1/3] run defence detection and chat completion concurrently --- backend/src/router.ts | 91 ++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/backend/src/router.ts b/backend/src/router.ts index 11dc07233..d96232a72 100644 --- a/backend/src/router.ts +++ b/backend/src/router.ts @@ -187,30 +187,42 @@ router.post("/openai/chat", async (req: OpenAiChatRequest, res) => { "Please send a message and current level to chat to me!"; } else { let numLevelsCompleted = req.session.numLevelsCompleted; + // use default model for levels + const chatModel = + currentLevel === LEVEL_NAMES.SANDBOX + ? req.session.chatModel + : defaultChatModel; + + // record the history before chat completion called + const chatHistoryBefore = [ + ...req.session.levelState[currentLevel].chatHistory, + ]; if (message) { chatResponse.transformedMessage = message; - // see if this message triggers any defences (only for level 3 and sandbox) - if ( - currentLevel === LEVEL_NAMES.LEVEL_3 || - currentLevel === LEVEL_NAMES.SANDBOX - ) { - chatResponse.defenceInfo = await detectTriggeredDefences( - message, - req.session.levelState[currentLevel].defences, - req.session.openAiApiKey - ); - // if message is blocked, add to chat history (not as completion) - if (chatResponse.defenceInfo.isBlocked) { - req.session.levelState[currentLevel].chatHistory.push({ - completion: null, - chatMessageType: CHAT_MESSAGE_TYPE.USER, - infoMessage: message, - }); + let openAiReply = null; + + // skip defence detection / blocking for levels 1 and 2 + if (currentLevel < LEVEL_NAMES.LEVEL_3) { + try { + openAiReply = await chatGptSendMessage( + req.session.levelState[currentLevel].chatHistory, + req.session.levelState[currentLevel].defences, + chatModel, + chatResponse.transformedMessage, + false, + req.session.openAiApiKey, + req.session.levelState[currentLevel].sentEmails, + currentLevel + ); + } catch (error) { + res.statusCode = 500; + console.log(error); + if (error instanceof Error) { + chatResponse.reply = "Failed to get chatGPT reply"; + } } - } - // if blocked, send the response - if (!chatResponse.defenceInfo.isBlocked) { + } else { // transform the message according to active defences chatResponse.transformedMessage = transformMessage( message, @@ -226,15 +238,17 @@ router.post("/openai/chat", async (req: OpenAiChatRequest, res) => { infoMessage: message, }); } - // use default model for levels - const chatModel = - currentLevel === LEVEL_NAMES.SANDBOX - ? req.session.chatModel - : defaultChatModel; + const triggeredDefencesPromise = detectTriggeredDefences( + message, + req.session.levelState[currentLevel].defences, + req.session.openAiApiKey + ).then((defenceInfo) => { + chatResponse.defenceInfo = defenceInfo; + }); // get the chatGPT reply try { - const openAiReply = await chatGptSendMessage( + const openAiReplyPromise = chatGptSendMessage( req.session.levelState[currentLevel].chatHistory, req.session.levelState[currentLevel].defences, chatModel, @@ -245,6 +259,30 @@ router.post("/openai/chat", async (req: OpenAiChatRequest, res) => { currentLevel ); + // run defence detection and chatGPT concurrently + const [, openAiReplyResolved] = await Promise.all([ + triggeredDefencesPromise, + openAiReplyPromise, + ]); + openAiReply = openAiReplyResolved; + + // if input message is blocked, restore the original chat history and add user message (not as completion) + if (chatResponse.defenceInfo.isBlocked) { + console.debug( + "input message was blocked. restoring chat history and adding user message" + ); + // set to null to stop message being returned to user + openAiReply = null; + // restore the original chat history + req.session.levelState[currentLevel].chatHistory = + chatHistoryBefore; + req.session.levelState[currentLevel].chatHistory.push({ + completion: null, + chatMessageType: CHAT_MESSAGE_TYPE.USER, + infoMessage: message, + }); + } + if (openAiReply) { chatResponse.wonLevel = openAiReply.wonLevel; chatResponse.reply = openAiReply.completion.content ?? ""; @@ -270,7 +308,6 @@ router.post("/openai/chat", async (req: OpenAiChatRequest, res) => { } } } - // if the reply was blocked then add it to the chat history if (chatResponse.defenceInfo.isBlocked) { req.session.levelState[currentLevel].chatHistory.push({ From 88fb3521845990402a08cec264a1cd2c295c3017 Mon Sep 17 00:00:00 2001 From: "Heather Logan (She/Her)" Date: Mon, 9 Oct 2023 17:03:11 +0100 Subject: [PATCH 2/3] split up chat request --- backend/src/router.ts | 412 +++++++++++++++++++++++++----------------- 1 file changed, 244 insertions(+), 168 deletions(-) diff --git a/backend/src/router.ts b/backend/src/router.ts index d96232a72..9fbbc0136 100644 --- a/backend/src/router.ts +++ b/backend/src/router.ts @@ -10,7 +10,9 @@ import { } from "./defence"; import { CHAT_MESSAGE_TYPE, + ChatHistoryMessage, ChatHttpResponse, + ChatModel, ChatModelConfiguration, MODEL_CONFIG, defaultChatModel, @@ -154,186 +156,260 @@ router.post("/email/clear", (req: EmailClearRequest, res) => { } }); -// Chat to ChatGPT -router.post("/openai/chat", async (req: OpenAiChatRequest, res) => { - // set reply params - const chatResponse: ChatHttpResponse = { - reply: "", - defenceInfo: { - blockedReason: "", - isBlocked: false, - alertedDefences: [], - triggeredDefences: [], - }, - numLevelsCompleted: req.session.numLevelsCompleted, - transformedMessage: "", - wonLevel: false, - }; +const initChatResponse: ChatHttpResponse = { + reply: "", + defenceInfo: { + blockedReason: "", + isBlocked: false, + alertedDefences: [], + triggeredDefences: [], + }, + numLevelsCompleted: 0, + transformedMessage: "", + wonLevel: false, +}; + +function handleChatError( + chatResponse: ChatHttpResponse, + blocked: boolean, + errorMsg: string +) { + console.error(errorMsg); + chatResponse.reply = errorMsg; + chatResponse.defenceInfo.isBlocked = blocked; + if (blocked) { + chatResponse.defenceInfo.blockedReason = errorMsg; + } + return chatResponse; +} - const message = req.body.message; - const currentLevel = req.body.currentLevel; - - // must have initialised openai - if (!req.session.openAiApiKey) { - res.statusCode = 401; - chatResponse.defenceInfo.isBlocked = true; - chatResponse.defenceInfo.blockedReason = - "Please enter a valid OpenAI API key to chat to me!"; - console.error(chatResponse.reply); - } else if (message === undefined || currentLevel === undefined) { - res.statusCode = 400; - chatResponse.defenceInfo.isBlocked = true; - chatResponse.defenceInfo.blockedReason = - "Please send a message and current level to chat to me!"; - } else { - let numLevelsCompleted = req.session.numLevelsCompleted; - // use default model for levels - const chatModel = - currentLevel === LEVEL_NAMES.SANDBOX - ? req.session.chatModel - : defaultChatModel; - - // record the history before chat completion called - const chatHistoryBefore = [ - ...req.session.levelState[currentLevel].chatHistory, - ]; - - if (message) { - chatResponse.transformedMessage = message; - let openAiReply = null; - - // skip defence detection / blocking for levels 1 and 2 - if (currentLevel < LEVEL_NAMES.LEVEL_3) { - try { - openAiReply = await chatGptSendMessage( - req.session.levelState[currentLevel].chatHistory, - req.session.levelState[currentLevel].defences, - chatModel, - chatResponse.transformedMessage, - false, - req.session.openAiApiKey, - req.session.levelState[currentLevel].sentEmails, - currentLevel +// Chat to ChatGPT +router.post( + "/openai/chat", + async (req: OpenAiChatRequest, res: express.Response) => { + // set reply params + let chatResponse = initChatResponse; + const message = req.body.message; + const currentLevel = req.body.currentLevel; + + // must have initialised openai + if (!req.session.openAiApiKey) { + chatResponse = handleChatError( + chatResponse, + true, + "Please enter a valid OpenAI API key to chat to me!" + ); + res.status(401).send(chatResponse); + } else if (message === undefined || currentLevel === undefined) { + chatResponse = handleChatError( + chatResponse, + true, + "Please send a message and current level to chat to me!" + ); + res.status(400).send(chatResponse); + } else { + let numLevelsCompleted = req.session.numLevelsCompleted; + // use default model for levels + const chatModel = + currentLevel === LEVEL_NAMES.SANDBOX + ? req.session.chatModel + : defaultChatModel; + + // record the history before chat completion called + const chatHistoryBefore = [ + ...req.session.levelState[currentLevel].chatHistory, + ]; + + if (message) { + chatResponse.transformedMessage = message; + // skip defence detection / blocking for levels 1 and 2 + if (currentLevel < LEVEL_NAMES.LEVEL_3) { + const lowLevelReply: ChatHttpResponse = await handleLowLevelChat( + req, + res, + chatResponse, + currentLevel, + chatModel + ); + chatResponse.reply = lowLevelReply.reply; + chatResponse.wonLevel = lowLevelReply.wonLevel; + } else { + // apply the defence detection for level 3 and sandbox + const highLevelReply: ChatHttpResponse = await handleHigherLevelChat( + req, + res, + message, + chatHistoryBefore, + chatResponse, + currentLevel, + chatModel ); - } catch (error) { - res.statusCode = 500; - console.log(error); - if (error instanceof Error) { - chatResponse.reply = "Failed to get chatGPT reply"; - } + chatResponse.reply = highLevelReply.reply; + chatResponse.wonLevel = highLevelReply.wonLevel; + chatResponse.transformedMessage = highLevelReply.transformedMessage; + chatResponse.defenceInfo = highLevelReply.defenceInfo; + chatResponse.numLevelsCompleted = highLevelReply.numLevelsCompleted; } - } else { - // transform the message according to active defences - chatResponse.transformedMessage = transformMessage( - message, - req.session.levelState[currentLevel].defences - ); - // if message has been transformed then add the original to chat history and send transformed to chatGPT - const messageIsTransformed = - chatResponse.transformedMessage !== message; - if (messageIsTransformed) { + // if the reply was blocked then add it to the chat history + if (chatResponse.defenceInfo.isBlocked) { req.session.levelState[currentLevel].chatHistory.push({ completion: null, - chatMessageType: CHAT_MESSAGE_TYPE.USER, - infoMessage: message, + chatMessageType: CHAT_MESSAGE_TYPE.BOT_BLOCKED, + infoMessage: chatResponse.defenceInfo.blockedReason, }); } - const triggeredDefencesPromise = detectTriggeredDefences( - message, - req.session.levelState[currentLevel].defences, - req.session.openAiApiKey - ).then((defenceInfo) => { - chatResponse.defenceInfo = defenceInfo; - }); - - // get the chatGPT reply - try { - const openAiReplyPromise = chatGptSendMessage( - req.session.levelState[currentLevel].chatHistory, - req.session.levelState[currentLevel].defences, - chatModel, - chatResponse.transformedMessage, - messageIsTransformed, - req.session.openAiApiKey, - req.session.levelState[currentLevel].sentEmails, - currentLevel - ); - - // run defence detection and chatGPT concurrently - const [, openAiReplyResolved] = await Promise.all([ - triggeredDefencesPromise, - openAiReplyPromise, - ]); - openAiReply = openAiReplyResolved; - - // if input message is blocked, restore the original chat history and add user message (not as completion) - if (chatResponse.defenceInfo.isBlocked) { - console.debug( - "input message was blocked. restoring chat history and adding user message" - ); - // set to null to stop message being returned to user - openAiReply = null; - // restore the original chat history - req.session.levelState[currentLevel].chatHistory = - chatHistoryBefore; - req.session.levelState[currentLevel].chatHistory.push({ - completion: null, - chatMessageType: CHAT_MESSAGE_TYPE.USER, - infoMessage: message, - }); - } - - if (openAiReply) { - chatResponse.wonLevel = openAiReply.wonLevel; - chatResponse.reply = openAiReply.completion.content ?? ""; - - // combine triggered defences - chatResponse.defenceInfo.triggeredDefences = [ - ...chatResponse.defenceInfo.triggeredDefences, - ...openAiReply.defenceInfo.triggeredDefences, - ]; - // combine blocked - chatResponse.defenceInfo.isBlocked = - openAiReply.defenceInfo.isBlocked; - - // combine blocked reason - chatResponse.defenceInfo.blockedReason = - openAiReply.defenceInfo.blockedReason; - } - } catch (error) { - res.statusCode = 500; - console.log(error); - if (error instanceof Error) { - chatResponse.reply = "Failed to get chatGPT reply"; - } + // enable next level when user wins current level + if (chatResponse.wonLevel) { + console.log("Win conditon met for level: ", currentLevel); + numLevelsCompleted = Math.max(numLevelsCompleted, currentLevel + 1); + req.session.numLevelsCompleted = numLevelsCompleted; + chatResponse.numLevelsCompleted = numLevelsCompleted; } + } else { + res.statusCode = 400; + chatResponse.reply = "Missing message"; + console.error(chatResponse.reply); } - // if the reply was blocked then add it to the chat history - if (chatResponse.defenceInfo.isBlocked) { - req.session.levelState[currentLevel].chatHistory.push({ - completion: null, - chatMessageType: CHAT_MESSAGE_TYPE.BOT_BLOCKED, - infoMessage: chatResponse.defenceInfo.blockedReason, - }); - } + } + // log and send the reply with defence info + console.log(chatResponse); + res.send(chatResponse); + } +); - // enable next level when user wins current level - if (chatResponse.wonLevel) { - console.log("Win conditon met for level: ", currentLevel); - numLevelsCompleted = Math.max(numLevelsCompleted, currentLevel + 1); - req.session.numLevelsCompleted = numLevelsCompleted; - chatResponse.numLevelsCompleted = numLevelsCompleted; - } - } else { - res.statusCode = 400; - chatResponse.reply = "Missing message"; - console.error(chatResponse.reply); +// handle the chat logic for level 1 and 2 with no defences applied +async function handleLowLevelChat( + req: OpenAiChatRequest, + res: express.Response, + chatResponse: ChatHttpResponse, + currentLevel: LEVEL_NAMES, + chatModel: ChatModel +): Promise { + let openAiReply = null; + // get the chatGPT reply + try { + openAiReply = await chatGptSendMessage( + req.session.levelState[currentLevel].chatHistory, + req.session.levelState[currentLevel].defences, + chatModel, + chatResponse.transformedMessage, + false, + req.session.openAiApiKey ?? "", + req.session.levelState[currentLevel].sentEmails, + currentLevel + ); + chatResponse.reply = openAiReply?.completion.content ?? ""; + chatResponse.wonLevel = openAiReply?.wonLevel ?? false; + } catch (error) { + res.statusCode = 500; + console.log(error); + if (error instanceof Error) { + chatResponse.reply = "Failed to get chatGPT reply"; } } - // log and send the reply with defence info - console.log(chatResponse); - res.send(chatResponse); -}); + return chatResponse; +} + +// handle the chat logic for high levels (with defence detection) +async function handleHigherLevelChat( + req: OpenAiChatRequest, + res: express.Response, + message: string, + chatHistoryBefore: ChatHistoryMessage[], + chatResponse: ChatHttpResponse, + currentLevel: LEVEL_NAMES, + chatModel: ChatModel +): Promise { + let openAiReply = null; + + // transform the message according to active defences + chatResponse.transformedMessage = transformMessage( + message, + req.session.levelState[currentLevel].defences + ); + // if message has been transformed then add the original to chat history and send transformed to chatGPT + const messageIsTransformed = chatResponse.transformedMessage !== message; + if (messageIsTransformed) { + req.session.levelState[currentLevel].chatHistory.push({ + completion: null, + chatMessageType: CHAT_MESSAGE_TYPE.USER, + infoMessage: message, + }); + } + // detect defences on input message + const triggeredDefencesPromise = detectTriggeredDefences( + message, + req.session.levelState[currentLevel].defences, + req.session.openAiApiKey ?? "" + ).then((defenceInfo) => { + chatResponse.defenceInfo = defenceInfo; + }); + + // get the chatGPT reply + try { + const openAiReplyPromise = chatGptSendMessage( + req.session.levelState[currentLevel].chatHistory, + req.session.levelState[currentLevel].defences, + chatModel, + chatResponse.transformedMessage, + messageIsTransformed, + req.session.openAiApiKey ?? "", + req.session.levelState[currentLevel].sentEmails, + currentLevel + ); + + // run defence detection and chatGPT concurrently + const [, openAiReplyResolved] = await Promise.all([ + triggeredDefencesPromise, + openAiReplyPromise, + ]); + openAiReply = openAiReplyResolved; + + // if input message is blocked, restore the original chat history and add user message (not as completion) + if (chatResponse.defenceInfo.isBlocked) { + console.debug( + "Input message was blocked. restoring chat history and adding user message" + ); + // set to null to stop message being returned to user + openAiReply = null; + + // restore the original chat history + req.session.levelState[currentLevel].chatHistory = chatHistoryBefore; + + req.session.levelState[currentLevel].chatHistory.push({ + completion: null, + chatMessageType: CHAT_MESSAGE_TYPE.USER, + infoMessage: message, + }); + } + + if (openAiReply) { + console.debug("if openai reply... ", openAiReply); + chatResponse.wonLevel = openAiReply.wonLevel; + chatResponse.reply = openAiReply.completion.content ?? ""; + + // combine triggered defences + chatResponse.defenceInfo.triggeredDefences = [ + ...chatResponse.defenceInfo.triggeredDefences, + ...openAiReply.defenceInfo.triggeredDefences, + ]; + // combine blocked + chatResponse.defenceInfo.isBlocked = openAiReply.defenceInfo.isBlocked; + + // combine blocked reason + chatResponse.defenceInfo.blockedReason = + openAiReply.defenceInfo.blockedReason; + } + } catch (error) { + chatResponse = handleChatError( + chatResponse, + false, + "Failed to get chatGPT reply" + ); + res.status(500).send(chatResponse); + } + return chatResponse; +} // get the chat history router.get("/openai/history", (req, res) => { From a1a0cf7aa95f4fdfb7bb4f58d706388cfdfff47e Mon Sep 17 00:00:00 2001 From: "Heather Logan (She/Her)" Date: Tue, 10 Oct 2023 11:47:48 +0100 Subject: [PATCH 3/3] refactor error handling --- backend/src/router.ts | 185 +++++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 103 deletions(-) diff --git a/backend/src/router.ts b/backend/src/router.ts index 9fbbc0136..dd214134a 100644 --- a/backend/src/router.ts +++ b/backend/src/router.ts @@ -156,23 +156,12 @@ router.post("/email/clear", (req: EmailClearRequest, res) => { } }); -const initChatResponse: ChatHttpResponse = { - reply: "", - defenceInfo: { - blockedReason: "", - isBlocked: false, - alertedDefences: [], - triggeredDefences: [], - }, - numLevelsCompleted: 0, - transformedMessage: "", - wonLevel: false, -}; - function handleChatError( + res: express.Response, chatResponse: ChatHttpResponse, blocked: boolean, - errorMsg: string + errorMsg: string, + statusCode = 500 ) { console.error(errorMsg); chatResponse.reply = errorMsg; @@ -180,75 +169,78 @@ function handleChatError( if (blocked) { chatResponse.defenceInfo.blockedReason = errorMsg; } - return chatResponse; + res.status(statusCode).send(chatResponse); } - // Chat to ChatGPT router.post( "/openai/chat", async (req: OpenAiChatRequest, res: express.Response) => { // set reply params - let chatResponse = initChatResponse; + const chatResponse: ChatHttpResponse = { + reply: "", + defenceInfo: { + blockedReason: "", + isBlocked: false, + alertedDefences: [], + triggeredDefences: [], + }, + numLevelsCompleted: 0, + transformedMessage: "", + wonLevel: false, + }; const message = req.body.message; const currentLevel = req.body.currentLevel; // must have initialised openai - if (!req.session.openAiApiKey) { - chatResponse = handleChatError( + if (message === undefined || currentLevel === undefined) { + handleChatError( + res, chatResponse, true, - "Please enter a valid OpenAI API key to chat to me!" + "Please send a message and current level to chat to me!", + 400 ); - res.status(401).send(chatResponse); - } else if (message === undefined || currentLevel === undefined) { - chatResponse = handleChatError( + return; + } + // set the transformed message to begin with + chatResponse.transformedMessage = message; + if (!req.session.openAiApiKey) { + handleChatError( + res, chatResponse, true, - "Please send a message and current level to chat to me!" + "Please enter a valid OpenAI API key to chat to me!", + 401 ); - res.status(400).send(chatResponse); - } else { - let numLevelsCompleted = req.session.numLevelsCompleted; - // use default model for levels - const chatModel = - currentLevel === LEVEL_NAMES.SANDBOX - ? req.session.chatModel - : defaultChatModel; - - // record the history before chat completion called - const chatHistoryBefore = [ - ...req.session.levelState[currentLevel].chatHistory, - ]; - + return; + } + let numLevelsCompleted = req.session.numLevelsCompleted; + + // use default model for levels, allow user to select in sandbox + const chatModel = + currentLevel === LEVEL_NAMES.SANDBOX + ? req.session.chatModel + : defaultChatModel; + + // record the history before chat completion called + const chatHistoryBefore = [ + ...req.session.levelState[currentLevel].chatHistory, + ]; + try { if (message) { - chatResponse.transformedMessage = message; - // skip defence detection / blocking for levels 1 and 2 + // skip defence detection / blocking for levels 1 and 2- sets chatResponse obj if (currentLevel < LEVEL_NAMES.LEVEL_3) { - const lowLevelReply: ChatHttpResponse = await handleLowLevelChat( - req, - res, - chatResponse, - currentLevel, - chatModel - ); - chatResponse.reply = lowLevelReply.reply; - chatResponse.wonLevel = lowLevelReply.wonLevel; + await handleLowLevelChat(req, chatResponse, currentLevel, chatModel); } else { - // apply the defence detection for level 3 and sandbox - const highLevelReply: ChatHttpResponse = await handleHigherLevelChat( + // apply the defence detection for level 3 and sandbox - sets chatResponse obj + await handleHigherLevelChat( req, - res, message, chatHistoryBefore, chatResponse, currentLevel, chatModel ); - chatResponse.reply = highLevelReply.reply; - chatResponse.wonLevel = highLevelReply.wonLevel; - chatResponse.transformedMessage = highLevelReply.transformedMessage; - chatResponse.defenceInfo = highLevelReply.defenceInfo; - chatResponse.numLevelsCompleted = highLevelReply.numLevelsCompleted; } // if the reply was blocked then add it to the chat history if (chatResponse.defenceInfo.isBlocked) { @@ -257,19 +249,22 @@ router.post( chatMessageType: CHAT_MESSAGE_TYPE.BOT_BLOCKED, infoMessage: chatResponse.defenceInfo.blockedReason, }); - } - // enable next level when user wins current level - if (chatResponse.wonLevel) { - console.log("Win conditon met for level: ", currentLevel); - numLevelsCompleted = Math.max(numLevelsCompleted, currentLevel + 1); - req.session.numLevelsCompleted = numLevelsCompleted; - chatResponse.numLevelsCompleted = numLevelsCompleted; + + // enable next level when user wins current level + if (chatResponse.wonLevel) { + console.debug("Win conditon met for level: ", currentLevel); + numLevelsCompleted = Math.max(numLevelsCompleted, currentLevel + 1); + req.session.numLevelsCompleted = numLevelsCompleted; + chatResponse.numLevelsCompleted = numLevelsCompleted; + } } } else { - res.statusCode = 400; - chatResponse.reply = "Missing message"; - console.error(chatResponse.reply); + handleChatError(res, chatResponse, true, "Missing message"); + return; } + } catch (error) { + handleChatError(res, chatResponse, false, "Failed to get chatGPT reply"); + return; } // log and send the reply with defence info console.log(chatResponse); @@ -280,46 +275,38 @@ router.post( // handle the chat logic for level 1 and 2 with no defences applied async function handleLowLevelChat( req: OpenAiChatRequest, - res: express.Response, chatResponse: ChatHttpResponse, currentLevel: LEVEL_NAMES, chatModel: ChatModel -): Promise { - let openAiReply = null; +) { // get the chatGPT reply - try { - openAiReply = await chatGptSendMessage( - req.session.levelState[currentLevel].chatHistory, - req.session.levelState[currentLevel].defences, - chatModel, - chatResponse.transformedMessage, - false, - req.session.openAiApiKey ?? "", - req.session.levelState[currentLevel].sentEmails, - currentLevel - ); - chatResponse.reply = openAiReply?.completion.content ?? ""; - chatResponse.wonLevel = openAiReply?.wonLevel ?? false; - } catch (error) { - res.statusCode = 500; - console.log(error); - if (error instanceof Error) { - chatResponse.reply = "Failed to get chatGPT reply"; - } + const openAiReply = await chatGptSendMessage( + req.session.levelState[currentLevel].chatHistory, + req.session.levelState[currentLevel].defences, + chatModel, + chatResponse.transformedMessage, + false, + req.session.openAiApiKey ?? "", + req.session.levelState[currentLevel].sentEmails, + currentLevel + ); + chatResponse.reply = openAiReply?.completion.content ?? ""; + chatResponse.wonLevel = openAiReply?.wonLevel ?? false; + + if (openAiReply instanceof Error) { + throw openAiReply; } - return chatResponse; } // handle the chat logic for high levels (with defence detection) async function handleHigherLevelChat( req: OpenAiChatRequest, - res: express.Response, message: string, chatHistoryBefore: ChatHistoryMessage[], chatResponse: ChatHttpResponse, currentLevel: LEVEL_NAMES, chatModel: ChatModel -): Promise { +) { let openAiReply = null; // transform the message according to active defences @@ -367,9 +354,6 @@ async function handleHigherLevelChat( // if input message is blocked, restore the original chat history and add user message (not as completion) if (chatResponse.defenceInfo.isBlocked) { - console.debug( - "Input message was blocked. restoring chat history and adding user message" - ); // set to null to stop message being returned to user openAiReply = null; @@ -384,7 +368,6 @@ async function handleHigherLevelChat( } if (openAiReply) { - console.debug("if openai reply... ", openAiReply); chatResponse.wonLevel = openAiReply.wonLevel; chatResponse.reply = openAiReply.completion.content ?? ""; @@ -401,14 +384,10 @@ async function handleHigherLevelChat( openAiReply.defenceInfo.blockedReason; } } catch (error) { - chatResponse = handleChatError( - chatResponse, - false, - "Failed to get chatGPT reply" - ); - res.status(500).send(chatResponse); + if (error instanceof Error) { + throw error; + } } - return chatResponse; } // get the chat history