File size: 19,868 Bytes
f35bde9
26471fd
f35bde9
 
 
26471fd
899870f
20ffed9
26471fd
20ffed9
 
26471fd
 
 
 
 
 
899870f
 
20ffed9
 
26471fd
 
899870f
26471fd
 
 
 
20ffed9
26471fd
20ffed9
26471fd
20ffed9
26471fd
20ffed9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26471fd
f35bde9
20ffed9
f35bde9
 
 
26471fd
 
 
 
 
 
 
 
 
20ffed9
26471fd
 
 
 
20ffed9
26471fd
 
 
 
20ffed9
26471fd
20ffed9
26471fd
 
 
 
20ffed9
26471fd
 
 
 
 
 
 
 
 
20ffed9
26471fd
 
 
20ffed9
26471fd
 
 
20ffed9
26471fd
 
20ffed9
26471fd
 
 
 
20ffed9
 
26471fd
 
 
 
20ffed9
26471fd
 
 
20ffed9
26471fd
 
 
20ffed9
 
26471fd
 
 
 
20ffed9
26471fd
 
 
 
f35bde9
26471fd
 
f35bde9
 
 
20ffed9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26471fd
 
20ffed9
 
 
26471fd
 
20ffed9
 
26471fd
 
20ffed9
 
26471fd
20ffed9
 
f35bde9
 
26471fd
20ffed9
f35bde9
20ffed9
 
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# app.py

import gradio as gr
from transformers import pipeline, set_seed
import random
import re # Для регулярных выражений (очистка текста)

# --- Загрузка моделей (как в прошлый раз, выберите нужные) ---
try:
    # generator = pipeline('text-generation', model='distilgpt2', max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256)
    generator = pipeline('text-generation', model='sberbank-ai/rugpt3small_based_on_gpt2', max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256)
    print("Генератор текста загружен.")
    GENERATOR_LOADED = True
except Exception as e:
    print(f"ОШИБКА: Не удалось загрузить генератор текста! {e}")
    generator = None
    GENERATOR_LOADED = False

try:
    # qa_pipeline = pipeline('question-answering', model='bert-large-uncased-whole-word-masking-finetuned-squad')
    qa_pipeline = pipeline('question-answering', model='timpal0l/mdeberta-v3-base-squad2') # Мультиязычная
    print("QA модель загружена.")
    QA_LOADED = True
except Exception as e:
    print(f"ОШИБКА: Не удалось загрузить QA модель! {e}")
    qa_pipeline = None
    QA_LOADED = False

