diff --git a/api/models/Preset.js b/api/models/Preset.js new file mode 100644 index 000000000..de33370e6 --- /dev/null +++ b/api/models/Preset.js @@ -0,0 +1,46 @@ +const Preset = require('./schema/presetSchema'); + +const getPreset = async (user, presetId) => { + try { + return await Preset.findOne({ user, presetId }).exec(); + } catch (error) { + console.log(error); + return { message: 'Error getting single preset' }; + } +}; + +module.exports = { + Preset, + getPreset, + getPresets: async (user, filter) => { + try { + return await Preset.find({ ...filter, user }).exec(); + } catch (error) { + console.log(error); + return { message: 'Error retriving presets' }; + } + }, + savePreset: async (user, { presetId, newPresetId, ...preset }) => { + try { + const update = { presetId, ...preset }; + if (newPresetId) { + update.presetId = newPresetId; + } + + return await Preset.findOneAndUpdate( + { presetId, user }, + { $set: update }, + { new: true, upsert: true } + ).exec(); + } catch (error) { + console.log(error); + return { message: 'Error saving preset' }; + } + }, + deletePresets: async (user, filter) => { + let toRemove = await Preset.find({ ...filter, user }).select('presetId'); + const ids = toRemove.map(instance => instance.presetId); + let deleteCount = await Preset.deleteMany({ ...filter, user }).exec(); + return deleteCount; + } +}; diff --git a/api/models/index.js b/api/models/index.js index 6ff90f7c5..e72b81846 100644 --- a/api/models/index.js +++ b/api/models/index.js @@ -1,6 +1,13 @@ -const { getMessages, saveMessage, saveBingMessage, deleteMessagesSince, deleteMessages } = require('./Message'); +const { + getMessages, + saveMessage, + saveBingMessage, + deleteMessagesSince, + deleteMessages +} = require('./Message'); const { getCustomGpts, updateCustomGpt, updateByLabel, deleteCustomGpts } = require('./CustomGpt'); const { getConvoTitle, getConvo, saveConvo, updateConvo } = require('./Conversation'); +const { getPreset, getPresets, savePreset, deletePresets } = require('./Preset'); module.exports = { getMessages, @@ -8,12 +15,19 @@ module.exports = { saveBingMessage, deleteMessagesSince, deleteMessages, + getConvoTitle, getConvo, saveConvo, updateConvo, + getCustomGpts, updateCustomGpt, updateByLabel, - deleteCustomGpts + deleteCustomGpts, + + getPreset, + getPresets, + savePreset, + deletePresets }; diff --git a/api/models/schema/conversationPreset.js b/api/models/schema/conversationPreset.js new file mode 100644 index 000000000..aead0ab79 --- /dev/null +++ b/api/models/schema/conversationPreset.js @@ -0,0 +1,70 @@ +module.exports = { + // endpoint: [azureOpenAI, openAI, bingAI, chatGPTBrowser] + endpoint: { + type: String, + default: null, + required: true + }, + // for azureOpenAI, openAI, chatGPTBrowser only + model: { + type: String, + default: null, + required: false + }, + // for azureOpenAI, openAI only + chatGptLabel: { + type: String, + default: null, + required: false + }, + promptPrefix: { + type: String, + default: null, + required: false + }, + temperature: { + type: Number, + default: 1, + required: false + }, + top_p: { + type: Number, + default: 1, + required: false + }, + presence_penalty: { + type: Number, + default: 0, + required: false + }, + frequency_penalty: { + type: Number, + default: 0, + required: false + }, + // for bingai only + jailbreak: { + type: Boolean, + default: false + }, + jailbreakConversationId: { + type: String, + default: null + }, + conversationSignature: { + type: String, + default: null + }, + clientId: { + type: String, + default: null + }, + invocationId: { + type: Number, + default: 1 + }, + toneStyle: { + type: String, + default: null + } +}; diff --git a/api/models/schema/convoSchema.js b/api/models/schema/convoSchema.js index 250695329..fc29b55fb 100644 --- a/api/models/schema/convoSchema.js +++ b/api/models/schema/convoSchema.js @@ -1,5 +1,6 @@ const mongoose = require('mongoose'); const mongoMeili = require('../plugins/mongoMeili'); +const conversationPreset = require('./conversationPreset'); const convoSchema = mongoose.Schema( { conversationId: { @@ -19,74 +20,7 @@ const convoSchema = mongoose.Schema( default: null }, messages: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Message' }], - // endpoint: [azureOpenAI, openAI, bingAI, chatGPTBrowser] - endpoint: { - type: String, - default: null, - required: true - }, - // for azureOpenAI, openAI, chatGPTBrowser only - model: { - type: String, - default: null, - required: false - }, - // for azureOpenAI, openAI only - chatGptLabel: { - type: String, - default: null, - required: false - }, - promptPrefix: { - type: String, - default: null, - required: false - }, - temperature: { - type: Number, - default: 1, - required: false - }, - top_p: { - type: Number, - default: 1, - required: false - }, - presence_penalty: { - type: Number, - default: 0, - required: false - }, - frequency_penalty: { - type: Number, - default: 0, - required: false - }, - // for bingai only - jailbreak: { - type: Boolean, - default: false - }, - jailbreakConversationId: { - type: String, - default: null - }, - conversationSignature: { - type: String, - default: null - }, - clientId: { - type: String, - default: null - }, - invocationId: { - type: Number, - default: 1 - }, - toneStyle: { - type: String, - default: null - } + ...conversationPreset }, { timestamps: true } ); diff --git a/api/models/schema/presetSchema.js b/api/models/schema/presetSchema.js new file mode 100644 index 000000000..35a2e1c57 --- /dev/null +++ b/api/models/schema/presetSchema.js @@ -0,0 +1,27 @@ +const mongoose = require('mongoose'); +const conversationPreset = require('./conversationPreset'); +const presetSchema = mongoose.Schema( + { + presetId: { + type: String, + unique: true, + required: true, + index: true + }, + title: { + type: String, + default: 'New Chat', + meiliIndex: true + }, + user: { + type: String, + default: null + }, + ...conversationPreset + }, + { timestamps: true } +); + +const Preset = mongoose.models.Preset || mongoose.model('Preset', presetSchema); + +module.exports = Preset; diff --git a/api/server/index.js b/api/server/index.js index d70c13839..a096901f8 100644 --- a/api/server/index.js +++ b/api/server/index.js @@ -57,6 +57,7 @@ const projectPath = path.join(__dirname, '..', '..', 'client'); app.use('/api/messages', routes.authenticatedOr401, routes.messages); app.use('/api/convos', routes.authenticatedOr401, routes.convos); app.use('/api/customGpts', routes.authenticatedOr401, routes.customGpts); + app.use('/api/presets', routes.authenticatedOr401, routes.presets); app.use('/api/prompts', routes.authenticatedOr401, routes.prompts); app.use('/auth', routes.auth); diff --git a/api/server/routes/index.js b/api/server/routes/index.js index 409c65392..e517b0bf4 100644 --- a/api/server/routes/index.js +++ b/api/server/routes/index.js @@ -1,9 +1,21 @@ const ask = require('./ask'); const messages = require('./messages'); const convos = require('./convos'); +const presets = require('./presets'); const customGpts = require('./customGpts'); -const prompts = require('./prompts'); +const prompts = require('./prompts'); const search = require('./search'); const { router: auth, authenticatedOr401, authenticatedOrRedirect } = require('./auth'); -module.exports = { search, ask, messages, convos, customGpts, prompts, auth, authenticatedOr401, authenticatedOrRedirect }; \ No newline at end of file +module.exports = { + search, + ask, + messages, + convos, + presets, + customGpts, + prompts, + auth, + authenticatedOr401, + authenticatedOrRedirect +}; diff --git a/api/server/routes/presets.js b/api/server/routes/presets.js new file mode 100644 index 000000000..2e872fd84 --- /dev/null +++ b/api/server/routes/presets.js @@ -0,0 +1,48 @@ +const express = require('express'); +const router = express.Router(); +const { getPreset, getPresets, savePreset, deletePresets } = require('../../models'); +const crypto = require('crypto'); + +router.get('/', async (req, res) => { + const presets = (await getPresets(req?.session?.user?.username)).map(preset => { + return preset.toObject(); + }); + res.status(200).send(presets); +}); + +router.post('/', async (req, res) => { + const update = req.body || {}; + + update.presetId = update?.presetId || crypto.randomUUID(); + + try { + await savePreset(req?.session?.user?.username, update); + + const presets = (await getPresets(req?.session?.user?.username)).map(preset => { + return preset.toObject(); + }); + res.status(201).send(presets); + } catch (error) { + console.error(error); + res.status(500).send(error); + } +}); + +router.post('/delete', async (req, res) => { + const { arg } = req.body; + + try { + await deletePresets(req?.session?.user?.username, arg); + + const presets = (await getPresets(req?.session?.user?.username)).map(preset => { + return preset.toObject(); + }); + res.status(201).send(presets); + // res.status(201).send(dbResponse); + } catch (error) { + console.error(error); + res.status(500).send(error); + } +}); + +module.exports = router;