From 3e5a3f2f7414dc5bf085473c39e0ec08cab7eae0 Mon Sep 17 00:00:00 2001 From: armatik Date: Sat, 2 Sep 2023 19:45:49 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D0=BD=D0=BE=D0=B6=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=B5=D0=BD=D0=BD=D1=8B=D0=B5=20=D1=83=D0=BB=D1=83=D1=87?= =?UTF-8?q?=D1=88=D0=B5=D0=BD=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/OpenAI/GPT35turbo/OA_processing.py | 66 ++++++++++- src/TelegramBot/main.py | 155 +++++++++++++++---------- 2 files changed, 158 insertions(+), 63 deletions(-) diff --git a/src/OpenAI/GPT35turbo/OA_processing.py b/src/OpenAI/GPT35turbo/OA_processing.py index 3af9c63..1bc959b 100644 --- a/src/OpenAI/GPT35turbo/OA_processing.py +++ b/src/OpenAI/GPT35turbo/OA_processing.py @@ -59,9 +59,6 @@ def openai_response(message_formated_text): #запись ошибки в лог с указанием времени и даты with open(os.path.join(mother_path, 'src/OpenAI/GPT35turbo/log.txt'), 'a') as log_file: log_file.write('\n' + time.strftime("%d.%m.%Y %H:%M:%S") + ' ' + str(ex)) - #Проверка на то что ответ не содержит ошибку - count_length = 0 - return response def sort_message_from_user(message_formated_text, message_id): @@ -137,4 +134,65 @@ def openai_message_processing(message_id): else: return f"Сообщение слишком длинное, максимальная длина сообщения \ {max_token_count - len(message_formated_text[0]['content'])} символов, укоротите его на \ - {len(str(cursor.execute('SELECT message_text FROM message_list WHERE message_id'))) - max_token_count} символов" \ No newline at end of file + {len(str(cursor.execute('SELECT message_text FROM message_list WHERE message_id'))) - max_token_count} символов" + +def openai_collecting_history_context(start_id, end_id, message_formated_text, message_id = 0): + # собираем список сообщений для OpenAI длинной до 14500 символов начиная с end_id и заканчивая start_id + if message_id == 0: + message_id = end_id + message_formated_text = openai_collecting_history_context(start_id, end_id, message_formated_text, message_id) + elif message_id > start_id: + message_formated_text = openai_collecting_history_context(start_id, end_id, message_formated_text, (message_id - 1)) + try: + message_formated_text.append({ + "role": "user", + "content": str(*(cursor.execute("SELECT message_text FROM message_list WHERE message_id = ?", + (message_id,)).fetchone())) + }) + except Exception: + pass + + return message_formated_text + +def openai_message_history_processing(start_id, end_id): + message_formated_text = [] + message_formated_text = openai_collecting_history_context(start_id, end_id, message_formated_text) + + max_token_count_history = 15000 + min_token_for_answer_history = 1500 + count_length = 0 + try: + for message in message_formated_text: + count_length += len(message['content']) + while count_length > max_token_count_history - min_token_for_answer_history: + message_formated_text.pop(1) + count_length = 0 + for message in message_formated_text: + count_length += len(message['content']) + except IndexError: + message_formated_text = [ + { + "role": "system", + "content": "Выведи сообщение об ошибке." + } + ] + message_formated_text.append({ + "role": "user", + "content": "Сделай пересказ всей истории сообщений без потери смысла от 3-его лица." + }) + try: + response = openai.ChatCompletion.create( + model="gpt-3.5-turbo-16k", + messages=message_formated_text, + max_tokens=max_token_count_history - count_length + ) + except OpenAIError as ex: + if 'on requests per min. Limit: 3 / min. Please try again' in str(ex): + response = ('Извини мой процессор перегрелся, дай мне минутку отдохнуть') + elif 'Bad gateway.' in str(ex): + response = ( + 'Ой, где я? Кажется кто то перерзал мой интернет кабель, подожди немного пока я его починю') + # запись ошибки в лог с указанием времени и даты + with open(os.path.join(mother_path, 'src/OpenAI/GPT35turbo/log.txt'), 'a') as log_file: + log_file.write('\n' + time.strftime("%d.%m.%Y %H:%M:%S") + ' ' + str(ex)) + return response \ No newline at end of file diff --git a/src/TelegramBot/main.py b/src/TelegramBot/main.py index 85163fb..1b41589 100644 --- a/src/TelegramBot/main.py +++ b/src/TelegramBot/main.py @@ -62,6 +62,7 @@ cursor.execute("""CREATE TABLE IF NOT EXISTS user_list ( user_name TEXT NOT NULL, user_role INTEGER, user_stats INTEGER + user_rep INTEGER )""") #запись информации о чате в базу данных @@ -69,7 +70,6 @@ async def empty_role(id): cursor.execute("UPDATE user_list SET user_role = ? WHERE user_id = ?", (0, id)) database.commit() - async def check(id): #проверка что у человека есть роль user_role = cursor.execute("SELECT user_role FROM user_list WHERE user_id = ?", (id,)).fetchone()[0] @@ -92,6 +92,7 @@ async def get_role(id): user_role = cursor.execute("SELECT user_role FROM user_list WHERE user_id = ?", (id,)).fetchone()[0] return await get_role_name(user_role) + async def check_admin(id, chat_id): #Проверка что человек есть в списке администраторов чата chat_admins = await bot.get_chat_administrators(chat_id) @@ -167,7 +168,7 @@ async def mute(message: types.Message): #получаем id отправителя сообщение на которое отвечает message target_id = message.reply_to_message.from_user.id target_name = cursor.execute("SELECT user_name FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[0] - #Проверка что человек пользователь + #Проверка, что человек пользователь if cursor.execute("SELECT user_role FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[0] == 0: #ограничения прав пользователя по отправке сообщений на time секунд time_sec = await time_to_seconds(message.text.split(' ')[1]) @@ -247,20 +248,6 @@ async def new_chat_members(message: types.Message): #Заносим пользователя в базу данных cursor.execute("INSERT INTO user_list VALUES (?, ?, ?, ?)", (message.new_chat_members[0].id, message.new_chat_members[0].username, 0, 0)) -# @dp.message_handler(commands=['mail']) -# async def mail(message: types.Message): -# #получаем тег пользователя которому должны написать в лс -# target_tag = message.text.split(' ')[1] -# target_tag = target_tag[1:] -# print(target_tag) -# #получаем id пользователя которому должны написать в лс -# target_id = int(cursor.execute("SELECT user_id FROM user_list WHERE user_name = ?", (target_tag,)).fetchone()[0]) -# print(target_id) -# #пишем пользователю в лс, привет {его имя} -# await bot.send_message(target_id, f"Привет {target_tag}! Я бот чата {message.chat.title}. {message.from_user.first_name} хочет с тобой связаться. Напиши ему в лс.") -# #пишем пользователю в чат, что его сообщение отправлено -# await message.reply(f"Сообщение отправлено пользователю {target_tag}") - @dp.message_handler(commands=['chatinfo']) async def chat_info(message: types.Message): @@ -273,11 +260,12 @@ async def chat_info(message: types.Message): chat_moderators = cursor.execute("SELECT COUNT(user_id) FROM user_list WHERE user_role = 1").fetchone()[0] chat_messages = cursor.execute("SELECT chat_stats FROM chat_list WHERE chat_id = ?", (chat_id,)).fetchone()[0] await message.reply( - f"Название чата: {chat_title}\n" - f"Кол-во пользователей: {chat_members}\n" - f"Кол-во администраторов: {len(chat_admins)}\n" - f"Кол-во модераторов: {chat_moderators}\n" - f"Кол-во сообщений: {chat_messages}") + f"Название чата: {chat_title}\n" + f"Количество пользователей: {chat_members}\n" + f"Количество администраторов: {len(chat_admins)}\n" + f"Количество модераторов: {chat_moderators}\n" + f"Количество сообщений: {chat_messages}", + parse_mode="HTML") await top10(message) else: await message.reply( @@ -302,12 +290,18 @@ async def start(message: types.Message): # Проверка наличия столбца имени пользователя в базе данных, если его нет, то добавить. try: cursor.execute("SELECT user_name FROM user_list") - # sqlite3.OperationalError: no such column: user_name except sqlite3.OperationalError: cursor.execute("ALTER TABLE user_list ADD COLUMN user_name TEXT") database.commit() await message.reply("База данных пользователей реструктурирована.") - # Проверка что все участники чата есть в базе данных + # Проверка наличия столбца репутации пользователя в базе данных, если его нет, то добавить. + try: + cursor.execute("SELECT user_rep FROM user_list") + except sqlite3.OperationalError: + cursor.execute("ALTER TABLE user_list ADD COLUMN user_rep INTEGER") + database.commit() + await message.reply("База данных пользователей реструктурирована.") + @dp.message_handler(commands=['top10']) @@ -323,17 +317,6 @@ async def top10(message: types.Message): f"{config['Telegram']['top10_answer']}\n{top10_message}") -@dp.message_handler(commands=['stats']) -async def stat(message: types.Message): - #статистика пользователя в формате: Имя пользователя - количество сообщений - user_stats = cursor.execute("SELECT user_stats FROM user_list WHERE user_id = ?", (message.from_user.id,)).fetchone() - your_id = message.from_id - your_name = message.from_user.username - await message.reply( - f"[{your_name}](tg://user?id={str(your_id)}) - {user_stats[0]}", - parse_mode="Markdown") - - @dp.message_handler(commands=['aboutme']) async def aboutme(message: types.Message): your_id = message.from_id @@ -341,6 +324,10 @@ async def aboutme(message: types.Message): your_name = message.from_user.username user_stats = cursor.execute("SELECT user_stats FROM user_list WHERE user_id = ?", (message.from_user.id,)).fetchone() rolenum = cursor.execute("SELECT user_role FROM user_list WHERE user_id = ?", (message.from_user.id,)).fetchone() + user_rep = cursor.execute("SELECT user_rep FROM user_list WHERE user_id = ?", (message.from_user.id,)).fetchone() + if "None" in str(user_rep): + user_rep = 0 + cursor.execute("UPDATE user_list SET user_rep = ? WHERE user_id = ?", (user_rep, your_id)) role = await get_role_name(rolenum[0]) #Имя пользователя на следующей строке статистика сообщений на следующей строке права пользователя #если пользователь есть в списке администраторов чата, то выдаём роль администратор @@ -352,39 +339,43 @@ async def aboutme(message: types.Message): if admin.user.id == your_id: if default_for_admin == 0: await message.reply( - f"Вы обнаружены в списке администраторов чата! \n" - f"Вам будет выдана роль: {config['Roles']['user']}\n" - f"Имя: [{your_name}](tg://user?id={str(your_id)})\n" - f"Кол-во сообщений: {user_stats[0]}\n" - f"Роль: {role}", - parse_mode="Markdown") + f"Вы обнаружены в списке администраторов чата! \n" + f"Вам будет выдана роль: {config['Roles']['user']}\n" + f"Имя: {your_name}\n" + f"Кол-во сообщений: {user_stats[0]}\n" + f"Репутация: {user_rep[0]}\n" + f"Роль: {role}", + parse_mode="HTML") no_answer = True elif default_for_admin == 1: await message.reply( - f"Вы обнаружены в списке администраторов чата.\n" - f"Вам будет выдана роль: {config['Roles']['moderator']}\n" - f"Имя: [{your_name}](tg://user?id={str(your_id)})\n" - f"Кол-во сообщений: {user_stats[0]}\n" - f"Роль: {role}", - parse_mode="Markdown") + f"Вы обнаружены в списке администраторов чата! \n" + f"Вам будет выдана роль: {config['Roles']['moderator']}\n" + f"Имя: {your_name}\n" + f"Кол-во сообщений: {user_stats[0]}\n" + f"Репутация: {user_rep[0]}\n" + f"Роль: {role}", + parse_mode="HTML") no_answer = True elif default_for_admin == 2: await message.reply( - f"Вы обнаружены в списке администраторов чата.\n" - f"Вам будет выдана роль: {config['Roles']['admin']}\n" - f"Имя: [{your_name}](tg://user?id={str(your_id)})\n" - f"Кол-во сообщений: {user_stats[0]}\n" - f"Роль: {role}", - parse_mode="Markdown") + f"Вы обнаружены в списке администраторов чата! \n" + f"Вам будет выдана роль: {config['Roles']['admin']}\n" + f"Имя: {your_name}\n" + f"Кол-во сообщений: {user_stats[0]}\n" + f"Репутация: {user_rep[0]}\n" + f"Роль: {role}", + parse_mode="HTML") no_answer = True cursor.execute("UPDATE user_list SET user_role = ? WHERE user_id = ?", (default_for_admin, your_id)) database.commit() if no_answer == False: await message.reply( - f"Имя: [{your_name}](tg://user?id={str(your_id)})\n" - f"Кол-во сообщений: {user_stats[0]}\n" - f"Роль: {role}", - parse_mode="Markdown") + f"Имя: {your_name}\n" + f"Кол-во сообщений: {user_stats[0]}\n" + f"Репутация: {user_rep[0]}\n" + f"Роль: {role}", + parse_mode="HTML") @dp.message_handler(commands=['setrole']) async def setrole(message: types.Message): @@ -439,6 +430,10 @@ async def about(message: types.Message): target_name = target_name[1:] target_id = cursor.execute("SELECT user_id FROM user_list WHERE user_name = ?", (target_name,)).fetchone() target_id = target_id[0] + user_rep = cursor.execute("SELECT user_rep FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[0] + if "None" in str(user_rep): + user_rep = 0 + cursor.execute("UPDATE user_list SET user_rep = ? WHERE user_id = ?", (user_rep, target_id)) await check(target_id) except: await message.reply( @@ -448,13 +443,43 @@ async def about(message: types.Message): user_role = cursor.execute("SELECT user_role FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[0] user_role = await get_role_name(user_role) await message.reply( - f"Имя: {target_name}\n" - f"Кол-во сообщений: {user_stats}\n" - f"Роль: {user_role}") + f"Имя: {target_name}\n" + f"Кол-во сообщений: {user_stats}\n" + f"Репутация: {user_rep}\n" + f"Роль: {user_role}", parse_mode="HTML") else: await message.reply( f"Ошибка! Проверьте правильность написания команды.") +from src.OpenAI.GPT35turbo.OA_processing import openai_message_history_processing + +@dp.message_handler(commands=['history']) +async def history(message: types.Message): + if message.reply_to_message is not None: + # Получаем id сообщения на которое отвечает message + start_message_id = message.reply_to_message.message_id + # Получаем id сообщения message + end_message_id = message.message_id + elif message.text.split()[1] != '': + end_message_id = message.message_id + start_message_id = end_message_id - int(message.text.split()[1]) + else: + await message.reply("Ошибка! Проверьте правильность написания команды.") + return + temp_message = await message.reply("Подождите немного, я обрабатываю историю сообщений... Функция ЭКСПЕРЕМЕНТАЛЬНАЯ " + "и может работать некорректно.") + # Получаем историю сообщений + response = openai_message_history_processing(start_message_id, end_message_id) + if response is None: + await message.reply("Я не понял тебя, попробуй перефразировать") + else: + bot_message_id = await message.reply(response['choices'][0]['message']['content'], parse_mode="markdown") + # заносим сообщение в базу данных в качестве message_id мы пишем id сообщения в bot_message_id + cursor.execute("INSERT INTO message_list VALUES (?, ?, ?, ?)", + (bot_message_id.message_id, response['choices'][0]['message']['content'], 0, message.message_id)) + # очищаем сообщение + asyncio.create_task(delete_message(temp_message, 0)) + from src.OpenAI.GPT35turbo.OA_processing import openai_message_processing @@ -493,6 +518,18 @@ async def in_message(message: types.Message): send_answer = True typing_mode = False + if send_answer == False: + # Если сообщение отвечает на другое сообщение, то проверяем наличие слова спасибо + if message.reply_to_message is not None: + if message.text.startswith("Спасибо"): + target_id = message.reply_to_message.from_user.id + target_name = cursor.execute("SELECT user_name FROM user_list WHERE user_id = ?", (target_id,)).fetchone()[0] + cursor.execute("UPDATE user_list SET user_rep = user_rep + 1 WHERE user_id = ?", (target_id,)) + database.commit() + await message.reply( + f"Спасибо, [{target_name}](tg://user?id={str(target_id)}) за ваш ответ!", + parse_mode="Markdown") + if send_answer: if typing_mode is False: your_id = message.from_id