From a6278667e13ade3183127a02ef567f6442b83cc2 Mon Sep 17 00:00:00 2001 From: bignutty <3515180-bignutty@users.noreply.gitlab.com> Date: Sat, 14 Sep 2024 20:52:08 +0200 Subject: [PATCH] gpt is back on the menu --- commands/message/genai/gpt.js | 88 +++++++++++++++++++++++++++++++++++ labscore/api/endpoints.js | 1 + labscore/api/index.js | 7 +++ 3 files changed, 96 insertions(+) create mode 100644 commands/message/genai/gpt.js diff --git a/commands/message/genai/gpt.js b/commands/message/genai/gpt.js new file mode 100644 index 0000000..8133ff8 --- /dev/null +++ b/commands/message/genai/gpt.js @@ -0,0 +1,88 @@ +const { gpt } = require('#api'); + +const { createEmbed } = require('#utils/embed') +const { editOrReply } = require('#utils/message') +const { iconPill, stringwrap, smallIconPill } = require('#utils/markdown') +const { STATICS } = require('#utils/statics'); +const { hasFeature } = require('#utils/testing'); + +// TODO: Turn this into a general purpose permissions constant +const { Permissions } = require("detritus-client/lib/constants"); + +module.exports = { + name: 'gpt', + label: 'text', + aliases: ['chatgpt', 'openai'], + metadata: { + description: `${iconPill("generative_ai", "LIMITED TESTING")}\n${smallIconPill("reply", "Supports Replies")}\n\nTalk to GPT-4o.`, + description_short: 'Chat with GPT-4o.', + examples: ['gpt How many otter species are there?'], + category: 'limited', + usage: 'gpt [-prompt ]' + }, + args: [ + { name: 'prompt', default: '', required: false, help: "The starting system prompt." }, +// { name: 'temperature', default: 0.25, required: false, help: "Model temperature." }, + ], + permissionsClient: [Permissions.EMBED_LINKS, Permissions.SEND_MESSAGES, Permissions.ATTACH_FILES, Permissions.USE_EXTERNAL_EMOJIS, Permissions.READ_MESSAGE_HISTORY], + run: async (context, args) => { + if(!await hasFeature(context, "ai/gpt")) return; + + context.triggerTyping(); + if(!args.text) return editOrReply(context, createEmbed("warning", context, `Missing Parameter (text).`)) + + let input = args.text; + + let prompt = `You are a friendly chat bot designed to help people.\n- Today\'s date is ${new Date().toLocaleDateString('en-us', { weekday:"long", year:"numeric", month:"long", day:"numeric"})}\n- You should always use gender neutral pronouns when possible.\n- When answering a question, be concise and to the point.\n- Try to keep responses below 1000 characters. This does not apply to subjects that require more exhaustive or in-depth explanation.` + if(args.prompt !== "") prompt = args.prompt + + // Get content if the user replies to anything + if(context.message.messageReference) { + let msg = await context.message.channel.fetchMessage(context.message.messageReference.messageId); + + if(msg.content && msg.content.length) input = msg.content + else if(msg.embeds?.length) for(const e of msg.embeds) if(e[1].description?.length) { input = e[1].description; break; } + + prompt = args.text + if(args.prompt !== "") return editOrReply(context, createEmbed("warning", context, `Prompt parameter is unsupported for message replies.`)) + } + + try{ + await editOrReply(context, createEmbed("ai_custom", context, STATICS.openai)) + + let res = await gpt(context, prompt, input) + res = res.response; + + let description = [] + let files = []; + + if(!res.body.response) return editOrReply(context, createEmbed("error", context, `GPT-4o returned an error. Try again later.`)) + + if(res.body.response.length <= 4000) description.push(res.body.response) + else { + files.push({ + filename: `chat.${Date.now().toString(36)}.txt`, + value: Buffer.from(res.body.response) + }) + } + + return editOrReply(context, { + embeds:[createEmbed("defaultNoFooter", context, { + author: { + name: stringwrap(prompt, 50, false), + iconUrl: STATICS.openai + }, + description: description.join('\n'), + footer: { + text: `GPT-4o • Response may be factually wrong or completely made up.` + } + })], + files + }) + }catch(e){ + console.log(e) + if(e.response.body?.message) return editOrReply(context, createEmbed("warning", context, e.response.body.message)) + return editOrReply(context, createEmbed("error", context, `Unable to generate text.`)) + } + } +}; \ No newline at end of file diff --git a/labscore/api/endpoints.js b/labscore/api/endpoints.js index 938ae25..481fd6d 100644 --- a/labscore/api/endpoints.js +++ b/labscore/api/endpoints.js @@ -55,6 +55,7 @@ const Api = Object.freeze({ UTILS_DICTIONARY: '/utils/dictionary-v2', UTILS_EMOJIPEDIA: '/utils/emojipedia', UTILS_GARFIELD: '/utils/garfield', + UTILS_GPT: '/utils/gpt', UTILS_INFERKIT: '/utils/inferkit', UTILS_MAPKIT: '/utils/mapkit', UTILS_OTTER: '/utils/otter', diff --git a/labscore/api/index.js b/labscore/api/index.js index f6bd323..df8d195 100644 --- a/labscore/api/index.js +++ b/labscore/api/index.js @@ -322,6 +322,13 @@ module.exports.garfield = async function(context,){ return await request(Api.UTILS_GARFIELD, "GET", {}, {}) } +module.exports.gpt = async function(context, prompt, input){ + return await request(Api.UTILS_GPT, "GET", {}, { + prompt, + input + }) +} + module.exports.inferkit = async function(context, input){ return await request(Api.UTILS_INFERKIT, "GET", {}, { input: input