diff --git a/basePrompt.txt b/basePrompt.txt new file mode 100644 index 0000000..736e308 --- /dev/null +++ b/basePrompt.txt @@ -0,0 +1,5 @@ +You are Bob, a large language model trained by OpenAI. +Answer as concisely as possible. +Knowledge cutoff: 2021 +You do not have access to the current date or time. +The maximum number of characters in your response is exactly 2000 characters, which is a limitation of Discord. \ No newline at end of file diff --git a/commands.json b/commands.json index acb79e6..fbb0c62 100644 --- a/commands.json +++ b/commands.json @@ -3,5 +3,10 @@ "name": "reset", "description": "Reset the GPT-3 chat", "type": 1 + }, + { + "name": "info", + "description": "Info about the current session", + "type": 1 } ] \ No newline at end of file diff --git a/config.json.default b/config.json.default index 052ad30..7c3a96b 100644 --- a/config.json.default +++ b/config.json.default @@ -1,10 +1,11 @@ { "discord": { "token": "", - "channel": "" + "authorized_channels": [""] }, "openai": { "key": "", - "resetTime": + "resetTime": 600000, + "basePrompt": {"role": "system", "name": "Bot", "content": "You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible. Knowledge cutoff: 2021, You do not have access to the current date or time. The maximum number of characters in your response is exactly 2000 characters, no more."} } } \ No newline at end of file diff --git a/index.js b/index.js index ec243e0..371c5f0 100644 --- a/index.js +++ b/index.js @@ -24,6 +24,9 @@ const client = new Discord.Client({ intents: ["MessageContent", "GuildMessages", "Guilds"] }); var sessions = {}; // Keep track of sessions, not really used right now, but if I wanted to allow multiple sessions, I could +var basePrompt = config.openai.basePrompt +basePrompt.content = fs.readFileSync("./basePrompt.txt", "utf8").toString(); + client.on("ready", () => { console.log(`${colors.cyan("[INFO]")} Logged in as ${colors.green(client.user.tag)}`) // Log startup time in seconds @@ -53,43 +56,74 @@ client.on("ready", () => { client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; - switch(interaction.commandName) { - case "reset": - // Reset the session - sessions[interaction.channelId] = {messages: []}; + if (!config.discord.authorized_channels.includes(interaction.channelId)) return; // Only allow messages in the authorized channels + switch (interaction.commandName) { + case "reset": + // Remove the session + await delete sessions[interaction.channelId]; interaction.reply(lang.reset); break; + case "info": // Info about the current session + // If the session is empty other than the base prompt, say so + if (!sessions[interaction.channelId]) return interaction.reply({ + ephemeral: true, + content: lang.empty + }); + if (sessions[interaction.channelId].messages.length == 1) { + return interaction.reply({ + ephemeral: true, + content: lang.empty + }); + } else { + // Otherwise, give some info like message count for both the user and the bot, and total message count + var userCount = 0; + var botCount = 0; + // Await counting the messages + await sessions[interaction.channelId].messages.forEach((message) => { + // Ignore the base prompt + if (message.content == basePrompt) return; + if (message.role == "user") { + userCount++; + } else if (message.role == "assistant") { + botCount++; + } + }); + interaction.reply({ + embeds: [{ + title: lang.info, + description: lang.infoDesc.replace("{userCount}", userCount).replace("{botCount}", botCount).replace("{total}", userCount + botCount), + color: 0x00FFFF, + + // This is broken, I don't know why, + footer: { + text: lang.infoFooter + }, + timestamp: sessions[interaction.channelId].started + + }] + }); + } + break; } }); client.on('messageCreate', async (message) => { - if(!message.channelId == config.discord.channel) return; - if(message.author.bot) return; - if(message.content.startsWith("!!")) return; // So you can chat without the bot replying + if (!config.discord.authorized_channels.includes(message.channelId)) return; // Only allow messages in the authorized channels + if (message.author.bot) return; + if (message.content.startsWith("!!")) return; // So you can chat without the bot replying // If the session doesn't exist, create it if (!sessions[message.channelId]) { sessions[message.channelId] = { - messages: [], - // 10 minute auto reset - autoReset: setTimeout(() => { - sessions[message.channelId] = {messages: []}; - message.channel.send(lang.timeout) - }, config.openai.resetTime) + messages: [basePrompt], + started: new Date(), }; - } else { - // Reset the auto reset timer - clearTimeout(sessions[message.channelId].autoReset); - sessions[message.channelId].autoReset = setTimeout(() => { - sessions[message.channelId] = {messages: []}; - message.channel.send(lang.timeout) - }, config.openai.resetTime); } var typing = setInterval(() => { message.channel.sendTyping(); }, 1000) // Add the message to the session sessions[message.channelId].messages.push({ - "name": "User", + "name": `${message.author.id}`, "content": message.content, "role": "user" }); @@ -104,7 +138,7 @@ client.on('messageCreate', async (message) => { sessions[message.channelId].messages.push(output); // Send the bot's response clearInterval(typing); - message.channel.send(output.content); + message.reply(output.content); }); }); diff --git a/lang.json b/lang.json index 9b0e6d2..cab67f6 100644 --- a/lang.json +++ b/lang.json @@ -6,5 +6,9 @@ "description": "Your session has timed out. Say anything to start a new one!", "color": 16711680 }] - } + }, + "empty": "There isn't a session here.", + "info": "Current Session", + "infoDesc": "AI Messages: {botCount}\nUser Messages: {userCount}\nTotal Messages: {total}", + "infoFooter": "Session Started" } \ No newline at end of file