# --- Встроенные знания и команды (РАСШИРЕНО для КОДИНГА) ---
knowledge_base = {
    # Мета-информация
    "кто ты": "Я Nova, модель Alpha 0.95, работающая на платформе Hugging Face Spaces. Я использую нейросетевые модели для генерации ответов и ответов на вопросы.",
    "что ты умеешь": "Я могу пытаться поддерживать диалог, отвечать на вопросы по контексту, генерировать текст и давать базовую информацию по некоторым темам, включая программирование. Мои знания ограничены, и я не выполняю код.",
    "как дела": "Как у программы, у меня все по плану! Готова обрабатывать ваши запросы.",
    "помощь": "Спросите меня о чем-нибудь, например, 'что такое переменная в программировании?' или 'какие есть циклы?'. Я постараюсь ответить. Также знаю команды: 'кто ты', 'что ты умеешь'.",

    # Основы Программирования
    "что такое программирование": "Программирование - это процесс написания инструкций (кода) для компьютера, чтобы он выполнял определенные задачи. Это как составление очень точного рецепта для машины.",
    "зачем нужно программирование": "Программирование позволяет создавать программы, веб-сайты, игры, автоматизировать задачи, анализировать данные и многое другое. Оно лежит в основе почти всех современных технологий.",
    "что такое алгоритм": "Алгоритм - это пошаговая инструкция или набор правил для решения определенной задачи. Например, рецепт приготовления блюда - это алгоритм.",
    "основные концепции программирования": "Ключевые идеи включают: переменные (хранение данных), типы данных (числа, строки), условные операторы (if/else - если/иначе), циклы (for, while - для повторения действий), функции (для организации кода).",
    "что такое переменная": "Переменная в программировании - это как именованный контейнер или ячейка памяти, где можно хранить данные (число, текст, и т.д.), чтобы использовать их позже в программе. Например, `age = 30`.",
    "что такое типы данных": "Типы данных определяют, какого рода информацию может хранить переменная и какие операции с ней можно выполнять. Распространенные типы: целые числа (integer), числа с плавающей точкой (float), строки (string - текст), булевы (boolean - истина/ложь).",
    "что такое строка": "Строка (string) - это последовательность символов, обычно используемая для представления текста. В большинстве языков строки заключаются в кавычки (одинарные или двойные). Например, \"Привет, мир!\".",
    "условный оператор if": "Оператор `if` (если) позволяет выполнить блок кода только в том случае, если определенное условие истинно. Часто используется вместе с `else` (иначе) для выполнения другого блока кода, если условие ложно.",
    "что такое цикл": "Цикл - это конструкция, которая позволяет повторять выполнение блока кода несколько раз. Основные виды: `for` (для), который обычно используется для перебора элементов (например, в списке) или выполнения заданное число раз, и `while` (пока), который выполняется, пока истинно определенное условие.",
    "цикл for": "Цикл `for` удобен, когда вы знаете, сколько раз нужно повторить действие, или когда нужно пройти по всем элементам коллекции (списка, строки).",
    "цикл while": "Цикл `while` повторяет блок кода до тех пор, пока заданное условие остается истинным. Важно убедиться, что условие когда-нибудь станет ложным, иначе цикл будет бесконечным.",
    "что такое функция": "Функция - это именованный блок кода, который выполняет определенную задачу. Функции помогают разбивать сложную программу на мелкие, управляемые части, избегать повторения кода и делать его более читаемым.",
    "язык программирования": "Язык программирования - это формальный язык, предназначенный для записи компьютерных программ. Популярные языки: Python (хорош для новичков, науки о данных, веб-бэкенда), JavaScript (для веб-фронтенда и бэкенда), Java (для энтерпрайза, Android), C++ (для игр, системного программирования), C# (для Windows, игр на Unity).",
    "python": "Python - популярный, высокоуровневый язык программирования с простым синтаксисом, подходящий для широкого круга задач: веб-разработка, наука о данных, машинное обучение, автоматизация.",
    "javascript": "JavaScript (JS) - основной язык для создания интерактивных веб-страниц (фронтенд). Также используется на бэкенде (Node.js) и для мобильных приложений.",
    "html": "HTML (HyperText Markup Language) - это не язык программирования, а язык разметки. Он используется для определения структуры и содержимого веб-страницы (заголовки, параграфы, картинки, ссылки).",
    "css": "CSS (Cascading Style Sheets) - язык стилей, используемый для описания внешнего вида документа, написанного на языке разметки (обычно HTML). Определяет цвета, шрифты, отступы, расположение элементов.",
    "что такое api": "API (Application Programming Interface) - это набор правил и протоколов, который позволяет разным программам 'общаться' друг с другом. Это как меню в ресторане: вы выбираете блюдо (функцию API), и кухня (другая программа) его готовит и отдает вам.",
    "что такое git": "Git - это распределенная система контроля версий. Она помогает разработчикам отслеживать изменения в коде, возвращаться к предыдущим версиям, работать над проектом совместно и не терять изменения.",
    "где учиться программировать": "Существует множество ресурсов: интерактивные онлайн-курсы (Codecademy, Coursera, Stepik, Яндекс.Практикум), документация языков, книги, видеоуроки на YouTube, форумы (Stack Overflow), сообщества разработчиков."

    # Добавьте сюда больше вопросов и ответов по кодингу!
}

