From 4b8070b4137af5f336edaf7aeb63e8a6fda29643 Mon Sep 17 00:00:00 2001 From: Paillat Date: Tue, 15 Aug 2023 14:11:21 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20chore(requirements.txt):=20add?= =?UTF-8?q?=20'simpleeval'=20package=20for=20math=20expression=20evaluatio?= =?UTF-8?q?n=20=F0=9F=94=A7=20chore(functionscalls.py):=20add=20'evaluate?= =?UTF-8?q?=5Fmath'=20function=20to=20evaluate=20math=20expressions=20?= =?UTF-8?q?=F0=9F=94=A7=20chore(makeprompt.py):=20refactor=20'chatgpt=5Fpr?= =?UTF-8?q?ocess'=20to=20use=20'prepare=5Fmessages'=20function=20for=20mes?= =?UTF-8?q?sage=20preparation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements.txt | 3 ++- src/functionscalls.py | 37 +++++++++++++++++++++++++++++++++++-- src/makeprompt.py | 32 +++++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0d63283..cfa296b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ tiktoken bs4 discord-oauth2.py black -orjson # for speed \ No newline at end of file +orjson # for speed +simpleeval \ No newline at end of file diff --git a/src/functionscalls.py b/src/functionscalls.py index 2f36b95..bb25c53 100644 --- a/src/functionscalls.py +++ b/src/functionscalls.py @@ -1,8 +1,11 @@ import discord import asyncio +import orjson import aiohttp import random import time + +from simpleeval import simple_eval from bs4 import BeautifulSoup from src.config import tenor_api_key @@ -117,6 +120,20 @@ functions = [ "required": ["query"], }, }, + { + "name": "evaluate_math", + "description": "Get the result of a math expression. Only math expressions are supported, no variables, no functions.", + "parameters": { + "type": "object", + "properties": { + "string": { + "type": "string", + "description": "The string to evaluate", + } + }, + "required": ["string"], + }, + }, ] server_normal_channel_functions = [ @@ -253,7 +270,6 @@ async def send_ascii_art_text( asciiiar_url = ( f"https://asciified.thelicato.io/api/v2/ascii?text={text}&font={font}" ) - print(asciiiar_url) ascii_art = await do_async_request(asciiiar_url, json=False) final_message = f"```\n{ascii_art}```\n{message}" if len(final_message) < 2000: @@ -299,15 +315,31 @@ async def send_ascii_art_image( await message_in_channel_in_wich_to_send.channel.send(message) +async def evaluate_math( + message_in_channel_in_wich_to_send: discord.Message, arguments: dict +): + evaluable = arguments.get("string", "") + if evaluable == "": + raise FuntionCallError("No string provided") + try: + result = simple_eval(evaluable) + except Exception as e: + result = f"Error: {e}" + return f"Result to math eval of {evaluable}: ```\n{str(result)}```" + + async def call_function(message: discord.Message, function_call): name = function_call.get("name", "") if name == "": 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] - await function(message, arguments) + returnable = await function(message, arguments) + return returnable functions_matching = { @@ -318,4 +350,5 @@ functions_matching = { "send_ascii_art_text": send_ascii_art_text, "send_ascii_art_image": send_ascii_art_image, "create_a_thread": create_a_thread, + "evaluate_math": evaluate_math, } diff --git a/src/makeprompt.py b/src/makeprompt.py index f4e930a..adc90fa 100644 --- a/src/makeprompt.py +++ b/src/makeprompt.py @@ -44,9 +44,7 @@ async def fetch_messages_history(channel: discord.TextChannel, limit, original_m return messages -async def chatgpt_process( - self, messages, message: discord.Message, api_key, prompt, model -): +async def prepare_messages(self, messages, message: discord.Message, api_key, prompt): async def error_call(error=""): try: if error != "": @@ -116,6 +114,20 @@ async def chatgpt_process( ) await message.channel.trigger_typing() + return msgs + + +async def chatgpt_process(self, msgs, message: discord.Message, api_key, prompt, model): + async def error_call(error=""): + try: + if error != "": + await message.channel.send( + f"An error occured: {error}", delete_after=10 + ) + await message.channel.trigger_typing() + except: + pass + response = str() caller = openai_caller() called_functions = ( @@ -134,7 +146,16 @@ async def chatgpt_process( response = response["choices"][0]["message"] # type: ignore if response.get("function_call"): function_call = response.get("function_call") - await call_function(message, function_call) + returned = await call_function(message, function_call) + if returned != None: + msgs.append( + { + "role": "function", + "content": returned, + "name": function_call.get("name"), + } + ) + await chatgpt_process(self, msgs, message, api_key, prompt, model) else: content = response.get("content", "") while len(content) != 0: @@ -283,4 +304,5 @@ async def chat_process(self, message): ) .replace("[pretend-to-be]", pretend_to_be) ) - await chatgpt_process(self, messages, message, api_key, prompt, model) + emesgs = await prepare_messages(self, messages, message, api_key, prompt) + await chatgpt_process(self, emesgs, message, api_key, prompt, model)