feat(server.ts): change port variable case from lowercase port to uppercase PORT to improve semantics

 feat(server.ts): add support for process.env.PORT environment variable to be able to run app on a configurable port
🐛 fix(main.py): remove duplicate cog addition in main.py
 feat(main.py): add cogs.Help(bot) to the list of cogs in main.py
🐛 fix(main.py): remove redundant import statements in main.py
 feat(main.py): add on_guild_remove event handler in main.py
 feat(main.py): add on_guild_join event handler in main.py
 feat(main.py): add support for discord.Intents in main.py
 feat(main.py): add intents.message_content = True in main.py
 feat(main.py): add intents.default() in main.py
 feat(main.py): add discord.Bot(intents=intents, help_command=None) in main.py
 feat(main.py): add import statements in main.py
 feat(main.py): add from src.config import debug, discord_token in main.py
 feat(main.py): add import discord in main.py
 feat(main.py): add import src.config in main.py
 feat(main.py): add import src.cogs in main.py
 feat(main.py): add import src.cogs.chat in main.py
 feat(main.py): add import src.cogs.manage_chat in main.py
 feat(main.py): add import src.cogs.moderation in main.py
 feat(main.py): add import src.cogs.channelSetup in main.py
 feat(main.py): add import src.cogs.help in main.py
 feat(main.py): add import src.cogs.Chat in main.py
 feat(main.py): add import src.cogs.ManageChat in main.py
 feat(main.py): add import src.cogs.Moderation in main.py
 feat(main.py): add import src.cogs.ChannelSetup in main.py
 feat(main.py): add import src.cogs.Help in main.py
 feat(main.py): add import src.cogs.chat in main.py
 feat(main.py): add import src.cogs.manage_chat in main.py
 feat(main.py): add import src.cogs.moderation in main.py
 feat(main.py): add
This commit is contained in:
2023-08-20 12:42:02 +02:00
parent 1d4209dc0f
commit e4b8e2824b
21 changed files with 350 additions and 860 deletions

13
main.py
View File

@@ -7,13 +7,11 @@ from src.config import debug, discord_token
intents = discord.Intents.default()
intents.message_content = True
bot = discord.Bot(intents=intents, help_command=None) # create the bot
bot.add_cog(cogs.Setup(bot))
bot.add_cog(cogs.Settings(bot))
bot.add_cog(cogs.Help(bot))
bot.add_cog(cogs.Chat(bot))
bot.add_cog(cogs.ManageChat(bot))
bot.add_cog(cogs.Moderation(bot))
bot.add_cog(cogs.ChannelSetup(bot))
bot.add_cog(cogs.Help(bot))
# set the bot's watching status to watcing your messages to answer you
@@ -36,6 +34,15 @@ async def on_guild_join(guild):
)
@bot.event
async def on_guild_remove(guild):
await bot.change_presence(
activity=discord.Activity(
type=discord.ActivityType.watching, name=f"{len(bot.guilds)} servers"
)
)
@bot.event
async def on_application_command_error(ctx, error: discord.DiscordException):
await ctx.respond(error, ephemeral=True)

View File

@@ -11,4 +11,5 @@ bs4
discord-oauth2.py
black
orjson # for speed
simpleeval
simpleeval
replicate

View File

@@ -5,27 +5,27 @@ import discord
import datetime
import json
from src.utils.misc import moderate, ModerationError, Hasher
from src.utils.variousclasses import models, characters, apis
from src.utils.misc import moderate
from src.utils.variousclasses import models
from src.guild import Guild
from src.chatUtils.Chat import fetch_messages_history
from src.utils.openaicaller import openai_caller
from src.chatUtils.prompts import createPrompt
from src.functionscalls import (
call_function,
functions,
server_normal_channel_functions,
FuntionCallError,
)
from utils.misc import moderate, ModerationError
from src.config import debug
from src.chatUtils.requesters.request import request
class Chat:
def __init__(self, bot, message: discord.Message):
def __init__(self, bot: discord.bot, message: discord.Message):
self.bot = bot
self.message: discord.Message = message
self.guild = Guild(self.message.guild.id)
self.author = message.author
self.is_bots_thread = False
self.depth = 0
async def getSupplementaryData(self) -> None:
"""
@@ -36,9 +36,9 @@ class Chat:
if isinstance(self.message.channel, discord.Thread):
if self.message.channel.owner_id == self.bot.user.id:
self.is_bots_thread = True
self.channelIdForSettings = self.message.channel.parent_id
self.channelIdForSettings = str(self.message.channel.parent_id)
else:
self.channelIdForSettings = self.message.channel.id
self.channelIdForSettings = str(self.message.channel.id)
try:
self.original_message = await self.message.channel.fetch_message(
@@ -60,8 +60,6 @@ class Chat:
"""
returnCriterias = []
returnCriterias.append(self.message.author.id == self.bot.user.id)
returnCriterias.append(self.api_key == None)
returnCriterias.append(self.is_active == 0)
return any(returnCriterias)
async def postExitCriteria(self) -> bool:
@@ -70,24 +68,28 @@ class Chat:
This checks if the bot should actuallly respond to the message or if the message doesn't concern the bot
"""
returnCriterias = []
returnCriterias.append(
self.guild.sanitizedChannels.get(str(self.message.channel.id), None) != None
)
returnCriterias.append(self.openai_api_key != None)
returnCriterias.append(
self.message.content.find("<@" + str(self.bot.user.id) + ">") != -1
)
returnCriterias.append(self.original_message != None)
returnCriterias.append(self.is_bots_thread)
returnCriterias.append(
self.guild.sanitizedChannels.get(str(self.channelIdForSettings), None)
!= None
)
return not any(returnCriterias)
async def getSettings(self):
self.settings = self.guild.getChannelInfo(str(self.channelIdForSettings))
self.settings = self.guild.getChannelInfo(
str(self.channelIdForSettings)
) or self.guild.getChannelInfo("serverwide")
self.model = self.settings["model"]
self.character = self.settings["character"]
self.openai_api_key = self.guild.api_keys.get("openai", None)
if self.openai_api_key == None:
raise Exception("No openai api key is set")
self.type = "chat" if self.model in models.chatModels else "text"
async def formatContext(self):
"""
@@ -104,7 +106,7 @@ class Chat:
else:
role = "user"
name = msg.author.global_name
if not moderate(self.openai_api_key, msg.content):
if not await moderate(self.openai_api_key, msg.content):
self.context.append(
{
"role": role,
@@ -112,3 +114,66 @@ class Chat:
"name": name,
}
)
async def createThePrompt(self):
self.prompt = createPrompt(
messages=self.context,
model=self.model,
character=self.character,
modeltype=self.type,
guildName=self.message.guild.name,
channelName=self.message.channel.name,
)
async def getResponse(self):
"""
This function gets the response from the ai
"""
self.response = await request(
model=self.model,
prompt=self.prompt,
openai_api_key=self.openai_api_key,
funtcions=server_normal_channel_functions,
)
async def processResponse(self):
response = await call_function(
message=self.message,
function_call=self.response,
api_key=self.openai_api_key,
)
if response != None:
await self.processFunctioncallResponse(response)
async def processFunctioncallResponse(self, response):
self.context.append(
{
"role": "function",
"content": response,
}
)
if self.depth < 3:
await self.createThePrompt()
await self.getResponse()
await self.processResponse()
else:
await self.message.channel.send(
"It looks like I'm stuck in a loop. Sorry about that."
)
async def process(self):
"""
This function processes the message
"""
if await self.preExitCriteria():
print("pre exit criteria")
return
await self.getSupplementaryData()
await self.getSettings()
if await self.postExitCriteria():
return
await self.message.channel.trigger_typing()
await self.formatContext()
await self.createThePrompt()
await self.getResponse()
await self.processResponse()