# --- Функция обработки запроса (логика остается той же) ---

def respond(message, chat_history):
    print(f"Получено сообщение: {message}")
    user_message_lower = message.lower().strip().replace("?","").replace(".","").replace("!","") # Очищенный ввод для команд

    # 1. Проверка на встроенные команды/знания
    if user_message_lower in knowledge_base:
        bot_response = knowledge_base[user_message_lower]
        print(f"Ответ из базы знаний: {bot_response}")
        chat_history.append((message, bot_response))
        return "", chat_history

    # 2. Попытка ответа на вопрос с помощью QA модели (упрощенная логика)
    if "?" in message and QA_LOADED and qa_pipeline:
        context = ""
        if chat_history:
            context_parts = []
            for user_msg, bot_msg in chat_history[-2:]: # Последние 2 обмена
                 context_parts.append(f"Пользователь: {user_msg}")
                 context_parts.append(f"Бот: {bot_msg}")
            context = "\n".join(context_parts)

        if len(context) > 50: # Нужен минимальный контекст
             print("Попытка ответа на вопрос через QA модель...")
             print(f"Контекст: {context[:200]}...")
             print(f"Вопрос: {message}")
             try:
                 qa_result = qa_pipeline(question=message, context=context)
                 print(f"Результат QA: {qa_result}")
                 if qa_result and qa_result['score'] > 0.15: # Немного повысим порог
                     bot_response = qa_result['answer']
                     chat_history.append((message, bot_response))
                     print(f"Ответ от QA модели: {bot_response}")
                     return "", chat_history
                 else:
                      print("QA модель не уверена в ответе.")
             except Exception as e:
                  print(f"Ошибка при использовании QA модели: {e}")

    # 3. Генерация ответа с помощью основной модели
    if GENERATOR_LOADED and generator:
        print("Генерация ответа с помощью основной модели...")
        prompt_history = []
        for user_msg, bot_msg in chat_history[-3:]: # Последние 3 обмена
            prompt_history.append(f"Пользователь: {user_msg}")
            prompt_history.append(f"Бот: {bot_msg}")
        prompt_history.append(f"Пользователь: {message}")
        prompt_history.append("Бот:")

        full_prompt = "\n".join(prompt_history)
        print(f"Промпт для генератора: {full_prompt[-500:]}")

        try:
            generated_output = generator(full_prompt)[0]['generated_text']
            bot_response = generated_output

            # Очистка
            if generated_output.startswith(full_prompt):
                 bot_response = generated_output[len(full_prompt):].strip()
            else:
                 last_user_line = f"Пользователь: {message}\nБот:"
                 if bot_response.strip().startswith(last_user_line.strip()):
                     bot_response = bot_response.strip()[len(last_user_line.strip()):].strip()
                 elif len(bot_response) > len(message) and message.lower() in bot_response[:len(message)*2].lower():
                      parts = bot_response.split('\n')
                      if len(parts)>1: bot_response = '\n'.join(parts[1:]).strip()

            bot_response = re.sub(r'^\s*(пользователь|user|бот|bot)\s*[:\-]?\s*', '', bot_response, flags=re.IGNORECASE).strip()

            if not bot_response or len(bot_response) < 3:
                bot_response = knowledge_base.get("не найдено", "Хм, не знаю, что на это ответить...") # Используем "не найдено" из базы
                print("Сгенерирован слишком короткий ответ, используется заглушка.")

        except Exception as e:
            print(f"Ошибка при генерации: {e}")
            bot_response = knowledge_base.get("ошибка генерации", f"Упс, произошла ошибка при генерации: {e}") # Используем текст ошибки из базы

    else:
        bot_response = "К сожалению, мои основные модули сейчас недоступны."
        print("Ошибка: Генератор текста не загружен.")

    chat_history.append((message, bot_response))
    print(f"Финальный ответ: {bot_response}")
    return "", chat_history


