| | const express = require('express'); |
| | const crypto = require('crypto'); |
| | const router = express.Router(); |
| | const { titleConvoBing, askBing } = require('../../../app'); |
| | const { saveMessage, getConvoTitle, saveConvo, getConvo } = require('../../../models'); |
| | const { handleError, sendMessage, createOnProgress, handleText } = require('../../utils'); |
| | const { setHeaders } = require('../../middleware'); |
| |
|
| | router.post('/', setHeaders, async (req, res) => { |
| | const { |
| | endpoint, |
| | text, |
| | messageId, |
| | overrideParentMessageId = null, |
| | parentMessageId, |
| | conversationId: oldConversationId, |
| | } = req.body; |
| | if (text.length === 0) { |
| | return handleError(res, { text: 'Prompt empty or too short' }); |
| | } |
| | if (endpoint !== 'bingAI') { |
| | return handleError(res, { text: 'Illegal request' }); |
| | } |
| |
|
| | |
| | const conversationId = oldConversationId || crypto.randomUUID(); |
| | const isNewConversation = !oldConversationId; |
| | const userMessageId = messageId; |
| | const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000'; |
| | let userMessage = { |
| | messageId: userMessageId, |
| | sender: 'User', |
| | text, |
| | parentMessageId: userParentMessageId, |
| | conversationId, |
| | isCreatedByUser: true, |
| | }; |
| |
|
| | |
| | let endpointOption = {}; |
| | if (req.body?.jailbreak) { |
| | endpointOption = { |
| | jailbreak: req.body?.jailbreak ?? false, |
| | jailbreakConversationId: req.body?.jailbreakConversationId ?? null, |
| | systemMessage: req.body?.systemMessage ?? null, |
| | context: req.body?.context ?? null, |
| | toneStyle: req.body?.toneStyle ?? 'creative', |
| | key: req.body?.key ?? null, |
| | }; |
| | } else { |
| | endpointOption = { |
| | jailbreak: req.body?.jailbreak ?? false, |
| | systemMessage: req.body?.systemMessage ?? null, |
| | context: req.body?.context ?? null, |
| | conversationSignature: req.body?.conversationSignature ?? null, |
| | clientId: req.body?.clientId ?? null, |
| | invocationId: req.body?.invocationId ?? null, |
| | toneStyle: req.body?.toneStyle ?? 'creative', |
| | key: req.body?.key ?? null, |
| | }; |
| | } |
| |
|
| | console.log('ask log', { |
| | userMessage, |
| | endpointOption, |
| | conversationId, |
| | }); |
| |
|
| | if (!overrideParentMessageId) { |
| | await saveMessage({ ...userMessage, user: req.user.id }); |
| | await saveConvo(req.user.id, { |
| | ...userMessage, |
| | ...endpointOption, |
| | conversationId, |
| | endpoint, |
| | }); |
| | } |
| |
|
| | |
| | return await ask({ |
| | isNewConversation, |
| | userMessage, |
| | endpointOption, |
| | conversationId, |
| | preSendRequest: true, |
| | overrideParentMessageId, |
| | req, |
| | res, |
| | }); |
| | }); |
| |
|
| | const ask = async ({ |
| | isNewConversation, |
| | userMessage, |
| | endpointOption, |
| | conversationId, |
| | preSendRequest = true, |
| | overrideParentMessageId = null, |
| | req, |
| | res, |
| | }) => { |
| | let { text, parentMessageId: userParentMessageId, messageId: userMessageId } = userMessage; |
| | const user = req.user.id; |
| |
|
| | let responseMessageId = crypto.randomUUID(); |
| | const model = endpointOption?.jailbreak ? 'Sydney' : 'BingAI'; |
| |
|
| | if (preSendRequest) { |
| | sendMessage(res, { message: userMessage, created: true }); |
| | } |
| |
|
| | let lastSavedTimestamp = 0; |
| | const { onProgress: progressCallback, getPartialText } = createOnProgress({ |
| | onProgress: ({ text }) => { |
| | const currentTimestamp = Date.now(); |
| | if (currentTimestamp - lastSavedTimestamp > 500) { |
| | lastSavedTimestamp = currentTimestamp; |
| | saveMessage({ |
| | messageId: responseMessageId, |
| | sender: model, |
| | conversationId, |
| | parentMessageId: overrideParentMessageId || userMessageId, |
| | model, |
| | text: text, |
| | unfinished: true, |
| | cancelled: false, |
| | error: false, |
| | isCreatedByUser: false, |
| | user, |
| | }); |
| | } |
| | }, |
| | }); |
| | const abortController = new AbortController(); |
| | let bingConversationId = null; |
| | if (!isNewConversation) { |
| | const convo = await getConvo(user, conversationId); |
| | bingConversationId = convo.bingConversationId; |
| | } |
| |
|
| | try { |
| | let response = await askBing({ |
| | text, |
| | userId: user, |
| | parentMessageId: userParentMessageId, |
| | conversationId: bingConversationId ?? conversationId, |
| | ...endpointOption, |
| | onProgress: progressCallback.call(null, { |
| | res, |
| | text, |
| | parentMessageId: overrideParentMessageId || userMessageId, |
| | }), |
| | abortController, |
| | }); |
| |
|
| | console.log('BING RESPONSE', response); |
| |
|
| | if (response.details && response.details.scores) { |
| | console.log('SCORES', response.details.scores); |
| | } |
| |
|
| | const newConversationId = endpointOption?.jailbreak |
| | ? response.jailbreakConversationId |
| | : response.conversationId || conversationId; |
| | const newUserMessageId = |
| | response.parentMessageId || response.details.requestId || userMessageId; |
| | const newResponseMessageId = response.messageId || response.details.messageId; |
| |
|
| | |
| | response.text = |
| | response.response || response.details.spokenText || '**Bing refused to answer.**'; |
| |
|
| | const partialText = getPartialText(); |
| | let unfinished = false; |
| | if (partialText?.trim()?.length > response.text.length) { |
| | response.text = partialText; |
| | unfinished = false; |
| | |
| | } |
| |
|
| | let responseMessage = { |
| | conversationId, |
| | bingConversationId: newConversationId, |
| | messageId: responseMessageId, |
| | newMessageId: newResponseMessageId, |
| | parentMessageId: overrideParentMessageId || newUserMessageId, |
| | sender: model, |
| | text: await handleText(response, true), |
| | model, |
| | suggestions: |
| | response.details.suggestedResponses && |
| | response.details.suggestedResponses.map((s) => s.text), |
| | unfinished, |
| | cancelled: false, |
| | error: false, |
| | isCreatedByUser: false, |
| | }; |
| |
|
| | await saveMessage({ ...responseMessage, user }); |
| | responseMessage.messageId = newResponseMessageId; |
| |
|
| | let conversationUpdate = { |
| | conversationId, |
| | bingConversationId: newConversationId, |
| | endpoint: 'bingAI', |
| | }; |
| |
|
| | if (endpointOption?.jailbreak) { |
| | conversationUpdate.jailbreak = true; |
| | conversationUpdate.jailbreakConversationId = response.jailbreakConversationId; |
| | } else { |
| | conversationUpdate.jailbreak = false; |
| | conversationUpdate.conversationSignature = response.conversationSignature; |
| | conversationUpdate.clientId = response.clientId; |
| | conversationUpdate.invocationId = response.invocationId; |
| | } |
| |
|
| | await saveConvo(user, conversationUpdate); |
| | userMessage.messageId = newUserMessageId; |
| |
|
| | |
| | if (!overrideParentMessageId) { |
| | await saveMessage({ |
| | ...userMessage, |
| | user, |
| | messageId: userMessageId, |
| | newMessageId: newUserMessageId, |
| | }); |
| | } |
| | userMessageId = newUserMessageId; |
| |
|
| | sendMessage(res, { |
| | title: await getConvoTitle(user, conversationId), |
| | final: true, |
| | conversation: await getConvo(user, conversationId), |
| | requestMessage: userMessage, |
| | responseMessage: responseMessage, |
| | }); |
| | res.end(); |
| |
|
| | if (userParentMessageId == '00000000-0000-0000-0000-000000000000') { |
| | const title = await titleConvoBing({ |
| | text, |
| | response: responseMessage, |
| | }); |
| |
|
| | await saveConvo(user, { |
| | conversationId: conversationId, |
| | title, |
| | }); |
| | } |
| | } catch (error) { |
| | console.error(error); |
| | const partialText = getPartialText(); |
| | if (partialText?.length > 2) { |
| | const responseMessage = { |
| | messageId: responseMessageId, |
| | sender: model, |
| | conversationId, |
| | parentMessageId: overrideParentMessageId || userMessageId, |
| | text: partialText, |
| | model, |
| | unfinished: true, |
| | cancelled: false, |
| | error: false, |
| | isCreatedByUser: false, |
| | }; |
| |
|
| | saveMessage({ ...responseMessage, user }); |
| |
|
| | return { |
| | title: await getConvoTitle(user, conversationId), |
| | final: true, |
| | conversation: await getConvo(user, conversationId), |
| | requestMessage: userMessage, |
| | responseMessage: responseMessage, |
| | }; |
| | } else { |
| | console.log(error); |
| | const errorMessage = { |
| | messageId: responseMessageId, |
| | sender: model, |
| | conversationId, |
| | parentMessageId: overrideParentMessageId || userMessageId, |
| | unfinished: false, |
| | cancelled: false, |
| | error: true, |
| | text: error.message, |
| | model, |
| | isCreatedByUser: false, |
| | }; |
| | await saveMessage({ ...errorMessage, user }); |
| | handleError(res, errorMessage); |
| | } |
| | } |
| | }; |
| |
|
| | module.exports = router; |
| |
|