diff --git a/api/app/titleConvo.js b/api/app/titleConvo.js index 88e8c75074..344af6f893 100644 --- a/api/app/titleConvo.js +++ b/api/app/titleConvo.js @@ -1,4 +1,5 @@ const { Configuration, OpenAIApi } = require('openai'); +const _ = require('lodash'); const proxyEnvToAxiosProxy = (proxyString) => { if (!proxyString) return null; @@ -11,29 +12,37 @@ const proxyEnvToAxiosProxy = (proxyString) => { port: port ? parseInt(port) : undefined, auth: username && password ? { username, password } : undefined }; - - return proxyConfig -} + + return proxyConfig; +}; const titleConvo = async ({ message, response, model }) => { const configuration = new Configuration({ apiKey: process.env.OPENAI_KEY }); const openai = new OpenAIApi(configuration); - const completion = await openai.createChatCompletion({ - model: 'gpt-3.5-turbo', - messages: [ - { - role: 'system', - content: - 'You are a title-generator with one job: giving a conversation, detect the language and titling the conversation provided by a user in title case, using the same language.' - }, - { role: 'user', content: `In 5 words or less, summarize the conversation below with a title in title case using the language the user writes in. Don't refer to the participants of the conversation by name. Do not include punctuation or quotation marks. Your response should be in title case, exclusively containing the title. Conversation:\n\nUser: "${message}"\n\n${model}: "${response}"\n\nTitle: ` }, - ] - }, { proxy: proxyEnvToAxiosProxy(process.env.PROXY || null) }); + const completion = await openai.createChatCompletion( + { + model: 'gpt-3.5-turbo', + messages: [ + { + role: 'system', + content: + 'You are a title-generator with one job: giving a conversation, detect the language and titling the conversation provided by a user in title case, using the same language.' + }, + { + role: 'user', + content: `In 5 words or less, summarize the conversation below with a title in title case using the language the user writes in. Don't refer to the participants of the conversation by name. Do not include punctuation or quotation marks. Your response should be in title case, exclusively containing the title. Conversation:\n\nUser: "${message}"\n\n${model}: "${response}"\n\nTitle: ` + } + ] + }, + { proxy: proxyEnvToAxiosProxy(process.env.PROXY || null) } + ); //eslint-disable-next-line return completion.data.choices[0].message.content.replace(/["\.]/g, ''); }; -module.exports = titleConvo; +const debouncedTitleConvo = _.debounce(titleConvo, 500); + +module.exports = debouncedTitleConvo; diff --git a/api/server/routes/ask.js b/api/server/routes/ask.js index 265672db8b..1d497c86b8 100644 --- a/api/server/routes/ask.js +++ b/api/server/routes/ask.js @@ -3,15 +3,15 @@ const crypto = require('crypto'); const router = express.Router(); const askBing = require('./askBing'); const askSydney = require('./askSydney'); -const { - titleConvo, - askClient, - browserClient, - customClient - // detectCode -} = require('../../app/'); +const { askClient, browserClient, customClient } = require('../../app/'); const { getConvo, saveMessage, getConvoTitle, saveConvo } = require('../../models'); -const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers'); +const { + handleError, + sendMessage, + createOnProgress, + genTitle, + handleText +} = require('./handlers'); const { getMessages } = require('../../models/Message'); router.use('/bing', askBing); @@ -42,15 +42,6 @@ router.post('/', async (req, res) => { ...convo }); - // if (model === 'chatgptCustom' && !chatGptLabel && conversationId) { - // const convo = await getConvo({ conversationId }); - // if (convo) { - // console.log('found convo for custom gpt', { convo }) - // chatGptLabel = convo.chatGptLabel; - // promptPrefix = convo.promptPrefix; - // } - // } - await saveMessage(userMessage); await saveConvo({ ...userMessage, model, ...convo }); @@ -94,17 +85,6 @@ router.post('/regenerate', async (req, res) => { res }); } else return handleError(res, { text: 'Parent message not found' }); - - // if (model === 'chatgptCustom' && !chatGptLabel && conversationId) { - // const convo = await getConvo({ conversationId }); - // if (convo) { - // console.log('found convo for custom gpt', { convo }) - // chatGptLabel = convo.chatGptLabel; - // promptPrefix = convo.promptPrefix; - // } - // } - - // await saveConvo({ ...userMessage, model, chatGptLabel, promptPrefix }); }); const ask = async ({ @@ -212,13 +192,7 @@ const ask = async ({ res.end(); if (userParentMessageId == '00000000-0000-0000-0000-000000000000') { - const title = await titleConvo({ - model, - message: text, - response: JSON.stringify(gptResponse?.text) - }); - - console.log('CONVERSATION TITLE', title); + const title = await genTitle({ model, text, response: gptResponse }); await saveConvo({ conversationId, diff --git a/api/server/routes/askBing.js b/api/server/routes/askBing.js index 066b64faec..681332ec37 100644 --- a/api/server/routes/askBing.js +++ b/api/server/routes/askBing.js @@ -1,9 +1,15 @@ const express = require('express'); const crypto = require('crypto'); const router = express.Router(); -const { titleConvo, getCitations, citeText, askBing } = require('../../app/'); +const { getCitations, citeText, askBing } = require('../../app/'); const { saveMessage, getConvoTitle, saveConvo } = require('../../models'); -const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers'); +const { + handleError, + sendMessage, + createOnProgress, + genTitle, + handleText +} = require('./handlers'); const citationRegex = /\[\^\d+?\^]/g; router.post('/', async (req, res) => { @@ -146,13 +152,7 @@ const ask = async ({ res.end(); if (userParentMessageId == '00000000-0000-0000-0000-000000000000') { - const title = await titleConvo({ - model, - message: text, - response: JSON.stringify(response?.text) - }); - - console.log('CONVERSATION TITLE', title); + const title = await genTitle({ model, text, response }); await saveConvo({ conversationId, diff --git a/api/server/routes/askSydney.js b/api/server/routes/askSydney.js index 03e3479be4..40aa967bcc 100644 --- a/api/server/routes/askSydney.js +++ b/api/server/routes/askSydney.js @@ -1,9 +1,15 @@ const express = require('express'); const crypto = require('crypto'); const router = express.Router(); -const { titleConvo, getCitations, citeText, askSydney } = require('../../app/'); +const { getCitations, citeText, askSydney } = require('../../app/'); const { saveMessage, saveConvo, getConvoTitle } = require('../../models'); -const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers'); +const { + handleError, + sendMessage, + createOnProgress, + genTitle, + handleText +} = require('./handlers'); const citationRegex = /\[\^\d+?\^]/g; router.post('/', async (req, res) => { @@ -158,13 +164,7 @@ const ask = async ({ res.end(); if (userParentMessageId == '00000000-0000-0000-0000-000000000000') { - const title = await titleConvo({ - model, - message: text, - response: JSON.stringify(response?.text) - }); - - console.log('CONVERSATION TITLE', title); + const title = await genTitle({ model, text, response }); await saveConvo({ conversationId, diff --git a/api/server/routes/convos.js b/api/server/routes/convos.js index 9a5f71cee3..99fb824708 100644 --- a/api/server/routes/convos.js +++ b/api/server/routes/convos.js @@ -1,41 +1,12 @@ const express = require('express'); const router = express.Router(); -const { titleConvo } = require('../../app/'); -const { getConvo, saveConvo, getConvoTitle } = require('../../models'); const { getConvosByPage, deleteConvos, updateConvo } = require('../../models/Conversation'); -const { getMessages } = require('../../models/Message'); router.get('/', async (req, res) => { const pageNumber = req.query.pageNumber || 1; res.status(200).send(await getConvosByPage(pageNumber)); }); -router.post('/gen_title', async (req, res) => { - const { conversationId } = req.body.arg; - - const convo = await getConvo(conversationId) - const firstMessage = (await getMessages({ conversationId }))[0] - const secondMessage = (await getMessages({ conversationId }))[1] - - // if (convo.title == 'New Chat') { - // const title = await titleConvo({ - // model: convo?.model, - // message: firstMessage?.text, - // response: JSON.stringify(secondMessage?.text || '') - // }); - - // console.log('CONVERSATION TITLE', title); - - // await saveConvo({ - // conversationId, - // title - // }) - - // res.status(200).send(title); - // } else - return res.status(200).send(convo.title); -}); - router.post('/clear', async (req, res) => { let filter = {}; const { conversationId } = req.body.arg; diff --git a/api/server/routes/handlers.js b/api/server/routes/handlers.js index d3e613bccc..7c6d6ce315 100644 --- a/api/server/routes/handlers.js +++ b/api/server/routes/handlers.js @@ -1,4 +1,4 @@ -const { citeText, detectCode } = require('../../app/'); +const { titleConvo, citeText, detectCode } = require('../../app/'); const _ = require('lodash'); const sanitizeHtml = require('sanitize-html'); @@ -14,6 +14,23 @@ const sendMessage = (res, message) => { res.write(`event: message\ndata: ${JSON.stringify(message)}\n\n`); }; +const genTitle = async ({ model, text, response }) => { + let title = 'New Chat'; + try { + title = await titleConvo({ + model, + message: text, + response: JSON.stringify(response?.text) + }); + } catch (e) { + console.error(e); + console.log('There was an issue generating title, see error above'); + } + + console.log('CONVERSATION TITLE', title); + return title; +}; + const createOnProgress = () => { let i = 0; let tokens = ''; @@ -56,4 +73,4 @@ const handleText = async (input) => { return text; }; -module.exports = { handleError, sendMessage, createOnProgress, handleText }; \ No newline at end of file +module.exports = { handleError, sendMessage, createOnProgress, genTitle, handleText }; diff --git a/client/src/components/Messages/index.jsx b/client/src/components/Messages/index.jsx index eaf0a0cb6d..d9b5b2a80b 100644 --- a/client/src/components/Messages/index.jsx +++ b/client/src/components/Messages/index.jsx @@ -3,7 +3,6 @@ import Spinner from '../svg/Spinner'; import { CSSTransition } from 'react-transition-group'; import ScrollToBottom from './ScrollToBottom'; import MultiMessage from './MultiMessage'; -import buildTree from '~/utils/buildTree'; import { useSelector } from 'react-redux'; const Messages = ({ messages, messageTree }) => {