Merge branch 'master' into feat-model-based-on-key

This commit is contained in:
Danny Avila 2023-03-16 13:39:41 -04:00 committed by GitHub
commit 1fe9e29187
27 changed files with 602 additions and 157 deletions

View file

@ -20,3 +20,10 @@ MONGO_URI="mongodb://127.0.0.1:27017/chatgpt-clone"
OPENAI_KEY=
CHATGPT_TOKEN=
BING_TOKEN=
# User System
# global enable/disable the sample user system.
# this is not a ready to use user system.
# dont't use it, unless you can write your own code.
ENABLE_USER_SYSTEM=

View file

@ -43,6 +43,9 @@ const convoSchema = mongoose.Schema(
type: String,
required: true
},
user: {
type: String
},
suggestions: [{ type: String }],
messages: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Message' }]
},
@ -52,9 +55,9 @@ const convoSchema = mongoose.Schema(
const Conversation =
mongoose.models.Conversation || mongoose.model('Conversation', convoSchema);
const getConvo = async (conversationId) => {
const getConvo = async (user, conversationId) => {
try {
return await Conversation.findOne({ conversationId }).exec();
return await Conversation.findOne({ user, conversationId }).exec();
} catch (error) {
console.log(error);
return { message: 'Error getting single conversation' };
@ -62,12 +65,13 @@ const getConvo = async (conversationId) => {
};
module.exports = {
saveConvo: async ({ conversationId, newConversationId, title, ...convo }) => {
saveConvo: async (user, { conversationId, newConversationId, title, ...convo }) => {
try {
const messages = await getMessages({ conversationId });
const update = { ...convo, messages };
if (title) {
update.title = title;
update.user = user
}
if (newConversationId) {
update.conversationId = newConversationId;
@ -82,7 +86,7 @@ module.exports = {
}
return await Conversation.findOneAndUpdate(
{ conversationId },
{ conversationId: conversationId, user },
{ $set: update },
{ new: true, upsert: true }
).exec();
@ -91,9 +95,9 @@ module.exports = {
return { message: 'Error saving conversation' };
}
},
updateConvo: async ({ conversationId, ...update }) => {
updateConvo: async (user, { conversationId, ...update }) => {
try {
return await Conversation.findOneAndUpdate({ conversationId }, update, {
return await Conversation.findOneAndUpdate({ conversationId: conversationId, user }, update, {
new: true
}).exec();
} catch (error) {
@ -101,12 +105,11 @@ module.exports = {
return { message: 'Error updating conversation' };
}
},
// getConvos: async () => await Conversation.find({}).sort({ createdAt: -1 }).exec(),
getConvosByPage: async (pageNumber = 1, pageSize = 12) => {
getConvosByPage: async (user, pageNumber = 1, pageSize = 12) => {
try {
const totalConvos = (await Conversation.countDocuments()) || 1;
const totalConvos = (await Conversation.countDocuments({ user })) || 1;
const totalPages = Math.ceil(totalConvos / pageSize);
const convos = await Conversation.find()
const convos = await Conversation.find({ user })
.sort({ createdAt: -1, created: -1 })
.skip((pageNumber - 1) * pageSize)
.limit(pageSize)
@ -119,17 +122,17 @@ module.exports = {
}
},
getConvo,
getConvoTitle: async (conversationId) => {
getConvoTitle: async (user, conversationId) => {
try {
const convo = await getConvo(conversationId);
const convo = await getConvo(user, conversationId);
return convo.title;
} catch (error) {
console.log(error);
return { message: 'Error getting conversation title' };
}
},
deleteConvos: async (filter) => {
let deleteCount = await Conversation.deleteMany(filter).exec();
deleteConvos: async (user, filter) => {
let deleteCount = await Conversation.deleteMany({...filter, user}).exec();
deleteCount.messages = await deleteMessages(filter);
return deleteCount;
},

View file

@ -12,16 +12,20 @@ const customGptSchema = mongoose.Schema({
type: String,
required: true
},
user: {
type: String
},
}, { timestamps: true });
const CustomGpt = mongoose.models.CustomGpt || mongoose.model('CustomGpt', customGptSchema);
const createCustomGpt = async ({ chatGptLabel, promptPrefix, value }) => {
const createCustomGpt = async ({ chatGptLabel, promptPrefix, value, user }) => {
try {
await CustomGpt.create({
chatGptLabel,
promptPrefix,
value
value,
user
});
return { chatGptLabel, promptPrefix, value };
} catch (error) {
@ -31,22 +35,22 @@ const createCustomGpt = async ({ chatGptLabel, promptPrefix, value }) => {
};
module.exports = {
getCustomGpts: async (filter) => {
getCustomGpts: async (user, filter) => {
try {
return await CustomGpt.find(filter).exec();
return await CustomGpt.find({ ...filter, user }).exec();
} catch (error) {
console.error(error);
return { customGpt: 'Error getting customGpts' };
}
},
updateCustomGpt: async ({ value, ...update }) => {
updateCustomGpt: async (user, { value, ...update }) => {
try {
const customGpt = await CustomGpt.findOne({ value }).exec();
const customGpt = await CustomGpt.findOne({ value, user }).exec();
if (!customGpt) {
return await createCustomGpt({ value, ...update });
return await createCustomGpt({ value, ...update, user });
} else {
return await CustomGpt.findOneAndUpdate({ value }, update, {
return await CustomGpt.findOneAndUpdate({ value, user }, update, {
new: true,
upsert: true
}).exec();
@ -56,9 +60,9 @@ module.exports = {
return { message: 'Error updating customGpt' };
}
},
updateByLabel: async ({ prevLabel, ...update }) => {
updateByLabel: async (user, { prevLabel, ...update }) => {
try {
return await CustomGpt.findOneAndUpdate({ chatGptLabel: prevLabel }, update, {
return await CustomGpt.findOneAndUpdate({ chatGptLabel: prevLabel, user }, update, {
new: true,
upsert: true
}).exec();
@ -67,9 +71,9 @@ module.exports = {
return { message: 'Error updating customGpt' };
}
},
deleteCustomGpts: async (filter) => {
deleteCustomGpts: async (user, filter) => {
try {
return await CustomGpt.deleteMany(filter).exec();
return await CustomGpt.deleteMany({ ...filter, user }).exec();
} catch (error) {
console.error(error);
return { customGpt: 'Error deleting customGpts' };

169
api/package-lock.json generated
View file

@ -12,9 +12,11 @@
"@keyv/mongo": "^2.1.8",
"@vscode/vscode-languagedetection": "^1.0.22",
"@waylaidwanderer/chatgpt-api": "^1.28.2",
"axios": "^1.3.4",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-session": "^1.17.3",
"keyv": "^4.5.2",
"keyv-file": "^0.2.0",
"lodash": "^4.17.21",
@ -1776,11 +1778,13 @@
}
},
"node_modules/axios": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"dependencies": {
"follow-redirects": "^1.14.8"
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": {
@ -2452,6 +2456,45 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-session": {
"version": "1.17.3",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz",
"integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==",
"dependencies": {
"cookie": "0.4.2",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-headers": "~1.0.2",
"parseurl": "~1.3.3",
"safe-buffer": "5.2.1",
"uid-safe": "~2.1.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/express-session/node_modules/cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express-session/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/express-session/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -3507,6 +3550,14 @@
"node": ">= 0.8"
}
},
"node_modules/on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
@ -3530,6 +3581,14 @@
"form-data": "^4.0.0"
}
},
"node_modules/openai/node_modules/axios": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"dependencies": {
"follow-redirects": "^1.14.8"
}
},
"node_modules/ora": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/ora/-/ora-6.1.2.tgz",
@ -3738,6 +3797,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
@ -3771,6 +3835,14 @@
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
},
"node_modules/random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
"integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@ -4353,6 +4425,17 @@
"node": ">= 0.6"
}
},
"node_modules/uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
"dependencies": {
"random-bytes": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
@ -6152,11 +6235,13 @@
}
},
"axios": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"requires": {
"follow-redirects": "^1.14.8"
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"balanced-match": {
@ -6628,6 +6713,41 @@
}
}
},
"express-session": {
"version": "1.17.3",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz",
"integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==",
"requires": {
"cookie": "0.4.2",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-headers": "~1.0.2",
"parseurl": "~1.3.3",
"safe-buffer": "5.2.1",
"uid-safe": "~2.1.5"
},
"dependencies": {
"cookie": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
}
}
},
"external-editor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
@ -7397,6 +7517,11 @@
"ee-first": "1.1.1"
}
},
"on-headers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA=="
},
"onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
@ -7412,6 +7537,16 @@
"requires": {
"axios": "^0.26.0",
"form-data": "^4.0.0"
},
"dependencies": {
"axios": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"requires": {
"follow-redirects": "^1.14.8"
}
}
}
},
"ora": {
@ -7569,6 +7704,11 @@
"ipaddr.js": "1.9.1"
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"pstree.remy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz",
@ -7593,6 +7733,11 @@
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
},
"random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
"integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ=="
},
"range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@ -8033,6 +8178,14 @@
"mime-types": "~2.1.24"
}
},
"uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
"requires": {
"random-bytes": "~1.0.0"
}
},
"undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",

View file

@ -22,9 +22,11 @@
"@keyv/mongo": "^2.1.8",
"@vscode/vscode-languagedetection": "^1.0.22",
"@waylaidwanderer/chatgpt-api": "^1.28.2",
"axios": "^1.3.4",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-session": "^1.17.3",
"keyv": "^4.5.2",
"keyv-file": "^0.2.0",
"lodash": "^4.17.21",

View file

@ -1,4 +1,5 @@
const express = require('express');
const session = require('express-session')
const dbConnect = require('../models/dbConnect');
const { migrateDb } = require('../models');
const path = require('path');
@ -7,6 +8,7 @@ const routes = require('./routes');
const app = express();
const port = process.env.PORT || 3080;
const host = process.env.HOST || 'localhost'
const userSystemEnabled = process.env.ENABLE_USER_SYSTEM || false
const projectPath = path.join(__dirname, '..', '..', 'client');
dbConnect().then(() => {
console.log('Connected to MongoDB');
@ -16,17 +18,38 @@ dbConnect().then(() => {
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(projectPath, 'public')));
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'chatgpt-clone-random-secrect',
resave: false,
saveUninitialized: true,
}))
app.get('/', function (req, res) {
app.get('/', routes.authenticatedOrRedirect, function (req, res) {
console.log(path.join(projectPath, 'public', 'index.html'));
res.sendFile(path.join(projectPath, 'public', 'index.html'));
});
app.use('/api/ask', routes.ask);
app.use('/api/messages', routes.messages);
app.use('/api/convos', routes.convos);
app.use('/api/customGpts', routes.customGpts);
app.use('/api/prompts', routes.prompts);
app.get('/api/me', function (req, res) {
if (userSystemEnabled) {
const user = req?.session?.user
if (user)
res.send(JSON.stringify({username: user?.username, display: user?.display}));
else
res.send(JSON.stringify(null));
} else {
res.send(JSON.stringify({username: 'anonymous_user', display: 'Anonymous User'}));
}
});
app.use('/api/ask', routes.authenticatedOr401, routes.ask);
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/prompts', routes.authenticatedOr401, routes.prompts);
app.use('/auth', routes.auth);
app.get('/api/models', function (req, res) {
const hasOpenAI = !!process.env.OPENAI_KEY;

View file

@ -37,7 +37,7 @@ router.post('/', async (req, res) => {
});
await saveMessage(userMessage);
await saveConvo({ ...userMessage, model, ...convo });
await saveConvo(req?.session?.user?.username, { ...userMessage, model, ...convo });
return await ask({
userMessage,
@ -176,9 +176,9 @@ const ask = async ({
gptResponse.parentMessageId = overrideParentMessageId || userMessageId;
await saveMessage(gptResponse);
await saveConvo(gptResponse);
await saveConvo(req?.session?.user?.username, gptResponse);
sendMessage(res, {
title: await getConvoTitle(conversationId),
title: await getConvoTitle(req?.session?.user?.username, conversationId),
final: true,
requestMessage: userMessage,
responseMessage: gptResponse
@ -188,10 +188,13 @@ const ask = async ({
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
const title = await titleConvo({ model, text, response: gptResponse });
await saveConvo({
conversationId,
title
});
await saveConvo(
req?.session?.user?.username,
{
conversationId,
title
}
);
}
} catch (error) {
console.log(error);

View file

@ -38,7 +38,7 @@ router.post('/', async (req, res) => {
});
await saveMessage(userMessage);
await saveConvo({ ...userMessage, model, ...convo });
await saveConvo(req?.session?.user?.username, { ...userMessage, model, ...convo });
return await ask({
isNewConversation,
@ -108,10 +108,13 @@ const ask = async ({
// Attition: the api will also create new conversationId while using invalid userMessage.parentMessageId,
// but in this situation, don't change the conversationId, but create new convo.
if (conversationId != userMessage.conversationId && isNewConversation)
await saveConvo({
conversationId: conversationId,
newConversationId: userMessage.conversationId
});
await saveConvo(
req?.session?.user?.username,
{
conversationId: conversationId,
newConversationId: userMessage.conversationId
}
);
conversationId = userMessage.conversationId;
response.text = response.response;
@ -129,9 +132,10 @@ const ask = async ({
response.text = await handleText(response, true);
await saveMessage(response);
await saveConvo({ ...response, model, chatGptLabel: null, promptPrefix: null, ...convo });
await saveConvo(req?.session?.user?.username, { ...response, model, chatGptLabel: null, promptPrefix: null, ...convo });
sendMessage(res, {
title: await getConvoTitle(conversationId),
title: await getConvoTitle(req?.session?.user?.username, conversationId),
final: true,
requestMessage: userMessage,
responseMessage: response
@ -141,10 +145,13 @@ const ask = async ({
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
const title = await titleConvo({ model, text, response });
await saveConvo({
conversationId,
title
});
await saveConvo(
req?.session?.user?.username,
{
conversationId,
title
}
);
}
} catch (error) {
console.log(error);

View file

@ -38,7 +38,7 @@ router.post('/', async (req, res) => {
});
await saveMessage(userMessage);
await saveConvo({ ...userMessage, model, ...convo });
await saveConvo(req?.session?.user?.username, { ...userMessage, model, ...convo });
return await ask({
isNewConversation,
@ -132,18 +132,22 @@ const ask = async ({
// Attition: the api will also create new conversationId while using invalid userMessage.parentMessageId,
// but in this situation, don't change the conversationId, but create new convo.
if (conversationId != userMessage.conversationId && isNewConversation)
await saveConvo({
conversationId: conversationId,
newConversationId: userMessage.conversationId
});
await saveConvo(
req?.session?.user?.username,
{
conversationId: conversationId,
newConversationId: userMessage.conversationId
}
);
conversationId = userMessage.conversationId;
response.text = await handleText(response, true);
// Save sydney response & convo, then send
await saveMessage(response);
await saveConvo({ ...response, model, chatGptLabel: null, promptPrefix: null, ...convo });
await saveConvo(req?.session?.user?.username, { ...response, model, chatGptLabel: null, promptPrefix: null, ...convo });
sendMessage(res, {
title: await getConvoTitle(conversationId),
title: await getConvoTitle(req?.session?.user?.username, conversationId),
final: true,
requestMessage: userMessage,
responseMessage: response
@ -153,10 +157,13 @@ const ask = async ({
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
const title = await titleConvo({ model, text, response });
await saveConvo({
conversationId,
title
});
await saveConvo(
req?.session?.user?.username,
{
conversationId,
title
}
);
}
} catch (error) {
console.log(error);

46
api/server/routes/auth.js Normal file
View file

@ -0,0 +1,46 @@
const express = require('express');
const router = express.Router();
const authYourLogin = require('./authYourLogin');
const userSystemEnabled = process.env.ENABLE_USER_SYSTEM || false
router.get('/login', function (req, res) {
if (userSystemEnabled)
res.redirect('/auth/your_login_page')
else
res.redirect('/')
})
router.get('/logout', function (req, res) {
// clear the session
req.session.user = null
req.session.save(function (error) {
if (userSystemEnabled)
res.redirect('/auth/your_login_page/logout')
else
res.redirect('/')
})
})
const authenticatedOr401 = (req, res, next) => {
if (userSystemEnabled) {
const user = req?.session?.user;
if (user) next();
else res.status(401).end();
} else next();
}
const authenticatedOrRedirect = (req, res, next) => {
if (userSystemEnabled) {
const user = req?.session?.user;
if (user) next();
else res.redirect('/auth/login').end();
} else next();
}
if (userSystemEnabled)
router.use('/your_login_page', authYourLogin);
module.exports = { router, authenticatedOr401, authenticatedOrRedirect };

View file

@ -0,0 +1,40 @@
const express = require('express');
const router = express.Router();
// WARNING!
// THIS IS NOT A READY TO USE USER SYSTEM
// PLEASE IMPLEMENT YOUR OWN USER SYSTEM
const userSystemEnabled = process.env.ENABLE_USER_SYSTEM || false
// Logout
router.get('/logout', (req, res) => {
// Do anything you want
console.warn('logout not implemented!')
// finish
res.redirect('/')
});
// Login
router.get('/', async (req, res) => {
// Do anything you want
console.warn('login not implemented! Automatic passed as sample user')
// save the user info into session
// username will be used in db
// display will be used in UI
req.session.user = {
username: 'sample_user',
display: 'Sample User',
}
req.session.save(function (error) {
if (error) {
console.log(error);
res.send(`<h1>Login Failed. An error occurred. Please see the server logs for details.</h1>`);
} else res.redirect('/')
})
});
module.exports = router;

View file

@ -1,10 +1,39 @@
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));
res.status(200).send(await getConvosByPage(req?.session?.user?.username, pageNumber));
});
router.post('/gen_title', async (req, res) => {
const { conversationId } = req.body.arg;
const convo = await getConvo(req?.session?.user?.username, conversationId)
const firstMessage = (await getMessages({ conversationId }))[0]
const secondMessage = (await getMessages({ conversationId }))[1]
const title = convo.jailbreakConversationId
? await getConvoTitle(req?.session?.user?.username, conversationId)
: await titleConvo({
model: convo?.model,
message: firstMessage?.text,
response: JSON.stringify(secondMessage?.text || '')
});
await saveConvo(
req?.session?.user?.username,
{
conversationId,
title
}
)
res.status(200).send(title);
});
router.post('/clear', async (req, res) => {
@ -15,7 +44,7 @@ router.post('/clear', async (req, res) => {
}
try {
const dbResponse = await deleteConvos(filter);
const dbResponse = await deleteConvos(req?.session?.user?.username, filter);
res.status(201).send(dbResponse);
} catch (error) {
console.error(error);
@ -27,7 +56,7 @@ router.post('/update', async (req, res) => {
const update = req.body.arg;
try {
const dbResponse = await updateConvo(update);
const dbResponse = await updateConvo(req?.session?.user?.username, update);
res.status(201).send(dbResponse);
} catch (error) {
console.error(error);

View file

@ -8,7 +8,7 @@ const {
} = require('../../models');
router.get('/', async (req, res) => {
const models = (await getCustomGpts()).map((model) => {
const models = (await getCustomGpts(req?.session?.user?.username)).map((model) => {
model = model.toObject();
model._id = model._id.toString();
return model;
@ -20,8 +20,8 @@ router.post('/delete', async (req, res) => {
const { arg } = req.body;
try {
await deleteCustomGpts(arg);
const models = (await getCustomGpts()).map((model) => {
await deleteCustomGpts(req?.session?.user?.username, arg);
const models = (await getCustomGpts(req?.session?.user?.username)).map((model) => {
model = model.toObject();
model._id = model._id.toString();
return model;
@ -56,7 +56,7 @@ router.post('/', async (req, res) => {
}
try {
const dbResponse = await setter(update);
const dbResponse = await setter(req?.session?.user?.username, update);
res.status(201).send(dbResponse);
} catch (error) {
console.error(error);

View file

@ -3,5 +3,6 @@ const messages = require('./messages');
const convos = require('./convos');
const customGpts = require('./customGpts');
const prompts = require('./prompts');
const { router: auth, authenticatedOr401, authenticatedOrRedirect } = require('./auth');
module.exports = { ask, messages, convos, customGpts, prompts };
module.exports = { ask, messages, convos, customGpts, prompts, auth, authenticatedOr401, authenticatedOrRedirect };