HeavensHackDev commited on
Commit
e54a9ba
·
verified ·
1 Parent(s): a3dfced

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +154 -284
app.py CHANGED
@@ -1,218 +1,81 @@
1
- # --- Создание интерфейса Gradio с УЛУЧШЕННЫМ и БОЛЕЕ КОНТРАСТНЫМ CSS ---
2
 
3
- # Определяем CSS стили
4
- custom_css = """
5
- /* Общий фон */
6
- .gradio-container {
7
- /* background: linear-gradient(to bottom right, #e0f7fa, #f1f8e9); */ /* Убрали градиент, может мешать */
8
- background-color: #f4f7f9; /* Спокойный светло-серый фон */
9
- border-radius: 15px;
10
- padding: 25px;
11
- color: #333; /* Основной цвет текста */
12
- }
13
-
14
- /* Заголовок */
15
- h1 {
16
- color: #1a237e; /* Глубокий индиго */
17
- text-align: center;
18
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Читаемый шрифт */
19
- margin-bottom: 15px;
20
- font-weight: 600;
21
- }
22
- #title-markdown p { /* Стили для параграфа под заголовком */
23
- text-align: center;
24
- color: #546e7a; /* Серо-синий */
25
- margin-top: -10px;
26
- margin-bottom: 25px;
27
- }
28
-
29
-
30
- /* --- СТИЛИ ЧАТА --- */
31
-
32
- /* Контейнер чата */
33
- #chatbot {
34
- background-color: #eceff1; /* Очень светлый серо-голубой фон чата */
35
- border-radius: 12px; /* Немного другие скругления */
36
- border: 1px solid #cfd8dc; /* Граница контейнера */
37
- padding: 10px; /* Внутренние отступы */
38
- box-shadow: inset 0 1px 3px rgba(0,0,0,0.05); /* Легкая внутренняя тень */
39
- }
40
-
41
- /* Сообщения пользователя */
42
- #chatbot .user-message .message-bubble-border {
43
- border: none !important; /* Убираем стандартную рамку gradio */
44
- }
45
- #chatbot .user-message .message-bubble {
46
- background: #007bff !important; /* Яркий синий фон */
47
- color: white !important; /* Белый текст */
48
- border-radius: 18px 18px 5px 18px !important; /* Асимметричное скругление */
49
- padding: 12px 18px !important;
50
- margin: 8px 5px 8px 0 !important; /* Отступы */
51
- align-self: flex-end !important;
52
- max-width: 80% !important;
53
- box-shadow: 0 2px 4px rgba(0, 123, 255, 0.2); /* Тень под цвет */
54
- word-wrap: break-word;
55
- text-align: left;
56
- }
57
-
58
-
59
- /* Сообщения бота */
60
- #chatbot .bot-message .message-bubble-border {
61
- border: none !important; /* Убираем стандартную рамку gradio */
62
- }
63
- #chatbot .bot-message .message-bubble {
64
- background: #ffffff !important; /* Чисто белый фон для контраста */
65
- color: #212529 !important; /* Темный текст (почти черный) */
66
- border: 1px solid #dee2e6 !important; /* Легкая серая рамка */
67
- border-radius: 18px 18px 18px 5px !important; /* Асимметричное скругление */
68
- padding: 12px 18px !important;
69
- margin: 8px 0 8px 5px !important; /* Отступы */
70
- align-self: flex-start !important;
71
- max-width: 80% !important;
72
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); /* Мягкая тень */
73
- word-wrap: break-word;
74
- text-align: left;
75
- }
76
-
77
- /* Блоки кода внутри сообщений бота */
78
- #chatbot .bot-message .message-bubble pre {
79
- background-color: #f8f9fa; /* Фон для блока кода */
80
- border: 1px solid #e9ecef; /* Рамка блока кода */
81
- border-radius: 6px; /* Скругление */
82
- padding: 10px; /* Отступы внутри */
83
- margin: 8px 0 5px 0; /* Отступы снаружи */
84
- overflow-x: auto; /* Горизонтальная прокрутка если код длинный */
85
- word-wrap: normal; /* Предотвратить перенос слов в коде */
86
- }
87
- #chatbot .bot-message .message-bubble pre code {
88
- background-color: transparent !important; /* Убираем фон у самого тега code */
89
- color: #2d3748; /* Цвет текста кода */
90
- font-family: 'Consolas', 'Monaco', 'Courier New', monospace; /* Моноширинный шрифт */
91
- font-size: 0.9em; /* Размер шрифта кода */
92
- padding: 0; /* Убираем внутренние отступы тега code */
93
- white-space: pre; /* Сохраняем пробелы и переносы */
94
- }
95
-
96
- /* --- ОСТАЛЬНЫЕ ЭЛЕМЕНТЫ --- */
97
-
98
- /* Поле ввода текста */
99
- textarea {
100
- border: 1px solid #ced4da !important;
101
- border-radius: 10px !important;
102
- padding: 12px 15px !important;
103
- background-color: #ffffff;
104
- transition: border-color 0.3s ease, box-shadow 0.3s ease;
105
- font-size: 1rem; /* Слегка увеличим шрифт ввода */
106
- }
107
- textarea:focus {
108
- border-color: #80bdff !important;
109
- box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
110
- outline: none; /* Убираем стандартный outline */
111
- }
112
-
113
- /* Кнопки */
114
- button {
115
- border-radius: 10px !important;
116
- padding: 10px 15px !important; /* Паддинги для кнопок */
117
- transition: background-color 0.2s ease, transform 0.1s ease !important;
118
- font-weight: 500 !important;
119
- border: none !important; /* Убираем рамки по умолчанию */
120
- }
121
- button:active {
122
- transform: translateY(1px); /* Эффект нажатия */
123
- }
124
- button.primary { /* Кнопка "Отправить" */
125
- background-color: #007bff !important; /* Синий цвет */
126
- color: white !important;
127
- }
128
- button.primary:hover {
129
- background-color: #0056b3 !important; /* Темнее при наведении */
130
- box-shadow: 0 2px 5px rgba(0, 123, 255, 0.3);
131
- }
132
- button.secondary { /* Кнопка "Очистить" */
133
- background-color: #6c757d !important; /* Серый цвет */
134
- color: white !important;
135
- }
136
- button.secondary:hover {
137
- background-color: #5a6268 !important; /* Темнее при наведении */
138
- box-shadow: 0 2px 5px rgba(108, 117, 125, 0.3);
139
- }
140
- """
141
-
142
- # --- Python код остается тем же, что и в предыдущем ответе ---
143
- # (начиная с import gradio as gr...)
144
- # ... весь остальной Python код без изменений ...
145
  import gradio as gr
