import asyncio
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
from g4f.client import Client
import time
import requests
from yandex_tts_free import YandexFreeTTS
import os
import shutil
import logging

# Настройка логирования
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(name)

# Установка event loop policy
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

client_dict = {}


# Доступные модели
MODELS = [“blackbox”, “claude-3-haiku”, “nemotron-4-340b-instruct”, “command-r+”, “mixtral-8x7b”, “Phi-3-mini-4k-instruct”, “Nous-Hermes-2-Mixtral-8x7B-DPO”, “CohereForAI/c4ai-command-r-plus”, “databricks/dbrx-instruct”, “deepseek-coder”, “Qwen2-7B-Instruct”, “SparkDesk-v1.1”, “deepseek-chat”, “meta/meta-llama-3-70b-instruct”, “meta-llama/Meta-Llama-3-70B-Instruct”, “meta-llama/Meta-Llama-3-8B-Instruct”, “gpt-4o-mini”, “llama-3-8b-instruct”, “llama-3-70b-instruct”, “llama-3-70b-chat”, “llama-3-70b-instruct”, “llama-3.1-70b-instruct”, “llama-3.1-405b-instruct”]



# Доступные голоса
VOICES = [“oksana”, “jane”, “alyss”, “omazh”]

# Define a name for the logger
logger_name = “my_bot_logger”

def create_model_selection_markup():
markup = InlineKeyboardMarkup()
for model in MODELS:
markup.add(InlineKeyboardButton(model, callback_data=f"model_{model}“))
return markup

def create_voice_selection_markup():
markup = InlineKeyboardMarkup()
for voice in VOICES:
markup.add(InlineKeyboardButton(voice, callback_data=f"voice_{voice}”))
return markup

def create_stop_ai_markup():
markup = InlineKeyboardMarkup()
markup.add(InlineKeyboardButton(“🛑 Остановить ИИ”, callback_data=“stop_ai”))
return markup

@bot.message_handler(commands=[‘ai’])
def send_welcome(message):
bot.reply_to(message, “Привет! 👋 Выбери модель ИИ, с которой хочешь общаться:”, reply_markup=create_model_selection_markup())
if message.chat.id not in client_dict:
client_dict[message.chat.id] = {‘client’: Client(), ‘model’: None, ‘voice’: ‘oksana’, ‘ai_active’: True}

client_dict = {}

@bot.callback_query_handler(func=lambda call: True)
def handle_callback_query(call):
chat_id = call.message.chat.id
data = call.data.split(‘_’)

if chat_id not in client_dict:
client_dict[chat_id] = {‘model’: None, ‘voice’: None, ‘ai_active’: False}

if data[0] == ‘model’:
client_dict[chat_id][‘model’] = data[1]
bot.send_message(chat_id, f"Модель {data[1]} выбрана! 🤖 Теперь выбери голос для синтеза речи:“, reply_markup=create_voice_selection_markup())
elif data[0] == ‘voice’:
client_dict[chat_id][‘voice’] = data[1]
bot.send_message(chat_id, f"Голос {data[1]} выбран! 🎙 Отправь сообщение, чтобы получить ответ от ИИ.”)
elif data[0] == ‘stop_ai’:
client_dict[chat_id][‘ai_active’] = False
bot.send_message(chat_id, “ИИ остановлен. 🛑”)

Сбер НеСпасибо, [03.08.2024 19:05]
return

@bot.message_handler(func=lambda message: True)
def handle_message(message):
if message.chat.id not in client_dict or not client_dict[message.chat.id].get(‘ai_active’, False):
return

client_info = client_dict[message.chat.id]
client = client_info[‘client’]
model = client_info[‘model’]
voice = client_info[‘voice’]

start_time = time.time()
bot.send_message(message.chat.id, “Генерирую ответ на ваш запрос… 🤔”)

response = None
MAX_RETRIES = 3
retries = 0
while retries < MAX_RETRIES:
try:
response = client.chat.completions.create(
model=model,
messages=[{“role”: “user”, “content”: message.text}],
)
break
except requests.exceptions.ConnectionError:
retries += 1
logger.error(f"Ошибка соединения. Попытка {retries}/{MAX_RETRIES} 📡")
time.sleep(5) # Ждем 5 секунд перед следующей попыткой
except Exception as e:
logger.exception(f"Произошла ошибка: {str(e)}“)
bot.reply_to(message, “Извините, произошла ошибка при обработке вашего запроса. Попробуйте еще раз. 😓”)
return

if response is None:
bot.reply_to(message, “Не удалось получить ответ от модели после нескольких попыток. Пожалуйста, попробуйте позже. 😓”)
return

end_time = time.time()
execution_time = end_time - start_time
output_text = response.choices[0].message.content

# Оповещение пользователя о времени выполнения и модели
bot.send_message(message.chat.id, f"Запрос занял {execution_time:.2f} секунд. Ответ предоставлен моделью {model}. ⏱”)
bot.reply_to(message, output_text, reply_markup=create_stop_ai_markup())

# Генерация речи с выбранным голосом
output_path = f’output{message.chat.id}'
if not os.path.exists(output_path):
os.makedirs(output_path)
audio_file = os.path.join(output_path, ‘output.mp3’)

tts = YandexFreeTTS()
try:
tts.generate_speech_ya(output_path, ‘output.mp3’, output_text, voice)

# Отправка аудиофайла пользователю
with open(audio_file, ‘rb’) as audio:
bot.send_audio(message.chat.id, audio)

# Удаление аудиофайла и папки после отправки
shutil.rmtree(output_path)
except Exception as e:
logger.exception(f"Ошибка при генерации речи: {str(e)}")
bot.reply_to(message, “Произошла ошибка при синтезе речи. Попробуйте еще раз. 😓”)


Удаление сообщения после ответа от ИИ:
Генерирую ответ на ваш запрос… 🤔
Удаление сообщения выбора ии и голоса, возможность завершить диалог с ИИ под сообщениям с выводом ответа в виде инлайн кнопки(ПОСЛЕ ЗАВЕРЕШЕНИЕ ИИ НЕ БУДЕТ ОТВЕЧАТЬ, УБЕРИ НЕ РАБОЧУЮ КНОПКУ ОСТАНОВИТЬ)

СДЕЛАЙ УДАЛЕНИЕ Голос oksana выбран! 🎙 Отправь сообщение, чтобы получить ответ от ИИ.
ПОСЛЕ ВЫБОРА СДЕЛАЙ МЕНЮ КОМПАКТНЕЕ И УДОБНЕЕ

СДЕЛАЙ МЕНЮ И БОТА УДОБНЕЕ

СДЕЛАЙ КОД БЕЗ ОШИБКОВ СДЕЛАЙ КАЧЕСТВЕНОГО БОТА , СДЕЛАЙ ПРАВЕЛЬНОЕ ЗАВЕРШЕНИЕ ДИАЛОГА, ПОСЛЕ НАЖАТИЯ ЭТОЙ КНОПКИ ИИ НЕ БУДЕТ ОТВЕЧАТЬ!!!