Skip to content

Commit a81bd27

Browse files
committed
feat(api): add support for saving messages to database
fix(api): change arrowParens prettier option to always fix(api): update addToCache to include endpointOption and latestMessage fix(api): update askOpenAI to include endpointOption in abortControllers fix(client): remove abortKey state and add currentParent state to MessageHandler
1 parent 6246fff commit a81bd27

File tree

5 files changed

+78
-32
lines changed

5 files changed

+78
-32
lines changed

api/.prettierrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"arrowParens": "avoid",
2+
"arrowParens": "always",
33
"bracketSpacing": true,
44
"endOfLine": "lf",
55
"htmlWhitespaceSensitivity": "css",

api/models/Message.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
error
1313
}) => {
1414
try {
15+
// may also need to update the conversation here
1516
await Message.findOneAndUpdate(
1617
{ messageId },
1718
{

api/server/routes/ask/addToCache.js

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,66 @@
11
const Keyv = require('keyv');
22
const { KeyvFile } = require('keyv-file');
33
const crypto = require('crypto');
4+
const { saveMessage } = require('../../../models');
45

5-
const addToCache = async ( { conversationId, parentMessageId }) => {
6-
const conversationsCache = new Keyv({
7-
store: new KeyvFile({ filename: './data/cache.json' })
8-
});
9-
10-
let conversation = await conversationsCache.get(conversationId);
11-
let isNewConversation = false;
12-
if (!conversation) {
13-
conversation = {
14-
messages: [],
15-
createdAt: Date.now()
6+
const addToCache = async ({
7+
endpointOption,
8+
conversationId,
9+
userMessage,
10+
latestMessage,
11+
parentMessageId
12+
}) => {
13+
try {
14+
const conversationsCache = new Keyv({
15+
store: new KeyvFile({ filename: './data/cache.json' }),
16+
namespace: 'chatgpt', // should be 'bing' for bing/sydney
17+
});
18+
19+
let conversation = await conversationsCache.get(conversationId);
20+
// used to generate a title for the conversation if none exists
21+
// let isNewConversation = false;
22+
if (!conversation) {
23+
conversation = {
24+
messages: [],
25+
createdAt: Date.now()
26+
};
27+
// isNewConversation = true;
28+
}
29+
30+
// const shouldGenerateTitle = opts.shouldGenerateTitle && isNewConversation;
31+
32+
const roles = (options) => {
33+
const { endpoint } = options;
34+
if (endpoint === 'openAI') {
35+
return options?.chatGptLabel || 'ChatGPT';
36+
} else if (endpoint === 'bingAI') {
37+
return options?.jailbreak ? 'Sydney' : 'BingAI';
38+
}
1639
};
17-
isNewConversation = true;
18-
}
1940

20-
// const shouldGenerateTitle = opts.shouldGenerateTitle && isNewConversation;
41+
const messageId = crypto.randomUUID();
2142

22-
const userMessage = {
23-
id: crypto.randomUUID(),
24-
parentMessageId,
25-
role: 'User',
26-
message
27-
};
28-
conversation.messages.push(userMessage);
43+
let responseMessage = {
44+
id: messageId,
45+
parentMessageId,
46+
role: roles(endpointOption),
47+
message: latestMessage
48+
};
49+
50+
await saveMessage({
51+
...responseMessage,
52+
conversationId,
53+
messageId,
54+
sender: responseMessage.role,
55+
text: latestMessage
56+
});
57+
58+
conversation.messages.push(userMessage, responseMessage);
59+
60+
await conversationsCache.set(conversationId, conversation);
61+
} catch (error) {
62+
console.error('Trouble adding to cache', error);
63+
}
2964
};
3065

31-
module.exports = { addToCache };
66+
module.exports = addToCache;

api/server/routes/ask/askOpenAI.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
const express = require('express');
22
const crypto = require('crypto');
33
const router = express.Router();
4+
const addToCache = require('./addToCache');
45
const { getOpenAIModels } = require('../endpoints');
56
const { titleConvo, askClient } = require('../../../app/');
67
const { saveMessage, getConvoTitle, saveConvo, updateConvo, getConvo } = require('../../../models');
78
const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers');
89

910
const abortControllers = new Map();
1011

11-
router.post('/abort', (req, res) => {
12-
const { abortKey, message } = req.body;
12+
router.post('/abort', async (req, res) => {
13+
const { abortKey, latestMessage, parentMessageId } = req.body;
14+
console.log(`req.body`, req.body);
1315
if (!abortControllers.has(abortKey)) {
1416
return res.status(404).send('Request not found');
1517
}
18+
19+
const { abortController, userMessage, endpointOption } = abortControllers.get(abortKey);
20+
if (!endpointOption.endpoint) {
21+
endpointOption.endpoint = req.originalUrl.replace('/api/ask/','').split('/abort')[0];
22+
}
1623

17-
const { abortController, userMessage } = abortControllers.get(abortKey);
1824
abortController.abort();
1925
abortControllers.delete(abortKey);
20-
console.log('Aborted request', abortKey, userMessage);
26+
console.log('Aborted request', abortKey, userMessage, endpointOption);
27+
await addToCache({ endpointOption, conversationId: abortKey, userMessage, latestMessage, parentMessageId });
2128

2229
res.status(200).send('Aborted');
2330
});
@@ -118,7 +125,7 @@ const ask = async ({
118125
const abortController = new AbortController();
119126
const abortKey = conversationId;
120127
console.log('conversationId -----> ', conversationId);
121-
abortControllers.set(abortKey, { abortController, userMessage });
128+
abortControllers.set(abortKey, { abortController, userMessage, endpointOption });
122129

123130
res.on('close', () => {
124131
abortController.abort();

client/src/components/MessageHandler/index.jsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export default function MessageHandler() {
1515
const [lastResponse, setLastResponse] = useRecoilState(store.lastResponse);
1616
const setSubmission = useSetRecoilState(store.submission);
1717
const [source, setSource] = useState(null);
18-
const [abortKey, setAbortKey] = useState(null);
18+
// const [abortKey, setAbortKey] = useState(null);
19+
const [currentParent, setCurrentParent] = useState(null);
1920

2021
const { refreshConversations } = store.useConversations();
2122

@@ -174,8 +175,9 @@ export default function MessageHandler() {
174175
'Content-Type': 'application/json'
175176
},
176177
body: JSON.stringify({
177-
abortKey,
178-
message: latestMessage,
178+
abortKey: currentParent.conversationId,
179+
latestMessage,
180+
parentMessageId: currentParent.messageId,
179181
})
180182
})
181183
.then(response => {
@@ -219,7 +221,8 @@ export default function MessageHandler() {
219221
};
220222
createdHandler(data, { ...submission, message });
221223
console.log('created', message);
222-
setAbortKey(message?.conversationId);
224+
// setAbortKey(message?.conversationId);
225+
setCurrentParent(message);
223226
} else {
224227
let text = data.text || data.response;
225228
if (data.initial) console.log(data);

0 commit comments

Comments
 (0)