File size: 6,103 Bytes
6066e39
 
 
1cc747b
6066e39
 
 
 
 
 
 
1cc747b
6066e39
 
 
 
 
 
61cb8bb
 
6066e39
 
 
 
 
 
 
0a1a5b2
 
6066e39
 
 
 
 
 
 
 
 
 
 
fe6d0c3
6066e39
 
fe6d0c3
6066e39
61cb8bb
6066e39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed7da4e
6066e39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed7da4e
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import logging
import os
from platform import system

from dotenv import load_dotenv
from huggingface_hub import HfApi, HfFolder
from humanfriendly.terminal import output
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, MessageHandler, filters, CallbackContext
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

load_dotenv()
TOKEN = os.getenv("TELEGRAM_TOKEN")
HF_TOKEN = os.getenv("HF_TOKEN")
MAX_LENGTH_REQUEST = 1024
MAX_NEW_TOKENS = 128
MAX_LENGTH_RESPONSE = 100
TEST_ENV=os.getenv("TEST_ENV")

# Настройка логирования
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

logger.info(f"TEST_ENV= {TEST_ENV}")

# Логин через токен
try:
    api = HfApi()
    HfFolder.save_token(HF_TOKEN)
except Exception as e:
    logger.error(f"Ошибка авторизации токена: {str(e)}")
    raise

rugpt3large_based_on_gpt2_model_name = "ai-forever/rugpt3large_based_on_gpt2"
rugpt3small_based_on_gpt2_model_name = "ai-forever/rugpt3small_based_on_gpt2"
sber_rugpt3small_based_on_gpt2_model_name = "sberbank-ai/rugpt3small_based_on_gpt2"
phi_mini_instruct_GGUF_model_name = "bartowski/Phi-3.5-mini-instruct-GGUF"
# Инициализация модели
try:
    model_name = phi_mini_instruct_GGUF_model_name # Меньшая модель
    tokenizer = AutoTokenizer.from_pretrained(model_name, padding_side="left")
    model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")
    logger.info("Модель успешно загружена")
except Exception as e:
    logger.error(f"Ошибка загрузки модели: {str(e)}")
    raise

# Настройка устройства
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
logger.info(f"Используемое устройство: {device}")

# Контекст диалога (упрощенная версия)
chat_contexts = {}


def get_chat_context(chat_id):
    if chat_id not in chat_contexts:
        chat_contexts[chat_id] = {"history": []}
    return chat_contexts[chat_id]


MAX_HISTORY_LENGTH = 10


def add_to_chat_history(chat_id, user_input, bot_response):
    context = get_chat_context(chat_id)
    context["history"].append({"user": user_input, "bot": bot_response})
    if len(context["history"]) > MAX_HISTORY_LENGTH:
        context["history"] = context["history"][-MAX_HISTORY_LENGTH:]


async def start(update: Update, context: CallbackContext) -> None:
    """Обработчик команды /start"""
    await update.message.reply_text('🚀 Привет! Я РУССКИЙ! :) бот.')


async def handle_message(update: Update, context: CallbackContext) -> None:
    """Обработка текстовых сообщений"""
    try:
        user_input = update.message.text
        chat_id = update.message.chat_id
        user_name = update.message.from_user.username
        logger.info(f"Получено сообщение: {user_input}")

        # Получаем контекст чата
        context = get_chat_context(chat_id)

        # Формируем входной текст с учетом истории
        input_text = ""
        for msg in context["history"]:
            input_text += f"Пользователь: {msg['user']}\nБот: {msg['bot']}"

        tokenizer.pad_token = tokenizer.eos_token
        # Генерация промта
        system_prompt = "Ответ должен быть точным и кратким."
        # system_prompt = ""
        # prompt = f"{system_prompt} Вопрос: {user_input}; Ответ: "
        prompt = f"{system_prompt}\n {user_input}\n"
        logger.info(f"Промт: {prompt}")

        # Генерация ответа
        inputs = tokenizer(
            prompt,
            return_tensors="pt",  # Возвращает PyTorch тензоры
            # truncation=True,  # Обрезает текст, если он превышает max_length
            # add_special_tokens=True,  # Добавляет специальные токены (например, [CLS], [SEP])
        ).to(device)

        outputs = model.generate(
            inputs.input_ids,
            max_new_tokens=60,
            no_repeat_ngram_size=3,
            repetition_penalty=1.5,
            do_sample=True,
            top_k=100,
            top_p=0.3,
            temperature=0.4,
            stop_strings=['<s>'],
            tokenizer=tokenizer,
        )

        # Декодирование ответа
        # response = list(map(tokenizer.decode, outputs))[0]
        response = tokenizer.batch_decode(outputs[:, inputs.input_ids.shape[1]:], skip_special_tokens=True)[0]
        logger.info(f"Ответ: {response}")

        if not response:
            response = "🤔 Пока не знаю, что ответить. Можете переформулировать вопрос?"

        # Отправка ответа
        await update.message.reply_text(response, parse_mode=None)
        add_to_chat_history(chat_id, user_input, response)

    except Exception as e:
        logger.error(f"Ошибка обработки сообщения: {str(e)}")
        await update.message.reply_text("❌ Произошла ошибка при обработке запроса")


def app() -> None:
    try:
        application = ApplicationBuilder().token(TOKEN).build()
        application.add_handler(CommandHandler("start", start))
        application.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
        application.add_error_handler(error)

        logger.info("Бот запущен")
        application.run_polling()

    except Exception as e:
        logger.error(f"Ошибка запуска бота: {str(e)}")


async def error(update: Update, context: CallbackContext) -> None:
    logger.error(f'Ошибка: {context.error}')


if __name__ == '__app__':
    app()