0
0
mirror of https://gitflic.ru/project/maks1ms/ocab.git synced 2024-12-24 16:44:44 +03:00

Minimal Work model. WARNING! Very much GOVNOkod

This commit is contained in:
armatik 2023-07-12 23:51:01 +03:00
parent 083287d6a0
commit 3e10e9b806
6 changed files with 266 additions and 30 deletions

View File

@ -4,7 +4,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" /> <excludeFolder url="file://$MODULE_DIR$/venv" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="jdk" jdkName="Python 3.11 (venv)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

View File

@ -1,18 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true"> <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="ACAB_DB" uuid="dddbe297-bec2-4e5c-b2b2-b7cea1bfdc0c"> <data-source source="LOCAL" name="OCAB_DB.db" uuid="bdda4c2e-5465-4855-9b40-cb80a36e16bf">
<driver-ref>sqlite.xerial</driver-ref> <driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize> <synchronize>true</synchronize>
<remarks>Содержит в себе список(tg_id)
пользователей бота с количеством
истраченных символов, репутацией
и лимитом символов для запросов.</remarks>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver> <jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/DataBase/UserList</jdbc-url> <jdbc-url>jdbc:sqlite:$PROJECT_DIR$/DataBase/OCAB_DB.db</jdbc-url>
<jdbc-additional-properties>
<property name="EXTERNAL_DATA_PATH" value="$PROJECT_DIR$/external-data.xml" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir> <working-dir>$ProjectFileDir$</working-dir>
</data-source> </data-source>
</component> </component>

View File

@ -0,0 +1,134 @@
import sqlite3
import os
import configparser
mother_path = os.path.dirname(os.path.dirname(os.getcwd()))
config = configparser.ConfigParser()
config.read(os.path.join(mother_path, 'src/config.ini'))
database = sqlite3.connect(os.path.join(mother_path, 'DataBase/OCAB_DB.db'))
cursor = database.cursor()
# Импорт библиотек
import openai
max_token_count = int(config['Openai']['max_token_count'])
base_message_formated_text = [
{
"role": "system",
"content": config['Openai']['story_model']
}
]
def openai_response(message_formated_text):
# Запуск OpenAI
# Считаем размер полученного текста
print(message_formated_text)
count_length = 0
for message in message_formated_text:
print(message["content"])
count_length += len(message["content"])
print(count_length)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=message_formated_text,
max_tokens=max_token_count - count_length
)
return response
def sort_message_from_user(message_formated_text, message_id):
print(int(*(
cursor.execute("SELECT message_sender FROM message_list WHERE message_id = ?", (message_id,)).fetchone())))
if int(*(
cursor.execute("SELECT message_sender FROM message_list WHERE message_id = ?",
(message_id,)).fetchone())) == 0:
message_formated_text.append({
"role": "assistant",
"content": str(*(cursor.execute("SELECT message_text FROM message_list WHERE message_id = ?",
(message_id,)).fetchone()))
})
else:
message_formated_text.append({
"role": "user",
"content": str(*(cursor.execute("SELECT message_text FROM message_list WHERE message_id = ?",
(message_id,)).fetchone()))
})
#Проверка что длина всех сообщений в кортеже не превышает max_token_count-500
count_length = 0
for message in message_formated_text:
count_length += len(message['content'])
if count_length > max_token_count-800:
message_formated_text.pop(1)
return message_formated_text
def openai_collecting_message(message_id, message_formated_text):
# собирает цепочку сообщений для OpenAI длинной до max_token_count
# проверяем что сообщение отвечает на другое сообщение
if int(*(cursor.execute("SELECT answer_id FROM message_list WHERE message_id = ?", (message_id,)).fetchone())) not in (0, 643885, 476959, 1, 476977, 633077, 630664, 476966, 634567):
# Продолжаем искать ответы на сообщения
print(int(*(cursor.execute("SELECT answer_id FROM message_list WHERE message_id = ?", (message_id,)).fetchone())))
message_formated_text = openai_collecting_message(int(*(cursor.execute("SELECT answer_id FROM message_list WHERE message_id = ?", (message_id,)).fetchone())), message_formated_text)
#Проверяем ID отправителя сообщения, если 0 то это сообщение от бота
sort_message_from_user(message_formated_text, message_id)
else:
# Проверяем ID отправителя сообщения, если 0 то это сообщение от бота
sort_message_from_user(message_formated_text, message_id)
return message_formated_text
# if (((cursor.execute("SELECT answer_id FROM message_list WHERE message_id") is None)) or (cursor.execute("SELECT answer_id FROM message_list WHERE message_id") == 643885)):
# openai_collecting_message(cursor.execute("SELECT answer_id FROM message_list WHERE message_id"))
# # проверяем что с новым сообщение длина всех сообщений в цепочке не будет превышать max_token_count
# count_length = 0
# for message in message_formated_text:
# count_length += len(message['content'])
# if count_length + len(cursor.execute("SELECT message_text FROM message_list WHERE message_id = ?", (message_id,)).fetchone()) > max_token_count:
# message_formated_text.pop(1)
# print(int(*(cursor.execute("SELECT message_sender FROM message_list WHERE message_id = ?", (message_id,)).fetchone())))
# if int(*(cursor.execute("SELECT message_sender FROM message_list WHERE message_id = ?", (message_id,)).fetchone())) == 0:
# message_formated_text.append({
# "role": "assistant",
# "content": str(*(cursor.execute("SELECT message_text FROM message_list WHERE message_id = ?", (message_id,)).fetchone()))
# })
# else:
# message_formated_text.append({
# "role": "user",
# "content": str(*(cursor.execute("SELECT message_text FROM message_list WHERE message_id = ?", (message_id,)).fetchone()))
# })
def openai_message_processing(message_id):
#проверяем на наличие сообщения в базе данных
if cursor.execute("SELECT message_text FROM message_list WHERE message_id = ?", (message_id,)).fetchone() is None:
return None
else:
# проверяем на то что сообщение влезает в max_token_count с учётом message_formated_text
#print((len(str(cursor.execute("SELECT message_text FROM message_list WHERE message_id")))))
#print(len(message_formated_text[0]['content']))
#print(max_token_count)
#print(max_token_count - len(message_formated_text[0]['content']))
message_formated_text = base_message_formated_text
if ((len(str(cursor.execute("SELECT message_text FROM message_list WHERE message_id")))) < (max_token_count - len(message_formated_text[0]['content']))):
message_formated_text = openai_collecting_message(message_id, message_formated_text)
response = openai_response(message_formated_text)
return response
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} символов"