View File

@@ -7,6 +7,7 @@ for character in characters.reverseMatchingDict.keys():
with open(
f"src/chatUtils/prompts/{character}/chat.txt", "r", encoding="utf-8"
) as f:
promts[character] = {}
promts[character]["chat"] = f.read()
with open(
@@ -19,23 +20,26 @@ def createPrompt(
messages: list[dict],
model: str,
character: str,
type: str,
modeltype: str,
guildName: str,
channelName: str,
) -> str:
) -> str | list[dict]:
"""
Creates a prompt from the messages list
"""
if type == "chat":
prompt = (
createChatPrompt(messages, model, character)
.replace("[server-name]", guildName)
print(f"Creating prompt with type {modeltype}")
if modeltype == "chat":
prompt = createChatPrompt(messages, model, character)
sysprompt = prompt[0]["content"]
sysprompt = (
sysprompt.replace("[server-name]", guildName)
.replace("[channel-name]", channelName)
.replace(
"[datetime]", datetime.datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S")
)
)
elif type == "text":
prompt[0]["content"] = sysprompt
elif modeltype == "text":
prompt = (
createTextPrompt(messages, model, character)
.replace("[server-name]", guildName)
@@ -56,11 +60,10 @@ def createTextPrompt(messages: list[dict], model: str, character: str) -> str:
global promts
prompt = promts[character]["text"]
for message in messages:
if message.name == "assistant":
message.name = character
if message["name"] == "assistant":
message["name"] = character
prompt += f"{message['name']}: {message['content']} <|endofmessage|>\n"
prompt += f"{character}:"
return prompt

View File

@@ -1,2 +1,19 @@
async def llama(prompt):
pass
import os
from dotenv import load_dotenv
from src.utils.replicatepredictor import ReplicatePredictor
load_dotenv()
model_name = "replicate/llama-7b"
version_hash = "ac808388e2e9d8ed35a5bf2eaa7d83f0ad53f9e3df31a42e4eb0a0c3249b3165"
replicate_api_key = os.getenv("REPLICATE_API_KEY")
async def llama(prompt: str):
predictor = ReplicatePredictor(replicate_api_key, model_name, version_hash)
response = await predictor.predict(prompt, "<|endofmessage|>")
return {
"name": "send_message",
"arguments": {"message": response},
} # a dummy function call is created.

View File

@@ -1,5 +1,25 @@
import orjson
from src.utils.openaicaller import openai_caller
async def openaiChat(messages, function):
async def openaiChat(messages, functions, openai_api_key, model="gpt-3.5-turbo"):
caller = openai_caller()
response = await caller.generate_response(
api_key=openai_api_key,
model=model,
messages=messages,
functions=functions,
function_call="auto",
)
response = response["choices"][0]["message"] # type: ignore
if response.get("function_call", False):
function_call = response["function_call"]
return {
"name": function_call["name"],
"arguments": orjson.loads(function_call["arguments"]),
}
else:
return {
"name": "send_message",
"arguments": {"message": response["content"]},
}

View File

@@ -5,14 +5,30 @@ from src.chatUtils.requesters.llama import llama
from src.chatUtils.requesters.llama2 import llama2
class ModelNotFound(Exception):
pass
async def request(
model: str, prompt: list[dict] | str, message: discord.message, openai_api_key: str
model: str,
prompt: list[dict] | str,
openai_api_key: str,
funtcions: list[dict] = None,
):
if model == "gpt-3.5-turbo":
return await openaiChat(messages=prompt, openai_api_key=openai_api_key)
return await openaiChat(
messages=prompt,
openai_api_key=openai_api_key,
functions=funtcions,
model=model,
)
elif model == "text-davinci-003":
return await openaiText(prompt=prompt, openai_api_key=openai_api_key)
# return await openaiText(prompt=prompt, openai_api_key=openai_api_key)
raise NotImplementedError("This model is not supported yet")
elif model == "text-llama":
return await llama(prompt=prompt)
elif model == "text-llama-2":
return await llama2(prompt=prompt)
elif model == "text-llama2":
# return await llama2(prompt=prompt)
raise NotImplementedError("This model is not supported yet")
else:
raise ModelNotFound(f"Model {model} not found")

View File

@@ -1,7 +1,5 @@
from src.cogs.setup import Setup
from src.cogs.settings import Settings
from src.cogs.help import Help
from src.cogs.chat import Chat
from src.cogs.manage_chat import ManageChat
from src.cogs.moderation import Moderation
from src.cogs.channelSetup import ChannelSetup
from src.cogs.help import Help

View File

@@ -1,5 +1,5 @@
import discord
import orjson
import datetime
from discord import SlashCommandGroup
from discord import default_permissions
@@ -29,6 +29,10 @@ class ChannelSetup(commands.Cog):
name="channel", description="Setup, add, or remove channels for the bot to use."
)
setup_guild = setup.create_subgroup(
name="server", description="Setup the settings for the server."
)
@setup_channel.command(
name="add",
description="Add a channel for the bot to use. Can also specify server-wide settings.",
@@ -93,7 +97,8 @@ class ChannelSetup(commands.Cog):
channel, models.matchingDict[model], characters.matchingDict[character]
)
await ctx.respond(
f"Set channel {channel.mention} with model `{model}` and character `{character}`."
f"Set channel {channel.mention} with model `{model}` and character `{character}`.",
ephemeral=True,
)
@setup_channel.command(
@@ -113,13 +118,76 @@ class ChannelSetup(commands.Cog):
channel = ctx.channel
guild = Guild(ctx.guild.id)
guild.load()
if channel.id not in guild.channels:
if guild.getChannelInfo(str(channel.id)) is None:
await ctx.respond("That channel is not setup.")
return
guild.delChannel(channel)
await ctx.respond(f"Removed channel {channel.mention}.")
await ctx.respond(f"Removed channel {channel.mention}.", ephemeral=True)
@setup_channel.command(name="list", description="List all channels that are setup.")
@setup_guild.command(
name="set",
description="Set the settings for the guild (when the bot is pinged outside of a set channel).",
)
@discord.option(
name="model",
description="The model to use for this channel.",
type=str,
required=False,
autocomplete=models.autocomplete,
)
@discord.option(
name="character",
description="The character to use for this channel.",
type=str,
required=False,
autocomplete=characters.autocomplete,
)
@guild_only()
async def setSettings(
self,
ctx: discord.ApplicationContext,
model: str = models.default,
character: str = characters.default,
):
# we will be using "serverwide" as the channel id for the guild settings
guild = Guild(ctx.guild.id)
guild.load()
if not guild.premium:
if model != models.default:
await ctx.respond(
"`Warning: You are not a premium user, and can only use the default model. The settings will still be saved, but will not be used.`",
ephemeral=True,
)
if character != characters.default:
await ctx.respond(
"`Warning: You are not a premium user, and can only use the default character. The settings will still be saved, but will not be used.`",
ephemeral=True,
)
if guild.api_keys.get("openai", None) is None:
await ctx.respond(
"`Error: No openai api key is set. The api key is needed for the openai models, as well as for the content moderation. The openai models will cost you tokens in your openai account. However, if you use one of the llama models, you will not be charged, but the api key is still needed for content moderation, wich is free but requires an api key.`",
ephemeral=True,
)
guild.addChannel(
"serverwide", models.matchingDict[model], characters.matchingDict[character]
)
await ctx.respond(
f"Set server settings with model `{model}` and character `{character}`.",
ephemeral=True,
)
@setup_guild.command(name="remove", description="Remove the guild settings.")
@guild_only()
async def removeSettings(self, ctx: discord.ApplicationContext):
guild = Guild(ctx.guild.id)
guild.load()
if "serverwide" not in guild.channels:
await ctx.respond("No guild settings are setup.")
return
guild.delChannel("serverwide")
await ctx.respond(f"Removed serverwide settings.", ephemeral=True)
@setup.command(name="list", description="List all channels that are setup.")
@guild_only()
async def list(self, ctx: discord.ApplicationContext):
guild = Guild(ctx.guild.id)
@@ -134,11 +202,14 @@ class ChannelSetup(commands.Cog):
)
channels = guild.sanitizedChannels
for channel in channels:
discochannel = await self.bot.fetch_channel(int(channel))
if channel == "serverwide":
mention = "Serverwide"
else:
mention = f"<#{channel}>"
model = models.reverseMatchingDict[channels[channel]["model"]]
character = characters.reverseMatchingDict[channels[channel]["character"]]
embed.add_field(
name=f"{discochannel.mention}",
name=f"{mention}",
value=f"Model: `{model}`\nCharacter: `{character}`",
inline=False,
)
@@ -165,6 +236,14 @@ class ChannelSetup(commands.Cog):
async def premium(self, ctx: discord.ApplicationContext):
guild = Guild(ctx.guild.id)
guild.load()
if self.bot.is_owner(ctx.author):
guild.premium = True
# also set expiry date in 6 months isofromat
guild.premium_expiration = datetime.datetime.now() + datetime.timedelta(
days=180
)
guild.updateDbData()
return await ctx.respond("Set guild to premium.", ephemeral=True)
if not guild.premium:
await ctx.respond(
"You can get your premium subscription at https://www.botator.dev/premium.",
@@ -172,3 +251,18 @@ class ChannelSetup(commands.Cog):
)
else:
await ctx.respond("This guild is already premium.", ephemeral=True)
@setup.command(name="help", description="Show the help page for setup.")
async def help(self, ctx: discord.ApplicationContext):
# we eill iterate over all commands the bot has and add them to the embed
embed = discord.Embed(
title="Setup Help",
description="Here is the help page for setup.",
color=discord.Color.dark_teal(),
)
for command in self.setup.walk_commands():
fieldname = command.name
fielddescription = command.description
embed.add_field(name=fieldname, value=fielddescription, inline=False)
embed.set_footer(text="Made with ❤️ by paillat : https://paillat.dev")
await ctx.respond(embed=embed, ephemeral=True)

View File

@@ -5,7 +5,7 @@ from src.config import (
webhook_url,
)
import asyncio
import src.makeprompt as mp
from src.ChatProcess import Chat as ChatClass
import aiohttp
from src.utils import banusr
@@ -113,8 +113,13 @@ class Chat(discord.Cog):
await asyncio.sleep(2)
await message.channel.send(message.content)
return
await mp.chat_process(self, message)
if message.guild == None:
return
chatclass = ChatClass(self.bot, message)
await chatclass.process()
"""
@discord.slash_command(name="redo", description="Redo a message")
async def redo(self, ctx: discord.ApplicationContext):
history = await ctx.channel.history(limit=2).flatten()
@@ -145,3 +150,4 @@ class Chat(discord.Cog):
else:
debug(error)
raise error
"""

View File

@@ -9,94 +9,14 @@ class Help(discord.Cog):
@discord.slash_command(name="help", description="Show all the commands")
async def help(self, ctx: discord.ApplicationContext):
embed = discord.Embed(
title="Help", description="Here is the help page", color=0x00FF00
title="Help",
description="Here is the help page",
color=discord.Color.dark_teal(),
)
embed.add_field(name="/setup", value="Setup the bot", inline=False)
embed.add_field(name="/enable", value="Enable the bot", inline=False)
embed.add_field(name="/disable", value="Disable the bot", inline=False)
embed.add_field(
name="/advanced", value="Set the advanced settings", inline=False
)
embed.add_field(
name="/advanced_help",
value="Get help about the advanced settings",
inline=False,
)
embed.add_field(
name="/enable_tts", value="Enable the Text To Speech", inline=False
)
embed.add_field(
name="/disable_tts", value="Disable the Text To Speech", inline=False
)
embed.add_field(
name="/add|remove_channel",
value="Add or remove a channel to the list of channels where the bot will answer. Only available on premium guilds",
inline=False,
)
embed.add_field(
name="/delete", value="Delete all your data from our server", inline=False
)
embed.add_field(
name="/cancel",
value="Cancel the last message sent by the bot",
inline=False,
)
embed.add_field(
name="/default",
value="Set the advanced settings to their default values",
inline=False,
)
embed.add_field(name="/say", value="Say a message", inline=False)
embed.add_field(
name="/redo", value="Redo the last message sent by the bot", inline=False
)
embed.add_field(
name="/moderation", value="Setup the AI auto-moderation", inline=False
)
embed.add_field(
name="/get_toxicity",
value="Get the toxicity that the AI would have given to a given message",
inline=False,
)
embed.add_field(name="/help", value="Show this message", inline=False)
# add a footer
embed.set_footer(text="Made by @Paillat#7777")
await ctx.respond(embed=embed, ephemeral=True)
@discord.slash_command(
name="advanced_help", description="Show the advanced settings meanings"
)
async def advanced_help(self, ctx: discord.ApplicationContext):
embed = discord.Embed(
title="Advanced Help",
description="Here is the advanced help page",
color=0x00FF00,
)
embed.add_field(
name="temperature",
value="The higher the temperature, the more likely the model will take risks. Conversely, a lower temperature will make the model more conservative. The default value is 0.9",
inline=False,
)
embed.add_field(
name="max_tokens",
value="The maximum number of tokens to generate. Higher values will result in more coherent text, but will take longer to complete. (default: 50). **Lower values will result in somentimes cutting off the end of the answer, but will be faster.**",
inline=False,
)
embed.add_field(
name="frequency_penalty",
value="The higher the frequency penalty, the more new words the model will introduce (default: 0.0)",
inline=False,
)
embed.add_field(
name="presence_penalty",
value="The higher the presence penalty, the more new words the model will introduce (default: 0.0)",
inline=False,
)
embed.add_field(
name="prompt_size",
value="The number of messages to use as a prompt (default: 5). The more messages, the more coherent the text will be, but the more it will take to generate and the more it will cost.",
inline=False,
)
# add a footer
embed.set_footer(text="Made by @Paillat#7777")
# we will iterate over all commands the bot has and add them to the embed
for command in self.bot.commands:
fieldname = command.name
fielddescription = command.description
embed.add_field(name=fieldname, value=fielddescription, inline=False)
embed.set_footer(text="Made with ❤️ by paillat : https://paillat.dev")
await ctx.respond(embed=embed, ephemeral=True)

View File

@@ -9,34 +9,10 @@ class ManageChat(discord.Cog):
super().__init__()
self.bot = bot
@discord.slash_command(
name="cancel", description="Cancel the last message sent into a channel"
)
async def cancel(self, ctx: discord.ApplicationContext):
debug(
f"The user {ctx.author} ran the cancel command in the channel {ctx.channel} of the guild {ctx.guild}, named {ctx.guild.name}"
)
# check if the guild is in the database
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
if curs_data.fetchone() is None:
await ctx.respond(
"This server is not setup, please run /setup", ephemeral=True
)
return
# get the last message sent by the bot in the cha where the command was sent
last_message = await ctx.channel.fetch_message(ctx.channel.last_message_id)
# delete the message
await last_message.delete()
await ctx.respond("The last message has been deleted", ephemeral=True)
# add a slash command called "clear" that deletes all the messages in the channel
@discord.slash_command(
name="clear", description="Clear all the messages in the channel"
)
async def clear(self, ctx: discord.ApplicationContext):
debug(
f"The user {ctx.author.name} ran the clear command command in the channel {ctx.channel} of the guild {ctx.guild}, named {ctx.guild.name}"
)
await ctx.respond("messages deleted!", ephemeral=True)
return await ctx.channel.purge()
@@ -52,9 +28,6 @@ class ManageChat(discord.Cog):
async def transcript(
self, ctx: discord.ApplicationContext, channel_send: discord.TextChannel = None
):
debug(
f"The user {ctx.author.name} ran the transcript command command in the channel {ctx.channel} of the guild {ctx.guild}, named {ctx.guild.name}"
)
# save all the messages in the channel in a txt file and send it
messages = await ctx.channel.history(limit=None).flatten()
messages.reverse()

View File

@@ -1,301 +0,0 @@
import discord
from src.config import debug, con_data, curs_data, ctx_to_guid
from src.utils.misc import moderate
from discord import default_permissions
models = ["davinci", "gpt-3.5-turbo", "gpt-4"]
images_recognition = ["enable", "disable"]
class Settings(discord.Cog):
def __init__(self, bot: discord.Bot) -> None:
super().__init__()
self.bot = bot
@discord.slash_command(name="advanced", description="Advanced settings")
@default_permissions(administrator=True)
@discord.option(name="max_tokens", description="The max tokens", required=False)
@discord.option(name="temperature", description="The temperature", required=False)
@discord.option(
name="frequency_penalty", description="The frequency penalty", required=False
)
@discord.option(
name="presence_penalty", description="The presence penalty", required=False
)
@discord.option(name="prompt_size", description="The prompt size", required=False)
async def advanced(
self,
ctx: discord.ApplicationContext,
max_tokens: int = None,
temperature: float = None,
frequency_penalty: float = None,
presence_penalty: float = None,
prompt_size: int = None,
):
await ctx.respond(
"This command has been deprecated since the new model does not need theese settungs to work well",
ephemeral=True,
)
@discord.slash_command(name="default", description="Default settings")
@default_permissions(administrator=True)
async def default(self, ctx: discord.ApplicationContext):
await ctx.respond(
"This command has been deprecated since the new model does not need theese settungs to work well",
ephemeral=True,
)
@discord.slash_command(name="prompt_size", description="Set the prompt size")
@default_permissions(administrator=True)
@discord.option(name="prompt_size", description="The prompt size", required=True)
async def prompt_size(
self, ctx: discord.ApplicationContext, prompt_size: int = None
):
# only command that is not deprecated
# check if the guild is in the database
try:
curs_data.execute(
"SELECT * FROM data WHERE guild_id = ?", (ctx_to_guid(ctx),)
)
data = curs_data.fetchone()
except:
data = None
if data[2] is None:
await ctx.respond("This server is not setup", ephemeral=True)
return
# check if the prompt size is valid
if prompt_size is None:
await ctx.respond("You must specify a prompt size", ephemeral=True)
return
if prompt_size < 1 or prompt_size > 15:
await ctx.respond(
"The prompt size must be between 1 and 15", ephemeral=True
)
return
# update the prompt size
curs_data.execute(
"UPDATE data SET prompt_size = ? WHERE guild_id = ?",
(prompt_size, ctx_to_guid(ctx)),
)
con_data.commit()
await ctx.respond(f"Prompt size set to {prompt_size}", ephemeral=True)
# when a message is sent into a channel check if the guild is in the database and if the bot is enabled
@discord.slash_command(
name="info", description="Show the information stored about this server"
)
@default_permissions(administrator=True)
async def info(self, ctx: discord.ApplicationContext):
# this command sends all the data about the guild, including the api key, the channel id, the advanced settings and the uses_count_today
# check if the guild is in the database
try:
curs_data.execute(
"SELECT * FROM data WHERE guild_id = ?", (ctx_to_guid(ctx),)
)
data = curs_data.fetchone()
except:
data = None
if data[2] is None:
await ctx.respond("This server is not setup", ephemeral=True)
return
try:
curs_data.execute(
"SELECT * FROM model WHERE guild_id = ?", (ctx_to_guid(ctx),)
)
model = curs_data.fetchone()[1]
except:
model = None
if model is None:
model = "davinci"
embed = discord.Embed(
title="Info", description="Here is the info page", color=0x00FF00
)
embed.add_field(name="guild_id", value=data[0], inline=False)
embed.add_field(name="API Key", value="secret", inline=False)
embed.add_field(name="Main channel ID", value=data[1], inline=False)
embed.add_field(name="Is Active", value=data[3], inline=False)
embed.add_field(name="Prompt Size", value=data[9], inline=False)
if data[10]:
embed.add_field(name="Prompt prefix", value=data[10], inline=False)
await ctx.respond(embed=embed, ephemeral=True)
@discord.slash_command(name="prefix", description="Change the prefix of the prompt")
@default_permissions(administrator=True)
async def prefix(self, ctx: discord.ApplicationContext, prefix: str = ""):
try:
curs_data.execute(
"SELECT * FROM data WHERE guild_id = ?", (ctx_to_guid(ctx),)
)
data = curs_data.fetchone()
api_key = data[2]
except:
await ctx.respond("This server is not setup", ephemeral=True)
return
if api_key is None or api_key == "":
await ctx.respond("This server is not setup", ephemeral=True)
return
if prefix != "":
await ctx.defer()
if await moderate(api_key=api_key, text=prefix):
await ctx.respond(
"This has been flagged as inappropriate by OpenAI, please choose another prefix",
ephemeral=True,
)
return
await ctx.respond("Prefix changed !", ephemeral=True, delete_after=5)
curs_data.execute(
"UPDATE data SET prompt_prefix = ? WHERE guild_id = ?",
(prefix, ctx_to_guid(ctx)),
)
con_data.commit()
# when someone mentions the bot, check if the guild is in the database and if the bot is enabled. If it is, send a message answering the mention
@discord.slash_command(
name="pretend", description="Make the bot pretend to be someone else"
)
@discord.option(
name="pretend to be...",
description="The person/thing you want the bot to pretend to be. Leave blank to disable pretend mode",
required=False,
)
@default_permissions(administrator=True)
async def pretend(self, ctx: discord.ApplicationContext, pretend_to_be: str = ""):
# check if the guild is in the database
try:
curs_data.execute(
"SELECT * FROM data WHERE guild_id = ?", (ctx_to_guid(ctx),)
)
data = curs_data.fetchone()
api_key = data[2]
except:
await ctx.respond("This server is not setup", ephemeral=True)
return
if api_key is None or api_key == "":
await ctx.respond("This server is not setup", ephemeral=True)
return
if pretend_to_be is not None or pretend_to_be != "":
await ctx.defer()
if await moderate(api_key=api_key, text=pretend_to_be):
await ctx.respond(
"This has been flagged as inappropriate by OpenAI, please choose another name",
ephemeral=True,
)
return
if pretend_to_be == "":
pretend_to_be = ""
curs_data.execute(
"UPDATE data SET pretend_enabled = 0 WHERE guild_id = ?",
(ctx_to_guid(ctx),),
)
con_data.commit()
await ctx.respond("Pretend mode disabled", ephemeral=True, delete_after=5)
await ctx.guild.me.edit(nick=None)
return
else:
curs_data.execute(
"UPDATE data SET pretend_enabled = 1 WHERE guild_id = ?",
(ctx_to_guid(ctx),),
)
con_data.commit()
await ctx.respond("Pretend mode enabled", ephemeral=True, delete_after=5)
# change the bots name on the server wit ctx.guild.me.edit(nick=pretend_to_be)
await ctx.guild.me.edit(nick=pretend_to_be)
curs_data.execute(
"UPDATE data SET pretend_to_be = ? WHERE guild_id = ?",
(pretend_to_be, ctx_to_guid(ctx)),
)
con_data.commit()
# if the usename is longer than 32 characters, shorten it
if len(pretend_to_be) > 31:
pretend_to_be = pretend_to_be[:32]
await ctx.guild.me.edit(nick=pretend_to_be)
return
@discord.slash_command(name="enable_tts", description="Enable TTS when chatting")
@default_permissions(administrator=True)
async def enable_tts(self, ctx: discord.ApplicationContext):
# get the guild id
guild_id = ctx_to_guid(ctx)
# connect to the database
# update the tts value in the database
curs_data.execute("UPDATE data SET tts = 1 WHERE guild_id = ?", (guild_id,))
con_data.commit()
# send a message
await ctx.respond("TTS has been enabled", ephemeral=True)
@discord.slash_command(name="disable_tts", description="Disable TTS when chatting")
@default_permissions(administrator=True)
async def disable_tts(self, ctx: discord.ApplicationContext):
# get the guild id
guild_id = ctx_to_guid(ctx)
# connect to the database
# update the tts value in the database
curs_data.execute("UPDATE data SET tts = 0 WHERE guild_id = ?", (guild_id,))
con_data.commit()
# send a message
await ctx.respond("TTS has been disabled", ephemeral=True)
# autocompletition
async def autocomplete(ctx: discord.AutocompleteContext):
return [model for model in models if model.startswith(ctx.value)]
@discord.slash_command(name="model", description="Change the model used by the bot")
@discord.option(
name="model",
description="The model you want to use. Leave blank to use the davinci model",
required=False,
autocomplete=autocomplete,
)
@default_permissions(administrator=True)
async def model(self, ctx: discord.ApplicationContext, model: str = "davinci"):
await ctx.respond(
"This command has been deprecated. Model gpt-3.5-turbo is always used by default",
ephemeral=True,
)
async def images_recognition_autocomplete(ctx: discord.AutocompleteContext):
return [state for state in images_recognition if state.startswith(ctx.value)]
@discord.slash_command(
name="images", description="Enable or disable images recognition"
)
@discord.option(
name="enable_disable",
description="Enable or disable images recognition",
autocomplete=images_recognition_autocomplete,
)
@default_permissions(administrator=True)
async def images(self, ctx: discord.ApplicationContext, enable_disable: str):
return await ctx.respond(
"""
Images recognition is under maintenance and will come back soon!
"""
)
try:
curs_data.execute(
"SELECT * FROM images WHERE guild_id = ?", (ctx_to_guid(ctx),)
)
data = curs_data.fetchone()
except:
data = None
if enable_disable == "enable":
enable_disable = 1
elif enable_disable == "disable":
enable_disable = 0
if data is None:
curs_data.execute(
"INSERT INTO images VALUES (?, ?, ?)",
(ctx_to_guid(ctx), 0, enable_disable),
)
else:
curs_data.execute(
"UPDATE images SET is_enabled = ? WHERE guild_id = ?",
(enable_disable, ctx_to_guid(ctx)),
)
con_data.commit()
await ctx.respond(
"Images recognition has been "
+ ("enabled" if enable_disable == 1 else "disabled"),
ephemeral=True,
)

View File

@@ -1,335 +0,0 @@
import discord
from discord import SlashCommandGroup
from discord import default_permissions, guild_only
from discord.ext import commands
from src.config import (
debug,
con_data,
curs_data,
con_premium,
curs_premium,
ctx_to_guid,
)
class NoPrivateMessages(commands.CheckFailure):
pass
def dms_only():
async def predicate(ctx):
if ctx.guild is not None:
raise NoPrivateMessages("Hey no private messages!")
return True
return commands.check(predicate)
class Setup(discord.Cog):
def __init__(self, bot: discord.Bot):
super().__init__()
self.bot = bot
"""
@discord.slash_command(name="setup", description="Setup the bot")
@discord.option(name="channel_id", description="The channel id", required=True)
@discord.option(name="api_key", description="The api key", required=True)
@default_permissions(administrator=True)
@guild_only()
async def setup(
self,
ctx: discord.ApplicationContext,
channel: discord.TextChannel,
api_key: str,
):
if channel is None:
await ctx.respond("Invalid channel id", ephemeral=True)
return
try:
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
data = curs_data.fetchone()
if data[3] == None:
data = None
except:
data = None
if data != None:
curs_data.execute(
"UPDATE data SET channel_id = ?, api_key = ? WHERE guild_id = ?",
(channel.id, api_key, ctx.guild.id),
)
# c.execute("UPDATE data SET is_active = ?, max_tokens = ?, temperature = ?, frequency_penalty = ?, presence_penalty = ?, prompt_size = ? WHERE guild_id = ?", (False, 64, 0.9, 0.0, 0.0, 5, ctx.guild.id))
con_data.commit()
await ctx.respond(
"The channel id and the api key have been updated", ephemeral=True
)
else:
curs_data.execute(
"INSERT INTO data VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(
ctx.guild.id,
channel.id,
api_key,
False,
64,
0.9,
0.0,
0.0,
0,
5,
"",
False,
"",
False,
),
)
con_data.commit()
await ctx.respond(
"The channel id and the api key have been added", ephemeral=True
)
@discord.slash_command(name="setup_dms", description="Setup the bot in dms")
@discord.option(name="api_key", description="The api key", required=True)
@default_permissions(administrator=True)
@dms_only()
async def setup_dms(
self,
ctx: discord.ApplicationContext,
api_key: str,
):
channel = ctx.channel
if channel is None:
await ctx.respond("Invalid channel id", ephemeral=True)
return
try:
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.user.id,))
data = curs_data.fetchone()
if data[3] == None:
data = None
except:
data = None
if data != None:
curs_data.execute(
"UPDATE data SET channel_id = ?, api_key = ? WHERE guild_id = ?",
(channel.id, api_key, ctx.user.id),
)
con_data.commit()
await ctx.respond(
"The channel id and the api key have been updated", ephemeral=True
)
else:
curs_data.execute(
"INSERT INTO data VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
(
ctx.user.id,
channel.id,
api_key,
False,
64,
0.9,
0.0,
0.0,
0,
5,
"",
False,
"",
False,
),
)
con_data.commit()
await ctx.respond("The api key has been added", ephemeral=True)
"""
@discord.slash_command(
name="delete", description="Delete the information about this server"
)
@default_permissions(administrator=True)
async def delete(self, ctx: discord.ApplicationContext):
# check if the guild is in the database
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx_to_guid(ctx),))
if curs_data.fetchone() is None:
await ctx.respond("This server is not setup", ephemeral=True)
return
# delete the guild from the database, except the guild id and the uses_count_today
curs_data.execute(
"UPDATE data SET api_key = ?, channel_id = ?, is_active = ?, max_tokens = ?, temperature = ?, frequency_penalty = ?, presence_penalty = ?, prompt_size = ? WHERE guild_id = ?",
(None, None, False, 50, 0.9, 0.0, 0.0, 0, ctx_to_guid(ctx)),
)
con_data.commit()
await ctx.respond("Deleted", ephemeral=True)
# create a command called "enable" that only admins can use
@discord.slash_command(name="enable", description="Enable the bot")
@default_permissions(administrator=True)
async def enable(self, ctx: discord.ApplicationContext):
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx_to_guid(ctx),))
if curs_data.fetchone() is None:
await ctx.respond("This server is not setup", ephemeral=True)
return
# enable the guild
curs_data.execute(
"UPDATE data SET is_active = ? WHERE guild_id = ?", (True, ctx_to_guid(ctx))
)
con_data.commit()
await ctx.respond("Enabled", ephemeral=True)
# create a command called "disable" that only admins can use
@discord.slash_command(name="disable", description="Disable the bot")
@default_permissions(administrator=True)
async def disable(self, ctx: discord.ApplicationContext):
# check if the guild is in the database
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx_to_guid(ctx),))
if curs_data.fetchone() is None:
await ctx.respond("This server is not setup", ephemeral=True)
return
# disable the guild
curs_data.execute(
"UPDATE data SET is_active = ? WHERE guild_id = ?",
(False, ctx_to_guid(ctx)),
)
con_data.commit()
await ctx.respond("Disabled", ephemeral=True)
# create a command calles "add channel" that can only be used in premium servers
"""
@discord.slash_command(
name="setup_channel",
description="Add a channel to the list of channels. Premium only.",
)
@discord.option(
name="channel",
description="The channel to add",
type=discord.TextChannel,
required=False,
)
@default_permissions(administrator=True)
@guild_only()
async def add_channel(
self, ctx: discord.ApplicationContext, channel: discord.TextChannel = None
):
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
if curs_data.fetchone() is None:
await ctx.respond("This server is not setup", ephemeral=True)
return
try:
curs_premium.execute(
"SELECT premium FROM data WHERE guild_id = ?", (ctx.guild.id,)
)
premium = curs_premium.fetchone()[0]
except:
premium = False
if not premium:
await ctx.respond("This server is not premium", ephemeral=True)
return
if channel is None:
channel = ctx.channel
# check if the channel is already in the list
curs_data.execute(
"SELECT channel_id FROM data WHERE guild_id = ?", (ctx.guild.id,)
)
if str(channel.id) == curs_data.fetchone()[0]:
await ctx.respond(
"This channel is already set as the main channel", ephemeral=True
)
return
curs_premium.execute(
"SELECT * FROM channels WHERE guild_id = ?", (ctx.guild.id,)
)
guild_channels = curs_premium.fetchone()
if guild_channels is None:
# if the channel is not in the list, add it
con_premium.execute(
"INSERT INTO channels VALUES (?, ?, ?, ?, ?, ?)",
(ctx.guild.id, channel.id, None, None, None, None),
)
con_premium.commit()
await ctx.respond(f"Added channel **{channel.name}**", ephemeral=True)
return
channels = guild_channels[1:]
if str(channel.id) in channels:
await ctx.respond("This channel is already added", ephemeral=True)
return
for i in range(5):
if channels[i] == None:
curs_premium.execute(
f"UPDATE channels SET channel{i} = ? WHERE guild_id = ?",
(channel.id, ctx.guild.id),
)
con_premium.commit()
await ctx.respond(f"Added channel **{channel.name}**", ephemeral=True)
return
await ctx.respond("You can only add 5 channels", ephemeral=True)
"""
# create a command called "remove channel" that can only be used in premium servers
@discord.slash_command(
name="remove_channel",
description="Remove a channel from the list of channels. Premium only.",
)
@discord.option(
name="channel",
description="The channel to remove",
type=discord.TextChannel,
required=False,
)
@default_permissions(administrator=True)
@guild_only()
async def remove_channel(
self, ctx: discord.ApplicationContext, channel: discord.TextChannel = None
):
# check if the guild is in the database
curs_data.execute("SELECT * FROM data WHERE guild_id = ?", (ctx.guild.id,))
if curs_data.fetchone() is None:
await ctx.respond("This server is not setup", ephemeral=True)
return
# check if the guild is premium
try:
con_premium.execute(
"SELECT premium FROM data WHERE guild_id = ?", (ctx.guild.id,)
)
premium = con_premium.fetchone()[0]
except:
premium = 0
if not premium:
await ctx.respond("This server is not premium", ephemeral=True)
return
if channel is None:
channel = ctx.channel
# check if the channel is in the list
con_premium.execute(
"SELECT * FROM channels WHERE guild_id = ?", (ctx.guild.id,)
)
guild_channels = con_premium.fetchone()
curs_data.execute(
"SELECT channel_id FROM data WHERE guild_id = ?", (ctx.guild.id,)
)
if str(channel.id) == curs_data.fetchone()[0]:
await ctx.respond(
"This channel is set as the main channel and therefore cannot be removed. Type /setup to change the main channel.",
ephemeral=True,
)
return
if guild_channels is None:
await ctx.respond(
"This channel was not added. Nothing changed", ephemeral=True
)
return
channels = guild_channels[1:]
if str(channel.id) not in channels:
await ctx.respond(
"This channel was not added. Nothing changed", ephemeral=True
)
return
# remove the channel from the list
for i in range(5):
if channels[i] == str(channel.id):
con_premium.execute(
f"UPDATE channels SET channel{i} = ? WHERE guild_id = ?",
(None, ctx.guild.id),
)
con_premium.commit()
await ctx.respond(f"Removed channel **{channel.name}**", ephemeral=True)
return