146
- from transformers import pipeline, set_seed
147
  import random
148
- import re # Для регулярных выражений (очистка текста)
 
 
 
 
 
 
 
 
 
 
 
 
149
 
150
- # --- Загрузка моделей (выберите нужные) ---
151
- # Модель-генератор (например, русская или английская)
152
- GENERATOR_MODEL_NAME = 'sberbank-ai/rugpt3small_based_on_gpt2' # Или 'distilgpt2'
153
  try:
154
- generator = pipeline('text-generation', model=GENERATOR_MODEL_NAME, max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256)
155
- print(f"Генератор текста ({GENERATOR_MODEL_NAME}) загружен.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  GENERATOR_LOADED = True
157
  except Exception as e:
158
- print(f"ОШИБКА: Не удалось загрузить генератор текста! {e}")
159
  generator = None
 
 
160
  GENERATOR_LOADED = False
161
 
162
- # QA Модель (например, мультиязычная)
163
  QA_MODEL_NAME = 'timpal0l/mdeberta-v3-base-squad2'
164
  try:
165
  qa_pipeline = pipeline('question-answering', model=QA_MODEL_NAME)
166
  print(f"QA модель ({QA_MODEL_NAME}) загружена.")
167
  QA_LOADED = True
 
 
168
  except Exception as e:
169
  print(f"ОШИБКА: Не удалось загрузить QA модель! {e}")
170
  qa_pipeline = None
171
  QA_LOADED = False
172
 
173
- # --- Встроенные знания и команды (Дополнены ответы про кодинг) ---
 
174
  knowledge_base = {
175
- # Мета-информация
176
- "кто ты": "Я Nova, модель Alpha 0.96, работающая на платформе Hugging Face Spaces. Я стараюсь отвечать на вопросы и поддерживать диалог, используя предопределенные ответы и нейросетевые модели.",
177
- "что ты умеешь": "Я могу отвечать на некоторые вопросы по программированию и другим темам из моей базы знаний, пытаться отвечать на вопросы по контексту диалога (если есть QA-модель) и поддерживать беседу. Я НЕ МОГУ выполнять команды по написанию произвольного кода, но могу дать общие объяснения или простые примеры.", # Уточнено про код
178
- "как дела": "Как у программы, у меня все по плану! Готова обрабатывать ваши запросы.",
179
- "помощь": "Спросите меня о чем-нибудь, например, 'что такое переменная в программировании?' или 'расскажи про python'. Я постараюсь ответить. Также знаю команды: 'кто ты', 'что ты умеешь'.",
180
-
181
- # --- НОВЫЕ ОТВЕТЫ на запросы КОДА ---
182
- "напиши код": "Я не могу писать произвольный код по запросу. Моя функция - давать информацию и объяснения. Возможно, вы имели в виду пример кода для какой-то задачи? Попробуйте спросить конкретнее, например: 'пример цикла for на python'.",
183
- "сгенерируй код": "Генерация сложного кода пока не входит в мои возможности. Я могу объяснить концепции или показать базовые синтаксические конструкции. Какой пример вас интересует?",
184
- "напиши скрипт": "К сожалению, я не пишу готовые скрипты. Опишите задачу, и я постараюсь объяснить, какие шаги или концепции программирования могут понадобиться для ее решения.",
185
- "код на питоне": "Пайтон - отличный язык! Уточните, какой именно аспект или пример кода на Python вас интересует? Например, 'как объявить переменную на python?' или 'пример функции на python'.",
186
- "пример кода": "Конечно! Какой пример кода вы хотели бы увидеть? Например, 'пример условного оператора if' или 'пример простого класса на python'.",
187
- "hello world на python": "Самый классический пример! Вот 'Hello, World!' на Python:\n```python\nprint(\"Hello, World!\")\n```",
188
- "пример цикла for на python": "Вот пример цикла `for`, который печатает числа от 0 до 4:\n```python\nfor i in range(5):\n print(i)\n```",
189
- "пример функции на python": "Вот простая функция на Python, которая складывает два числа:\n```python\ndef add_numbers(a, b):\n return a + b\n\nresult = add_numbers(5, 3)\nprint(result) # Выведет 8\n```",
190
- "как объявить переменную на python": "Переменная в Python объявляется простым присваиванием значения. Например:\n```python\nmy_variable = 10\nuser_name = \"Alice\"\nis_active = True\n```",
191
-
192
- # Основы Программирования (остальное из 0.95)
193
- "что такое программирование": "Программирование - это процесс написания инструкций (кода) для компьютера, чтобы он выполнял определенные задачи. Это как составление очень точного рецепта для машины.",
194
- "зачем нужно программирование": "Программирование позволяет создавать программы, веб-сайты, игры, автоматизировать задачи, анализировать данные и многое другое. Оно лежит в основе почти всех современных технологий.",
195
- "что такое алгоритм": "Алгоритм - это пошаговая инструкция или набор правил для решения определенной задачи. Например, рецепт приготовления блюда - это алгоритм.",
196
- "основные концепции программирования": "Ключевые идеи включают: переменные (хранение данных), типы данных (числа, строки), условные операторы (if/else - если/иначе), циклы (for, while - для повторения действий), функции (для организации кода).",
197
- "что такое переменная": "Переменная в программировании - это как именованный контейнер или ячейка памяти, где можно хранить данные (число, текст, и т.д.), чтобы использовать их позже в программе. Например, `age = 30`.",
198
- "что такое типы данных": "Типы данных определяют, какого рода информацию может хранить переменная и какие операции с ней можно выполнять. Распространенные типы: целые числа (integer), числа с плавающей точкой (float), строки (string - текст), булевы (boolean - истина/ложь).",
199
- "что такое строка": "Строка (string) - это последовательность символов, обычно используемая для представления текста. В большинстве языков строки заключаются в кавычки (одинарные или двойные). Например, \"Привет, мир!\".",
200
- "условный оператор if": "Оператор `if` (если) позволяет выполнить блок кода только в том случае, если определенное условие истинно. Часто используется вместе с `else` (иначе) для выполнения другого блока кода, если условие ложно.",
201
- "что такое цикл": "Цикл - это конструкция, которая позволяет повторять выполнение блока кода несколько раз. Основные виды: `for` (для), который обычно используется для перебора элементов (например, в списке) или выполнения заданное число раз, и `while` (пока), который выполняется, пока истинно определенное условие.",
202
- "цикл for": "Цикл `for` удобен, когда вы знаете, сколько раз нужно повторить действие, или когда нужно пройти по всем элементам коллекции (списка, строки).",
203
- "цикл while": "Цикл `while` повторяет блок кода до тех пор, пока заданное условие остается истинным. Важно убедиться, что условие когда-нибудь станет ложным, иначе цикл будет бесконечным.",
204
- "что такое функция": "Функция - это именованный блок кода, который выполняет определенную задачу. Функции помогают разбивать сложную программу на мелкие, управляемые части, избегать повторения кода и делать его более читаемым.",
205
- "язык программирования": "Язык программирования - это формальный язык, предназначенный для записи компьютерных программ. Популярные языки: Python (хорош для новичков, науки о данных, веб-бэкенда), JavaScript (для веб-фронтенда и бэкенда), Java (для энтерпрайза, Android), C++ (для игр, системного программирования), C# (для Windows, игр на Unity).",
206
- "python": "Python - популярный, высокоуровневый язык программирования с ��ростым синтаксисом, подходящий для широкого круга задач: веб-разработка, наука о данных, машинное обучение, автоматизация.",
207
- "javascript": "JavaScript (JS) - основной язык для создания интерактивных веб-страниц (фронтенд). Также используется на бэкенде (Node.js) и для мобильных приложений.",
208
- "html": "HTML (HyperText Markup Language) - это не язык программирования, а язык разметки. Он используется для определения структуры и содержимого веб-страницы (заголовки, параграфы, картинки, ссылки).",
209
- "css": "CSS (Cascading Style Sheets) - язык стилей, используемый для описания внешнего вида документа, написанного на языке разметки (обычно HTML). Определяет цвета, шрифты, отступы, расположение элементов.",
210
- "что такое api": "API (Application Programming Interface) - это набор правил и протоколов, который позволяет разным программам 'общаться' друг с другом. Это как меню в ресторане: вы выбираете блюдо (функцию API), и кухня (другая программа) его готовит и отдает вам.",
211
- "что такое git": "Git - это распределенная система контроля версий. Она помогает разработчикам отслеживать изменения в коде, возвращаться к предыдущим версиям, работать над проектом совместно и не терять изменения.",
212
- "где учиться программировать": "Существует множество ресурсов: интерактивные онлайн-курсы (Codecademy, Coursera, Stepik, Яндекс.Практикум), документация языков, книги, видеоуроки на YouTube, форумы (Stack Overflow), сообщества разработчиков."
213
  }
214
 
215
- # --- Утилиты ---
216
  def clean_text(text):
217
  if not isinstance(text, str): return ""
218
  text = text.lower().strip()
@@ -221,134 +84,141 @@ def clean_text(text):
221
  return text
222
 
223
  def clean_generated_output(generated_text, prompt):
 
224
  if not generated_text or not isinstance(generated_text, str): return ""
225
  if not prompt or not isinstance(prompt, str): prompt = ""
226
  cleaned = generated_text
227
  prompt_clean = prompt.strip()
228
  if prompt_clean and cleaned.startswith(prompt_clean):
229
  cleaned = cleaned[len(prompt_clean):].strip()
230
- cleaned = re.sub(r'^\s*(ответ|бот|пользователь|user|bot)\s*[:\-]?\s*', '', cleaned, flags=re.IGNORECASE | re.MULTILINE).strip()
231
- last_lines = prompt_clean.split('\n')
232
- if len(last_lines) >= 2:
233
- last_user_line = last_lines[-2].strip()
234
- if last_user_line.lower().startswith(("пользователь:", "user:")):
235
- user_message_only = last_user_line.split(":", 1)[1].strip()
236
- if user_message_only and cleaned.lower().startswith(user_message_only.lower()):
237
- end_of_echo_pos = len(user_message_only)
238
- following_text = cleaned[end_of_echo_pos:].lstrip()
239
- if re.match(r'^(бот|bot)\s*[:\-]?\s*', following_text, flags=re.IGNORECASE):
240
- following_text = re.sub(r'^(бот|bot)\s*[:\-]?\s*', '', following_text, flags=re.IGNORECASE).strip()
241
- cleaned = following_text
242
- cleaned = re.sub(r'^\s*(ответ|бот|пользователь|user|bot)\s*[:\-]?\s*', '', cleaned, flags=re.IGNORECASE | re.MULTILINE).strip()
243
  return cleaned
244
 
245
- # --- Основная Функция Обработки (Alpha 0.96 Логика) ---
 
246
  def respond(message, chat_history):
247
  print("-" * 30)
248
  print(f"ВХОД: '{message}'")
249
  user_message_clean = clean_text(message)
250
- bot_response = "" # Инициализация переменной
251
 
252
- # 1. Точное совпадение в knowledge_base
253
  if user_message_clean in knowledge_base:
254
  bot_response = knowledge_base[user_message_clean]
255
- print(f"Ответ [Точный]: {bot_response[:100]}...") # Логгируем начало ответа
256
-
257
- # 2. Запрос кода
258
- if not bot_response: # Только если не нашли точный ответ
259
- code_request_patterns = ["напиши код", "напиши скрипт", "сгенерируй код", "создай код", "write code", "generate code", "create script", "code example for", "пример кода для"]
260
- is_code_request = any(user_message_clean.startswith(pattern) for pattern in code_request_patterns)
261
- if is_code_request:
262
- bot_response = knowledge_base.get("напиши код", "Я не могу писать произвольный код, но могу дать объяснение или пример. Уточните ваш запрос.")
263
- print(f"Ответ [Запрос кода]: {bot_response}")
264
-
265
- # 3. QA модель
266
- if not bot_response and "?" in message and QA_LOADED and qa_pipeline:
267
- context = ""
268
- if chat_history:
269
- context_parts = []
270
- for user_msg, bot_msg in chat_history[-2:]:
271
- context_parts.append(f"Пользователь: {user_msg}")
272
- if bot_msg: context_parts.append(f"Бот: {bot_msg}")
273
- context = "\n".join(context_parts)
274
- if len(context) > 50:
275
- print("Попытка ответа через QA...")
276
- try:
277
- qa_result = qa_pipeline(question=message, context=context)
278
- print(f"Результат QA: score={qa_result.get('score', 0):.2f}, answer='{qa_result.get('answer', '')[:50]}...'")
279
- if qa_result and qa_result['score'] > 0.25: # Уверенность > 25%
280
- answer = qa_result['answer'].strip()
281
- if answer:
282
- bot_response = answer
283
- print(f"Ответ [QA]: {bot_response[:100]}...")
284
- else: print("QA модель дала пустой ответ.")
285
- else: print("QA модель не уверена.")
286
- except Exception as e: print(f"Ошибка при использовании QA модели: {e}")
287
-
288
- # 4. Генерация
289
  if not bot_response and GENERATOR_LOADED and generator:
290
- print("Попытка генерации ответа...")
291
- prompt_history = []
292
- for user_msg, bot_msg in chat_history[-3:]:
293
- prompt_history.append(f"Пользователь: {user_msg}")
294
- if bot_msg: prompt_history.append(f"Бот: {bot_msg}")
295
- prompt_history.append(f"Пользователь: {message}")
296
- prompt_history.append("Бот:")
297
- full_prompt = "\n".join(prompt_history)
298
- print(f"Промпт для генератора: ...{full_prompt[-500:]}")
 
 
 
 
 
 
299
  try:
300
- generated_output = generator(full_prompt)[0]['generated_text']
301
- print(f"Сырой ответ генератора: {generated_output}")
302
- cleaned_generated = clean_generated_output(generated_output, full_prompt)
303
- print(f"Очищенный ответ генератора: {cleaned_generated}")
304
- if cleaned_generated and len(cleaned_generated) > 5: # Минимальная длина для осмысленного ответа
305
- bot_response = cleaned_generated
306
- print(f"Ответ [Генерация]: {bot_response[:100]}...")
307
- else:
308
- print("Генерация не удалась или слишком короткая.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  except Exception as e:
310
- print(f"Ошибка при генерации: {e}")
311
- bot_response = knowledge_base.get("ошибка генерации", "Произошла ошибка при попытке сгенерировать ответ.")
312
 
313
- # 5. Ответ по умолчанию (если ничего не сработало)
314
  if not bot_response:
315
- bot_response = knowledge_base.get("не найдено", сожалению, я пока не знаю, как на это ответить.")
316
- print("Ответ [Не найдено/Заглушка]")
 
 
 
 
317
 
318
 
319
  # Добавляем в историю и возвращаем
320
  chat_history.append((message, bot_response))
321
- return "", chat_history # Очищаем поле ввода
322
 
323
 
324
- # --- Gradio Интерфейс ---
325
- with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue=gr.themes.colors.blue, secondary_hue=gr.themes.colors.slate)) as demo: # Тема с цветами
326
- gr.Markdown("# 🤖 Nova Alpha 0.96 <br> Улучшенный интерфейс и знания о коде", elem_id="title-markdown")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
 
328
  chatbot = gr.Chatbot(
329
- label="Диалог",
330
- height=550,
331
- elem_id="chatbot",
332
- bubble_full_width=False,
333
- avatar_images=(None, "https://img.icons8.com/plasticine/100/bot.png") # Аватарка для бота
334
  )
335
-
336
  with gr.Row():
337
  msg = gr.Textbox(
338
- label="Ваше сообщение",
339
- placeholder="Спросите о Python или скажите 'привет'...",
340
- scale=4,
341
- show_label=False,
342
- container=False # Убираем контейнер текстбокса для лучшего выравнивания
343
  )
344
- submit_btn = gr.Button("➤ Отправить", variant="primary", scale=1, min_width=120) # Иконка и мин. ширина
345
- clear_btn = gr.Button("🗑️ Очистить", variant="secondary", scale=1, min_width=120) # Иконка и мин. ширина
346
 
347
- # Обработчики
348
  msg.submit(respond, [msg, chatbot], [msg, chatbot])
349
  submit_btn.click(respond, [msg, chatbot], [msg, chatbot])
350
  clear_btn.click(lambda: (None, []), None, [msg, chatbot], queue=False)
351
 
352
  # Запуск
353
  demo.queue()
354
- demo.launch(debug=True)
 
1
+ # app.py
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import gradio as gr
4
+ from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM # Используем Auto классы для большей гибкости
5
  import random
6
+ import re
7
+ import torch # Убедимся, что torch импортирован
8
+
9
+ # --- Выбор Модели ---
10
+ # Заменяем на самую маленькую DeepSeek Coder Instruct
11
+ # !!! ПРЕДУПРЕЖДЕНИЕ: МОЖЕТ НЕ ЗАПУСТИТЬСЯ ИЛИ БЫТЬ ОЧЕНЬ МЕДЛЕННОЙ НА FREE CPU !!!
12
+ CODE_MODEL_NAME = "deepseek-ai/deepseek-coder-1.3b-instruct"
13
+
14
+ # --- Загрузка моделей ---
15
+ GENERATOR_LOADED = False
16
+ QA_LOADED = False
17
+ generator = None
18
+ qa_pipeline = None
19
 
20
+ # 1. Модель для кодирования/генерации
 
 
21
  try:
22
+ # Для моделей кода часто лучше использовать AutoModelForCausalLM и AutoTokenizer напрямую
23
+ # Вместо pipeline('text-generation') это дает больше контроля
24
+ print(f"Загрузка токенизатора: {CODE_MODEL_NAME}")
25
+ tokenizer = AutoTokenizer.from_pretrained(CODE_MODEL_NAME, trust_remote_code=True)
26
+ print(f"Загрузка модели: {CODE_MODEL_NAME}")
27
+ # Загружаем с torch_dtype=torch.float16 для экономии памяти, если возможно
28
+ try:
29
+ generator_model = AutoModelForCausalLM.from_pretrained(
30
+ CODE_MODEL_NAME,
31
+ trust_remote_code=True,
32
+ torch_dtype=torch.float16 # Пытаемся загрузить в половинной точности
33
+ )
34
+ except Exception as e_half: # Если float16 не поддерживается/вызывает ошибку, пробуем float32
35
+ print(f"Не удалось загрузить в float16 ({e_half}), пробую float32...")
36
+ generator_model = AutoModelForCausalLM.from_pretrained(
37
+ CODE_MODEL_NAME,
38
+ trust_remote_code=True
39
+ )
40
+
41
+ # Создаем pipeline вручную
42
+ generator = pipeline('text-generation', model=generator_model, tokenizer=tokenizer, device=-1) # device=-1 значит CPU
43
+
44
+ print(f"Генератор кода/текста ({CODE_MODEL_NAME}) загружен.")
45
  GENERATOR_LOADED = True
46
  except Exception as e:
47
+ print(f"ОШИБКА: Не удалось загрузить модель {CODE_MODEL_NAME}! {e}")
48
  generator = None
49
+ generator_model = None
50
+ tokenizer = None
51
  GENERATOR_LOADED = False
52
 
53
+ # 2. QA Модель (оставляем как есть или можно убрать, если не нужна)
54
  QA_MODEL_NAME = 'timpal0l/mdeberta-v3-base-squad2'
55
  try:
56
  qa_pipeline = pipeline('question-answering', model=QA_MODEL_NAME)
57
  print(f"QA модель ({QA_MODEL_NAME}) загружена.")
58
  QA_LOADED = True
59
+ # !!! ВНИМАНИЕ: Две модели могут потребовать слишком много RAM !!!
60
+ # !!! Возможно, стоит закомментировать загрузку QA, если возникают проблемы с памятью !!!
61
  except Exception as e:
62
  print(f"ОШИБКА: Не удалось загрузить QA модель! {e}")
63
  qa_pipeline = None
64
  QA_LOADED = False
65
 
66
+
67
+ # --- Встроенные знания (можно сократить, т.к. модель сама умнее) ---
68
  knowledge_base = {
69
+ "кто ты": f"Я Nova (использую модель {CODE_MODEL_NAME}), работающая на Hugging Face Spaces. Я специализируюсь на помощи с кодом и ответами на вопросы по программированию.",
70
+ "что ты умеешь": "Я могу пытаться генерировать код, объяснять его, находить ошибки определенной степени), отвечать на вопросы по программированию и поддерживать диалог.",
71
+ "как дела": "Работаю над кодом! А если серьезно - функционирую нормально.",
72
+ "помощь": "Спросите меня о программировании, попросите написать фрагмент кода (например, 'напиши функцию на python для суммирования списка'), или просто пообщаемся.",
73
+ "python": "Python - отличный высокоуровневый язык, известный своей читаемостью. Хорошо подходит для веб-разработки, анализа данных, ИИ и автоматизации.",
74
+ "javascript": "JavaScript - основной язык веб-фронтенда, позволяет делать страницы интерактивными. С Node.js используется и на бэкенде.",
75
+ # Убрали много базовых вещей, т.к. модель должна знать их сама
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
 
78
+ # --- Утилиты (clean_text, clean_generated_output - как раньше) ---
79
  def clean_text(text):
80
  if not isinstance(text, str): return ""
81
  text = text.lower().strip()
 
84
  return text
85
 
86
  def clean_generated_output(generated_text, prompt):
87
+ # Простая очистка - убираем промпт если он есть в начале
88
  if not generated_text or not isinstance(generated_text, str): return ""
89
  if not prompt or not isinstance(prompt, str): prompt = ""
90
  cleaned = generated_text
91
  prompt_clean = prompt.strip()
92
  if prompt_clean and cleaned.startswith(prompt_clean):
93
  cleaned = cleaned[len(prompt_clean):].strip()
94
+
95
+ # Попробуем убрать стандартные фразы, которые модель может добавить
96
+ cleaned = re.sub(r'^\s*(ответ|бот|вот код|конечно|here is the code)\s*[:\-]?\s*', '', cleaned, flags=re.IGNORECASE).strip()
97
+
 
 
 
 
 
 
 
 
 
98
  return cleaned
99
 
100
+
101
+ # --- Основная Функция Обработки (Упрощенная, больше полагаемся на модель) ---
102
  def respond(message, chat_history):
103
  print("-" * 30)
104
  print(f"ВХОД: '{message}'")
105
  user_message_clean = clean_text(message)
106
+ bot_response = ""
107
 
108
+ # 1. Проверка на точное совпадение в knowledge_base (ОСТАВЛЯЕМ для мета-вопросов)
109
  if user_message_clean in knowledge_base:
110
  bot_response = knowledge_base[user_message_clean]
111
+ print(f"Ответ [Точный]: {bot_response[:100]}...")
112
+
113
+ # 2. Основная генерация (используем модель DeepSeek Coder)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  if not bot_response and GENERATOR_LOADED and generator:
115
+ print("Генерация ответа с помощью модели кода...")
116
+ # Формируем промпт в формате, который модель ожидае�� (часто нужен специальный формат для Instruct-моделей)
117
+ # Для DeepSeek Coder Instruct формат может быть таким:
118
+ prompt_list = []
119
+ prompt_list.append("### Instruction:")
120
+ # Добавим контекст из чата (если есть)
121
+ for user_msg, bot_msg in chat_history[-2:]: # Последние 2 обмена для контекста
122
+ prompt_list.append(f"User: {user_msg}")
123
+ if bot_msg: prompt_list.append(f"Assistant: {bot_msg}") # Используем Assistant
124
+ prompt_list.append(f"{message}") # Текущее сообщение как инструкция/вопрос
125
+ prompt_list.append("\n### Response:") # Приглашение для ответа
126
+
127
+ full_prompt = "\n".join(prompt_list)
128
+ print(f"Промпт для DeepSeek: ...{full_prompt[-600:]}") # Логируем конец
129
+
130
  try:
131
+ # Параметры генерации для кода
132
+ # `max_new_tokens` - ограничивает длину *сгенерированного* текста
133
+ # `temperature` - контроль случайности (ниже = более предсказуемо)
134
+ # `top_p`, `top_k` - другие методы семплирования
135
+ # `eos_token_id` - ID токена конца последовательности (может помочь модели остановиться)
136
+ generated_output = generator(
137
+ full_prompt,
138
+ max_new_tokens=250, # Ограничим генерацию
139
+ temperature=0.7,
140
+ top_k=50,
141
+ top_p=0.95,
142
+ # eos_token_id=tokenizer.eos_token_id if tokenizer else None, # Помогает модели остановиться
143
+ pad_token_id=tokenizer.eos_token_id if tokenizer else 50256, # Часто нужно указать
144
+ num_return_sequences=1,
145
+ do_sample=True
146
+ )[0]['generated_text']
147
+
148
+ print(f"Сырой ответ DeepSeek: {generated_output}")
149
+
150
+ # Очистка - убираем весь промпт
151
+ bot_response = clean_generated_output(generated_output, full_prompt)
152
+ print(f"Очищенный ответ DeepSeek: {bot_response}")
153
+
154
+ # Дополнительно убираем инструкции, которые модель могла повторить
155
+ bot_response = bot_response.replace("### Instruction:", "").replace("### Response:", "").strip()
156
+
157
+ if not bot_response or len(bot_response) < 5:
158
+ bot_response = knowledge_base.get("не найдено", "Извините, не смог сгенерировать ответ.")
159
+ print("Генерация DeepSeek не удалась или слишком короткая.")
160
+
161
  except Exception as e:
162
+ print(f"Ошибка при генерации DeepSeek: {e}")
163
+ bot_response = knowledge_base.get("ошибка генерации", f"Произошла ошибка при генерации: {e}")
164
 
165
+ # 3. Ответ по умолчанию
166
  if not bot_response:
167
+ # Если генератор не загружен или ничего не получилось
168
+ if not GENERATOR_LOADED:
169
+ bot_response = "Модель для генерации кода не загружена."
170
+ else:
171
+ bot_response = knowledge_base.get("не найдено", "К сожалению, я пока не знаю, как на это ответить.")
172
+ print("Ответ [Заглушка/Ошибка]")
173
 
174
 
175
  # Добавляем в историю и возвращаем
176
  chat_history.append((message, bot_response))
177
+ return "", chat_history
178
 
179
 
180
+ # --- Gradio Интерфейс (CSS тот же) ---
181
+ custom_css = """
182
+ .gradio-container { background-color: #f4f7f9; border-radius: 15px; padding: 25px; color: #333; }
183
+ h1 { color: #1a237e; text-align: center; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin-bottom: 15px; font-weight: 600; }
184
+ #title-markdown p { text-align: center; color: #546e7a; margin-top: -10px; margin-bottom: 25px;}
185
+ #chatbot { background-color: #eceff1; border-radius: 12px; border: 1px solid #cfd8dc; padding: 10px; box-shadow: inset 0 1px 3px rgba(0,0,0,0.05); }
186
+ #chatbot .user-message .message-bubble-border { border: none !important; }
187
+ #chatbot .user-message .message-bubble { background: #007bff !important; color: white !important; border-radius: 18px 18px 5px 18px !important; padding: 12px 18px !important; margin: 8px 5px 8px 0 !important; align-self: flex-end !important; max-width: 80% !important; box-shadow: 0 2px 4px rgba(0, 123, 255, 0.2); word-wrap: break-word; text-align: left;}
188
+ #chatbot .bot-message .message-bubble-border { border: none !important; }
189
+ #chatbot .bot-message .message-bubble { background: #ffffff !important; color: #212529 !important; border: 1px solid #dee2e6 !important; border-radius: 18px 18px 18px 5px !important; padding: 12px 18px !important; margin: 8px 0 8px 5px !important; align-self: flex-start !important; max-width: 80% !important; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); word-wrap: break-word; text-align: left;}
190
+ #chatbot .bot-message .message-bubble pre { background-color: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; padding: 10px; margin: 8px 0 5px 0; overflow-x: auto; word-wrap: normal; }
191
+ #chatbot .bot-message .message-bubble pre code { background-color: transparent !important; color: #2d3748; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 0.9em; padding: 0; white-space: pre; }
192
+ textarea { border: 1px solid #ced4da !important; border-radius: 10px !important; padding: 12px 15px !important; background-color: #ffffff; transition: border-color 0.3s ease, box-shadow 0.3s ease; font-size: 1rem; }
193
+ textarea:focus { border-color: #80bdff !important; box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); outline: none; }
194
+ button { border-radius: 10px !important; padding: 10px 15px !important; transition: background-color 0.2s ease, transform 0.1s ease !important; font-weight: 500 !important; border: none !important; }
195
+ button:active { transform: translateY(1px); }
196
+ button.primary { background-color: #007bff !important; color: white !important; }
197
+ button.primary:hover { background-color: #0056b3 !important; box-shadow: 0 2px 5px rgba(0, 123, 255, 0.3); }
198
+ button.secondary { background-color: #6c757d !important; color: white !important; }
199
+ button.secondary:hover { background-color: #5a6268 !important; box-shadow: 0 2px 5px rgba(108, 117, 125, 0.3); }
200
+ """
201
+
202
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue=gr.themes.colors.blue, secondary_hue=gr.themes.colors.slate)) as demo:
203
+ gr.Markdown("# 🤖 Nova (DeepSeek Test) 💡 <br> Используем модель для кода. Ответы могут быть ОЧЕНЬ медленными!")
204
 
205
  chatbot = gr.Chatbot(
206
+ label="Диалог", height=550, elem_id="chatbot",
207
+ show_copy_button=True, bubble_full_width=False,
208
+ avatar_images=(None, "https://img.icons8.com/plasticine/100/bot.png")
 
 
209
  )
 
210
  with gr.Row():
211
  msg = gr.Textbox(
212
+ label="Ваше сообщение", placeholder="Напиши функцию python для...",
213
+ scale=4, show_label=False, container=False
 
 
 
214
  )
215
+ submit_btn = gr.Button("➤ Отправить", variant="primary", scale=1, min_width=120)
216
+ clear_btn = gr.Button("🗑️ Очистить", variant="secondary", scale=1, min_width=120)
217
 
 
218
  msg.submit(respond, [msg, chatbot], [msg, chatbot])
219
  submit_btn.click(respond, [msg, chatbot], [msg, chatbot])
220
  clear_btn.click(lambda: (None, []), None, [msg, chatbot], queue=False)
221
 
222
  # Запуск
223
  demo.queue()
224
+ demo.launch(debug=True)