# --- Создание интерфейса Gradio с УЛУЧШЕННЫМ CSS ---

# Определяем CSS стили
custom_css = """
/* Общий фон */
.gradio-container {
    background: linear-gradient(to bottom right, #e0f7fa, #f1f8e9); /* Приятный градиент */
    border-radius: 15px;
    padding: 25px;
}

/* Заголовок */
h1 {
    color: #004d40; /* Темно-бирюзовый */
    text-align: center;
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    margin-bottom: 15px;
}

/* Контейнер чата */
#chatbot {
    background-color: #ffffff; /* Белый фон для сообщений */
    border-radius: 10px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1); /* Легкая тень */
    border: 1px solid #e0e0e0;
}

/* Сообщения пользователя */
#chatbot .user {
    background-color: #e3f2fd; /* Голубоватый фон */
    color: #0d47a1; /* Темно-синий текст */
    border-radius: 15px 15px 0 15px; /* Скругление углов */
    padding: 10px 15px;
    margin: 5px;
    align-self: flex-end; /* Выравнивание справа */
    max-width: 85%;
}

/* Сообщения бота */
#chatbot .bot {
    background-color: #f1f8e9; /* Светло-зеленоватый фон */
    color: #33691e; /* Темно-зеленый текст */
    border-radius: 15px 15px 15px 0; /* Скругление углов */
    padding: 10px 15px;
    margin: 5px;
    align-self: flex-start; /* Выравнивание слева */
     max-width: 85%;
}

/* Поле ввода текста */
textarea {
    border: 1px solid #b0bec5; /* Сероватая рамка */
    border-radius: 8px !important; /* !important нужен для переопределения стандартных стилей gradio */
    padding: 12px !important;
    background-color: #ffffff;
    transition: border-color 0.3s ease;
}
textarea:focus {
    border-color: #0277bd !important; /* Синяя рамка при фокусе */
    box-shadow: 0 0 5px rgba(2, 119, 189, 0.3);
}

/* Кнопки */
button {
    border-radius: 8px !important;
    transition: background-color 0.3s ease, box-shadow 0.3s ease !important;
    font-weight: 500 !important;
}
button.primary { /* Основная кнопка Отправить */
    background: linear-gradient(to right, #007991, #78ffd6) !important; /* Бирюзовый градиент */
    color: white !important;
    border: none !important;
}
button.primary:hover {
     box-shadow: 0 4px 8px rgba(0, 121, 145, 0.3);
     background: linear-gradient(to right, #006073, #5fddb8) !important; /* Чуть темнее при наведении */
}
button.secondary { /* Кнопка Очистить */
   background-color: #cfd8dc !important; /* Светло-серый */
   color: #37474f !important;
   border: 1px solid #b0bec5 !important;
}
button.secondary:hover {
    background-color: #b0bec5 !important; /* Темнее при наведении */
}
"""

with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo: # Применяем CSS и мягкую тему
    gr.Markdown(
        """
        # 🤖 Nova Alpha 0.95 🎨
        Улучшенный интерфейс! Задавайте вопросы или команды.
        """, elem_id="title-markdown" # Можно задать ID для CSS
    )

    chatbot = gr.Chatbot(label="Диалог", height=500, elem_id="chatbot")
    with gr.Row():
        msg = gr.Textbox(
            label="Ваше сообщение",
            placeholder="Спросите о Python или скажите 'привет'...",
            scale=4
        )
        submit_btn = gr.Button("Отправить", variant="primary", scale=1)
        clear_btn = gr.Button("Очистить", variant="secondary", scale=1) # Добавили класс для CSS

    msg.submit(respond, [msg, chatbot], [msg, chatbot])
    submit_btn.click(respond, [msg, chatbot], [msg, chatbot])
    clear_btn.click(lambda: (None, []), None, [msg, chatbot], queue=False)

demo.queue()
demo.launch(debug=True)