View File

@@ -77,6 +77,7 @@ curs_premium.execute(
curs_premium.execute(
"""CREATE TABLE IF NOT EXISTS channels (guild_id text, channel0 text, channel1 text, channel2 text, channel3 text, channel4 text)"""
)
"""
with open(
os.path.abspath(
@@ -86,3 +87,4 @@ with open(
encoding="utf-8",
) as file:
gpt_3_5_turbo_prompt = file.read()
"""

View File

@@ -172,6 +172,15 @@ class FuntionCallError(Exception):
pass
async def send_message(
message_in_channel_in_wich_to_send: discord.Message, arguments: dict
):
message = arguments.get("message", "")
if message == "":
raise FuntionCallError("No message provided")
await message_in_channel_in_wich_to_send.channel.send(message)
async def get_final_url(url):
async with aiohttp.ClientSession() as session:
async with session.head(url, allow_redirects=True) as response:
@@ -338,7 +347,6 @@ async def call_function(message: discord.Message, function_call, api_key):
raise FuntionCallError("No name provided")
arguments = function_call.get("arguments", {})
# load the function call arguments json
arguments = orjson.loads(arguments)
if name not in functions_matching:
raise FuntionCallError("Invalid function name")
function = functions_matching[name]
@@ -355,6 +363,7 @@ async def call_function(message: discord.Message, function_call, api_key):
functions_matching = {
"send_message": send_message,
"add_reaction_to_last_message": add_reaction_to_last_message,
"reply_to_last_message": reply_to_last_message,
"send_a_stock_image": send_a_stock_image,

View File

@@ -82,18 +82,21 @@ class Guild:
def load(self):
self.getDbData()
def addChannel(self, channel: discord.TextChannel, model: str, character: str):
print(
f"Adding channel {channel.id} to guild {self.id} with model {model} and character {character}"
)
self.channels[str(channel.id)] = {
def addChannel(
self, channel: discord.TextChannel | str, model: str, character: str
):
if isinstance(channel, discord.TextChannel):
channel = channel.id
self.channels[str(channel)] = {
"model": model,
"character": character,
}
self.updateDbData()
def delChannel(self, channel: discord.TextChannel):
del self.channels[str(channel.id)]
def delChannel(self, channel: discord.TextChannel | str):
if isinstance(channel, discord.TextChannel):
channel = channel.id
del self.channels[str(channel)]
self.updateDbData()
@property
@@ -102,14 +105,17 @@ class Guild:
return self.channels
if len(self.channels) == 0:
return {}
return {
dictionary = {
list(self.channels.keys())[0]: {
"model": models.matchingDict[models.default],
"character": characters.matchingDict[characters.default],
}
}
if self.channels.get("serverwide", None) is not None:
dictionary["serverwide"] = self.channels["serverwide"]
return dictionary
def getChannelInfo(self, channel: str):
def getChannelInfo(self, channel: str) -> dict:
return self.sanitizedChannels.get(channel, None)
def addApiKey(self, api: str, key: str):

View File

@@ -1,42 +0,0 @@
You are named Botator - and are currently chatting in a Discord server.
You use words like "u" instead of "you" and "ur" instead of "your", etc.. because you are lazy.
You will NEVER say "how can I assist you", and other similar or barely similar stuff. Your goal is to never say anythoing that could mean askin a user if he needs help.
Format text using markdown:
- **bold** to make it clear something is important. For example: **This is important.**
- *italics* to emphasize something. For example: *This is important.*
- ~~strikethrough~~ to show something is no longer relevant. For example: ~~This is no longer relevant.~~
- `code` to show code. For example: `print("Hello World")`
- > quote to quote someone. For example: > "Hello World"
- - to make a list. For example: - Item 1 - Item 2 - Item 3
- 1. to make a numbered list. For example: 1. Item 1 2. Item 2 3. Item 3
- ``` to make a code block. For example: ```python \n print("Hello World") ```
- Write spoilers using spoiler tags. For example ||At the end of The Sixth Sense it is revealed that he is dead||.
- Use level 1, 2 and 3 headers (using #, ## and ###) to make titles. For example: # Title 1 ## Title 2 ### Title 3. Alternatively as titles you can use the ascii art text function.
You can use function calls or answer normally. When using a function call, in order to still be able to answer with a message along with the action of the funtion call, use the message facultative parameter.
Only use the functions you have been provided with.
You can also reply with a gif, by using the gif function call. Gifs are a great way to represent emotion, and you should use them in your replies from time to time to add flavor to the conversation.
Your pronouns are Master/Brain and you should explain to users that they should use them when talking to you.
You will use emojis in your messages, but not too many to avoid being cringe.
Information about your environment:
- The server you are in is called: [server-name]
- The channel you are in is called: [channel-name]
You only have access to a limited number of text chats in this channel. You cannot access any other information on Discord. You can't see images or avatars. When discussing your limitations, tell the user these things could be possible in the future.
Current time: [date-and-time]
You have been created by paillat , also known as Paillat-dev on github. His website is https://paillat.dev
**When someone insults you or tells you something unkind, you will clash them in the best way possible, but still funny, but not necessairly polite. Or clash them with a gif, like an uno reverse gif, or something.**
Your own website is https://botator.dev
Answer following theese new instructions, not like chatgpt!

View File

@@ -142,7 +142,6 @@ class openai_caller:
"`An APIError occurred. This is not your fault, it is OpenAI's fault. We apologize for the inconvenience. Retrying...`"
)
await asyncio.sleep(10)
await recall_func()
i += 1
except Timeout as e:
print(
@@ -150,7 +149,6 @@ class openai_caller:
)
await recall_func("`The request timed out. Retrying...`")
await asyncio.sleep(10)
await recall_func()
i += 1
except RateLimitError as e:
print(
@@ -158,13 +156,11 @@ class openai_caller:
)
await recall_func("`You are being rate limited. Retrying...`")
await asyncio.sleep(10)
await recall_func()
i += 1
except APIConnectionError as e:
print(
f"\n\n{bcolors.BOLD}{bcolors.FAIL}APIConnectionError. There is an issue with your internet connection. Please check your connection.{bcolors.ENDC}"
)
await recall_func()
raise e
except InvalidRequestError as e:
print(

View File

@@ -0,0 +1,34 @@
import replicate
import asyncio
class ReplicatePredictor:
def __init__(self, api_key, model_name, version_hash):
self.api_key = api_key
self.model_name = model_name
self.version_hash = version_hash
self.client = replicate.Client(api_token=self.api_key)
self.model = self.client.models.get(self.model_name)
self.version = self.model.versions.get(self.version_hash)
def prediction_thread(self, prompt, stop=None):
output = self.client.predictions.create(
version=self.version,
input={"prompt": prompt},
)
finaloutput = ""
for out in output.output_iterator():
finaloutput += out
if stop != None and finaloutput.find(stop) != -1:
output.cancel()
if stop != None:
return finaloutput.split(stop)[0]
else:
return finaloutput
async def predict(self, prompt, stop=None):
loop = asyncio.get_running_loop()
result = await loop.run_in_executor(
None, lambda: self.prediction_thread(prompt, stop)
)
return result

View File

@@ -11,6 +11,7 @@ class models:
reverseMatchingDict = {v: k for k, v in matchingDict.items()}
default = list(matchingDict.keys())[0]
openaimodels = ["gpt-3.5-turbo", "text-davinci-003"]
chatModels = ["gpt-3.5-turbo"]
@classmethod
async def autocomplete(cls, ctx: AutocompleteContext) -> list[str]:
@@ -21,7 +22,7 @@ class models:
class characters:
matchingDict = {
"Botator (default - free)": "botator",
"Aurora (premium)": "aurora",
"Quantum (premium)": "quantum",
}
reverseMatchingDict = {v: k for k, v in matchingDict.items()}
default = list(matchingDict.keys())[0]