View File

@ -3,12 +3,6 @@ from aiogram import types
from src.TelegramBot.main import dp from src.TelegramBot.main import dp
from main import cursor, config
@dp.message_handler() #импортировать функцию для обработки сообщений из OpenAI
async def send(message: types.Message):
# Получение сообщений в чате, и запись их в базу данных
# Проверка на то, что сообщение не пустое и не отправлено в чате содержащим ChatType = 1 в базе данных chatlist
if (message.chat.type == "group" or message.chat.type == "supergroup") and \
message.text != '' and message.text != ' ': return None
else:
# Проверка статуса ChatType в базе данных chatlist

View File

@ -1,23 +1,29 @@
# Файл с инициализацией всех процессов телеграмм бота и запуском API OpenAI
# Импорт библиотек # Импорт библиотек
import os import os
from contextlib import suppress
import openai import openai
import configparser import configparser
import sqlite3 import sqlite3
import asyncio
from aiogram import Bot, Dispatcher, executor, types from aiogram import Bot, Dispatcher, executor, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.utils.exceptions import MessageCantBeDeleted, MessageToDeleteNotFound
from MessageHandler import * mother_path = os.path.dirname(os.path.dirname(os.getcwd()))
# Импорт переменных из файла .ini # Импорт переменных из файла .ini
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(os.path.join(os.path.dirname(__file__), 'config.ini')) config.read(os.path.join(mother_path, 'src/config.ini'))
TOKEN = config['Telegram']['token'] TOKEN = config['Telegram']['token']
OPENAI_API_KEY = config['OpenAI']['api_key'] OPENAI_API_KEY = (config['Openai']['api_key'])
bot_trigger_front = (config['Telegram']['bot_trigger_front']).split('|')
bot_trigger_all = (config['Telegram']['bot_trigger_all']).split('|')
# удаление лишних элементов массивов
bot_trigger_front.remove('')
bot_trigger_all.remove('')
# Инициализация бота # Инициализация бота
@ -29,8 +35,100 @@ dp = Dispatcher(bot, storage=MemoryStorage())
openai.api_key = OPENAI_API_KEY openai.api_key = OPENAI_API_KEY
# Инициализация базы данных OCAB_DB в папке DataBase/OCAB_DB.db # Инициализация базы данных OCAB_DB в папке DataBase/OCAB_DB.db
database = sqlite3.connect(os.path.join(os.path.dirname(__file__), 'DataBase/OCAB_DB.db')) # Создаём базу данных sqlite3 по пути /home/armatik/PycharmProjects/OpenChatAiBot/DataBase/OCAB_DB.db
database = sqlite3.connect(os.path.join(mother_path, 'DataBase/OCAB_DB.db'))
cursor = database.cursor() cursor = database.cursor()
# Создаём таблицу chat_list
cursor.execute("""CREATE TABLE IF NOT EXISTS chat_list (
chat_id INTEGER PRIMARY KEY,
chat_role INTEGER NOT NULL,
chat_stats INTEGER NOT NULL
)""")
# Создаём таблицу message_list
cursor.execute("""CREATE TABLE IF NOT EXISTS message_list (
message_id INTEGER PRIMARY KEY,
message_text TEXT NOT NULL,
message_sender INTEGER NOT NULL,
answer_id INTEGER
)""")
# Создаём таблицу user_list
cursor.execute("""CREATE TABLE IF NOT EXISTS user_list (
user_id INTEGER PRIMARY KEY,
user_role INTEGER,
user_stats INTEGER
)""")
#запись информации о чате в базу данных
@dp.message_handler(commands=['start'])
async def start(message: types.Message):
chat_id = message.chat.id
chat_role = 0
chat_stats = 1
cursor.execute("INSERT INTO chat_list VALUES (?, ?, ?)", (chat_id, chat_role, chat_stats))
database.commit()
await message.reply("Привет, я бот, который учится на основе модели GPT-3.5. "
"Я могу поговорить с тобой на любую тему, но пока что я не очень умный, поэтому не обижайся, "
"если я не пойму тебя. Чтобы начать общение со мной, напиши мне сообщение, начинающееся с "
"слова Арма, например: Арма, как дела?")
from src.OpenAI.GPT35turbo.OA_processing import openai_message_processing
async def delete_message(message: types.Message, sleep_time: int = 0):
await asyncio.sleep(sleep_time)
with suppress(MessageCantBeDeleted, MessageToDeleteNotFound):
await message.delete()
@dp.message_handler()
async def in_message(message: types.Message):
chat_id = message.chat.id
# Получение сообщений в чате, и запись их в базу данных
# Проверка на то, что сообщение не пустое и не отправлено в чате содержащим ChatType = 1 в базе данных chatlist
if (message.chat.type != "group" or message.chat.type != "supergroup") and \
message.text != '' and message.text != ' ' and \
(cursor.execute("SELECT chat_role FROM chat_list WHERE chat_id;") == 1): return None
else:
# Запись сообщения в базу данных
cursor.execute("INSERT INTO message_list VALUES (?, ?, ?, ?)",
(message.message_id, message.text, message.from_user.id, None))
if message.reply_to_message is not None:
# Запись ответа на сообщение в базу данных
cursor.execute("UPDATE message_list SET answer_id = ? WHERE message_id = ?",
(message.reply_to_message.message_id, message.message_id))
database.commit()
# Обработка сообщения OpenAI
send_answer = False
# импортируем массив триггеров из файла .ini
if message.reply_to_message and message.reply_to_message.from_user.id == (await bot.me).id:
send_answer = True
for trigger in bot_trigger_all:
if trigger.lower() in message.text.lower():
send_answer = True
for trigger in bot_trigger_front:
if message.text.lower().startswith(trigger.lower()):
send_answer = True
if send_answer:
your_id = message.from_id
your_name = message.from_user.username
temp_msg = await message.reply(
f"[{your_name}](tg://user?id={str(your_id)}), Подожди немного и я обязательно отвечу тебе!",
parse_mode="Markdown")
response = openai_message_processing(message.message_id)
if response is None:
bot_message_id = await message.reply("Я не понял тебя, попробуй перефразировать")
asyncio.create_task(delete_message(temp_msg, 0))
#заносим сообщение в базу данных в качестве message_id пишем id сообщения которое отправил бот
cursor.execute("INSERT INTO message_list VALUES (?, ?, ?, ?)",
(bot_message_id, "Я не понял тебя, попробуй перефразировать", 0, message.message_id))
else:
bot_message_id = await message.reply(response['choices'][0]['message']['content'], parse_mode="markdown")
asyncio.create_task(delete_message(temp_msg, 0))
#заносим сообщение в базу данных в качестве 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))
database.commit()
if __name__ == '__main__': if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True) executor.start_polling(dp, skip_updates=True)

View File

@ -1,7 +1,24 @@
[Telegram] [Telegram]
token="....." token=****
admin_password="Test_pass" # ONLY FOR ADDING CHAT TO ADMIN LIST! admin_password="Test_pass"
# Пока не используется
[OpenAI] # Массивы заполнять через запятую. Пример: test|test2 |test3,
token="....." bot_trigger_front=
chat_model="....." # Живой пример: Арма |Армат |Арма, |
bot_trigger_all=
# Живой пример: @arma_ai_bot |помогите |
[Openai]
api_key=****
chat_model=gpt-3.5-turbo
story_model=
# Тут должен быть текст истории бота, но я его не показываю)))
max_token_count=4000
# максимальное количество токенов в сообщении
min_token_for_answer=800
# минимальное количество токенов в сообщении ответа бота (чем больше, тем более длинный ответ ГАРАНТИРОВАН)
[AI_Dungeon]
use=openai
# "openai" or "YaGPT" Пока не используется