HeavensHackDev commited on
Commit
20ffed9
·
verified ·
1 Parent(s): 26471fd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -78
app.py CHANGED
@@ -5,15 +5,10 @@ from transformers import pipeline, set_seed
5
  import random
6
  import re # Для регулярных выражений (очистка текста)
7
 
8
- # --- Загрузка моделей ---
9
- # 1. Генератор текста (для общего ответа и диалога)
10
- # Замените 'distilgpt2' на нужную модель, если используете другую
11
- # Попробуйте 'microsoft/DialoGPT-medium' - специально для диалогов (английский)
12
- # Или русские аналоги, если найдете подходящие по размеру для CPU
13
  try:
14
- # generator = pipeline('text-generation', model='distilgpt2', max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256) # Указываем pad_token_id явно
15
- # generator = pipeline('conversational', model='microsoft/DialoGPT-medium') # Специальная диалоговая модель (англ)
16
- generator = pipeline('text-generation', model='sberbank-ai/rugpt3small_based_on_gpt2', max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256) # Попробуем русскую поменьше
17
  print("Генератор текста загружен.")
18
  GENERATOR_LOADED = True
19
  except Exception as e:
@@ -21,11 +16,9 @@ except Exception as e:
21
  generator = None
22
  GENERATOR_LOADED = False
23
 
24
- # 2. Модель для ответов на вопросы (Question Answering)
25
- # Используем небольшую мультиязычную модель
26
  try:
27
- qa_pipeline = pipeline('question-answering', model='bert-large-uncased-whole-word-masking-finetuned-squad') # Пример англоязычной
28
- # qa_pipeline = pipeline('question-answering', model='timpal0l/mdeberta-v3-base-squad2') # Пример мультиязычной (может быть лучше для RU)
29
  print("QA модель загружена.")
30
  QA_LOADED = True
31
  except Exception as e:
@@ -33,21 +26,42 @@ except Exception as e:
33
  qa_pipeline = None
34
  QA_LOADED = False
35
 
36
- # --- "Встроенные" знания и команды ---
37
  knowledge_base = {
 
38
  "кто ты": "Я Nova, модель Alpha 0.95, работающая на платформе Hugging Face Spaces. Я использую нейросетевые модели для генерации ответов и ответов на вопросы.",
39
- "что ты умеешь": "Я могу пытаться поддерживать диалог, отвечать на вопросы по предоставленному контексту (если удастся его определить), и генерировать текст на основе предыдущих сообщений. Также я знаю некоторые встроенные команды.",
40
  "как дела": "Как у программы, у меня все по плану! Готова обрабатывать ваши запросы.",
41
- "помощь": "Спросите меня о чем-нибудь, или дайте команду. Я попробую ответить. Примеры команд: 'кто ты', 'что ты умеешь'.",
42
- # Можно добавить больше простых ответов
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
 
45
- # --- Функция обработки запроса ---
46
 
47
  def respond(message, chat_history):
48
- """
49
- Главная функция обработки. Определяет тип запроса и выбирает стратегию ответа.
50
- """
51
  print(f"Получено сообщение: {message}")
52
  user_message_lower = message.lower().strip().replace("?","").replace(".","").replace("!","") # Очищенный ввод для команд
53
 
@@ -58,28 +72,24 @@ def respond(message, chat_history):
58
  chat_history.append((message, bot_response))
59
  return "", chat_history
60
 
61
- # 2. Попытка ответа на вопрос с помощью QA модели
62
- # Очень упрощенная логика: если есть "?" и QA модель загружена
63
  if "?" in message and QA_LOADED and qa_pipeline:
64
- # Используем историю чата как контекст (последние сообщения)
65
  context = ""
66
  if chat_history:
67
- # Собираем текст из последних N обменов (N=2)
68
  context_parts = []
69
- for user_msg, bot_msg in chat_history[-2:]:
70
  context_parts.append(f"Пользователь: {user_msg}")
71
  context_parts.append(f"Бот: {bot_msg}")
72
  context = "\n".join(context_parts)
73
 
74
- if len(context) > 50: # Нужен минимальный контекст для QA
75
  print("Попытка ответа на вопрос через QA модель...")
76
- print(f"Контекст: {context[:200]}...") # Логируем начало контекста
77
  print(f"Вопрос: {message}")
78
  try:
79
  qa_result = qa_pipeline(question=message, context=context)
80
  print(f"Результат QA: {qa_result}")
81
- # Если модель уверена в ответе (score > порога)
82
- if qa_result and qa_result['score'] > 0.1: # Порог уверенности (нужно подбирать)
83
  bot_response = qa_result['answer']
84
  chat_history.append((message, bot_response))
85
  print(f"Ответ от QA модели: {bot_response}")
@@ -88,62 +98,46 @@ def respond(message, chat_history):
88
  print("QA модель не уверена в ответе.")
89
  except Exception as e:
90
  print(f"Ошибка при использовании QA модели: {e}")
91
- # Если QA не сработала, переходим к генерации
92
 
93
- # 3. Генерация ответа с помощью основной модели (если команды/QA не сработали)
94
  if GENERATOR_LOADED and generator:
95
  print("Генерация ответа с помощью основной модели...")
96
- # Формируем промпт с историей
97
  prompt_history = []
98
- for user_msg, bot_msg in chat_history[-3:]: # Берем последние 3 обмена
99
  prompt_history.append(f"Пользователь: {user_msg}")
100
  prompt_history.append(f"Бот: {bot_msg}")
101
  prompt_history.append(f"Пользователь: {message}")
102
- prompt_history.append("Бот:") # Приглашение для генерации ответа
103
 
104
  full_prompt = "\n".join(prompt_history)
105
- print(f"Промпт для генератора: {full_prompt[-500:]}") # Логируем конец промпта
106
 
107
  try:
108
- # Уменьшаем max_length, если промпт уже длинный
109
- # prompt_tokens = len(generator.tokenizer.encode(full_prompt)) # Подсчет токенов может быть медленным
110
- # available_tokens = generator.model.config.max_length - prompt_tokens - 10 # Запас
111
- # current_max_length = max(10, min(generator.model.config.max_length, prompt_tokens + 50)) # Генерация ~50 токенов
112
- # print(f"Макс. длина для генерации: {current_max_length}")
113
-
114
  generated_output = generator(full_prompt)[0]['generated_text']
115
-
116
- # Очистка ответа
117
- # Убираем промпт из начала
118
  bot_response = generated_output
 
 
119
  if generated_output.startswith(full_prompt):
120
  bot_response = generated_output[len(full_prompt):].strip()
121
  else:
122
- # Если промпт не найден в начале (некоторые модели ведут себя иначе)
123
- # Попробуем убрать последнее сообщение пользователя
124
  last_user_line = f"Пользователь: {message}\nБот:"
125
- if bot_response.strip().startswith(last_user_line.strip()): # Убираем и саму строку "Бот:"
126
  bot_response = bot_response.strip()[len(last_user_line.strip()):].strip()
127
- # Очень грубый способ убрать возможное эхо промпта
128
  elif len(bot_response) > len(message) and message.lower() in bot_response[:len(message)*2].lower():
129
  parts = bot_response.split('\n')
130
- if len(parts)>1:
131
- bot_response = '\n'.join(parts[1:]).strip()
132
-
133
 
134
- # Дополнительная очистка (убираем возможные "Пользователь:", "Бот:")
135
  bot_response = re.sub(r'^\s*(пользователь|user|бот|bot)\s*[:\-]?\s*', '', bot_response, flags=re.IGNORECASE).strip()
136
 
137
- if not bot_response or len(bot_response) < 3: # Проверка на совсем короткий/пустой ответ
138
- bot_response = "Хм, не знаю, что на это ответить..."
139
  print("Сге��ерирован слишком короткий ответ, используется заглушка.")
140
 
141
  except Exception as e:
142
  print(f"Ошибка при генерации: {e}")
143
- bot_response = f"Упс, произошла ошибка при генерации: {e}"
144
 
145
  else:
146
- # Если ни одна модель не загружена
147
  bot_response = "К сожалению, мои основные модули сейчас недоступны."
148
  print("Ошибка: Генератор текста не загружен.")
149
 
@@ -152,36 +146,114 @@ def respond(message, chat_history):
152
  return "", chat_history
153
 
154
 
155
- # --- Создание интерфейса Gradio ---
156
- with gr.Blocks(css=".gradio-container {background-color: #f9f9f9}") as demo: # Добавим немного CSS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  gr.Markdown(
158
  """
159
- # Nova Alpha 0.95 🚀
160
- Простой чат-бот с базовыми знаниями и попыткой ответа на вопросы.
161
- Работает на CPU, ответы могут быть медленными.
162
- """
163
  )
164
 
165
- chatbot = gr.Chatbot(label="Диалог", height=500) # Увеличим высоту
166
- with gr.Row(): # Поместим текстбокс и кнопки в ряд
167
  msg = gr.Textbox(
168
  label="Ваше сообщение",
169
- placeholder="Спросите 'кто ты' или задайте вопрос...",
170
- scale=4 # Текстбокс займет больше места
171
  )
172
- submit_btn = gr.Button("Отправить", variant="primary", scale=1) # Явная кнопка отправки
173
- clear_btn = gr.Button("Очистить", scale=1)
174
-
175
 
176
- # Связываем обработчики:
177
- # Отправка по Enter в Textbox
178
  msg.submit(respond, [msg, chatbot], [msg, chatbot])
179
- # Отправка по клику на кнопку
180
  submit_btn.click(respond, [msg, chatbot], [msg, chatbot])
 
181
 
182
- # Очистка по клику на кнопку
183
- clear_btn.click(lambda: (None, []), None, [msg, chatbot], queue=False) # Возвращаем пустой список для истории
184
-
185
- # Запуск (важно для Spaces!)
186
- demo.queue() # Используем очередь для обработки запросов по одному (лучше для CPU)
187
- demo.launch(debug=True) # debug=True покажет логи и ошибки в интерфейсе
 
5
  import random
6
  import re # Для регулярных выражений (очистка текста)
7
 
8
+ # --- Загрузка моделей (как в прошлый раз, выберите нужные) ---
 
 
 
 
9
  try:
10
+ # generator = pipeline('text-generation', model='distilgpt2', max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256)
11
+ generator = pipeline('text-generation', model='sberbank-ai/rugpt3small_based_on_gpt2', max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256)
 
12
  print("Генератор текста загружен.")
13
  GENERATOR_LOADED = True
14
  except Exception as e:
 
16
  generator = None
17
  GENERATOR_LOADED = False
18
 
 
 
19
  try:
20
+ # qa_pipeline = pipeline('question-answering', model='bert-large-uncased-whole-word-masking-finetuned-squad')
21
+ qa_pipeline = pipeline('question-answering', model='timpal0l/mdeberta-v3-base-squad2') # Мультиязычная
22
  print("QA модель загружена.")
23
  QA_LOADED = True
24
  except Exception as e:
 
26
  qa_pipeline = None
27
  QA_LOADED = False
28
 
29
+ # --- Встроенные знания и команды (РАСШИРЕНО для КОДИНГА) ---
30
  knowledge_base = {
31
+ # Мета-информация
32
  "кто ты": "Я Nova, модель Alpha 0.95, работающая на платформе Hugging Face Spaces. Я использую нейросетевые модели для генерации ответов и ответов на вопросы.",
33
+ "что ты умеешь": "Я могу пытаться поддерживать диалог, отвечать на вопросы по контексту, генерировать текст и давать базовую информацию по некоторым темам, включая программирование. Мои знания ограничены, и я не выполняю код.",
34
  "как дела": "Как у программы, у меня все по плану! Готова обрабатывать ваши запросы.",
35
+ "помощь": "Спросите меня о чем-нибудь, например, 'что такое переменная в программировании?' или 'какие есть циклы?'. Я постараюсь ответить. Также знаю команды: 'кто ты', 'что ты умеешь'.",
36
+
37
+ # Основы Программирования
38
+ "что такое программирование": "Программирование - это процесс написания инструкций (ко��а) для компьютера, чтобы он выполнял определенные задачи. Это как составление очень точного рецепта для машины.",
39
+ "зачем нужно программирование": "Программирование позволяет создавать программы, веб-сайты, игры, автоматизировать задачи, анализировать данные и многое другое. Оно лежит в основе почти всех современных технологий.",
40
+ "что такое алгоритм": "Алгоритм - это пошаговая инструкция или набор правил для решения определенной задачи. Например, рецепт приготовления блюда - это алгоритм.",
41
+ "основные концепции программирования": "Ключевые идеи включают: переменные (хранение данных), типы данных (числа, строки), условные операторы (if/else - если/иначе), циклы (for, while - для повторения действий), функции (для организации кода).",
42
+ "что такое переменная": "Переменная в программировании - это как именованный контейнер или ячейка памяти, где можно хранить данные (число, текст, и т.д.), чтобы использовать их позже в программе. Например, `age = 30`.",
43
+ "что такое типы данных": "Типы данных определяют, какого рода информацию может хранить переменная и какие операции с ней можно выполнять. Распространенные типы: целые числа (integer), числа с плавающей точкой (float), строки (string - текст), булевы (boolean - истина/ложь).",
44
+ "что такое строка": "Строка (string) - это последовательность символов, обычно используемая для представления текста. В большинстве языков строки заключаются в кавычки (одинарные или двойные). Например, \"Привет, мир!\".",
45
+ "условный оператор if": "Оператор `if` (если) позволяет выполнить блок кода только в том случае, если определенное условие истинно. Часто используется вместе с `else` (иначе) для выполнения другого блока кода, если условие ложно.",
46
+ "что такое цикл": "Цикл - это конструкция, которая позволяет повторять выполнение блока кода несколько раз. Основные виды: `for` (для), который обычно используется для перебора элементов (например, в списке) или выполнения заданное число раз, и `while` (пока), который выполняется, пока истинно определенное условие.",
47
+ "цикл for": "Цикл `for` удобен, когда вы знаете, сколько раз нужно повторить действие, или когда нужно пройти по всем элементам коллекции (списка, строки).",
48
+ "цикл while": "Цикл `while` повторяет блок кода до тех пор, пока заданное условие остается истинным. Важно убедиться, что условие когда-нибудь станет ложным, иначе цикл будет бесконечным.",
49
+ "что такое функция": "Функция - это именованный блок кода, который выполняет определенную задачу. Функции помогают разбивать сложную программу на мелкие, управляемые части, избегать повторения кода и делать его более читаемым.",
50
+ "язык программирования": "Язык программирования - это формальный язык, предназначенный для записи компьютерных программ. Популярные языки: Python (хорош для новичков, науки о данных, веб-бэкенда), JavaScript (для веб-фронтенда и бэкенда), Java (для энтерпрайза, Android), C++ (для игр, системного программирования), C# (для Windows, игр на Unity).",
51
+ "python": "Python - популярный, высокоуровневый язык программирования с простым синтаксисом, подходящий для широкого круга задач: веб-разработка, наука о данных, машинное обучение, автоматизация.",
52
+ "javascript": "JavaScript (JS) - основной язык для создания интерактивных веб-страниц (фронтенд). Также используется на бэкенде (Node.js) и для мобильных приложений.",
53
+ "html": "HTML (HyperText Markup Language) - это не язык программирования, а язык разметки. Он используется для определения структуры и содержимого веб-страницы (заголовки, параграфы, картинки, ссылки).",
54
+ "css": "CSS (Cascading Style Sheets) - язык стилей, используемый для описания внешнего вида документа, написанного на языке разметки (обычно HTML). Определяет цвета, шрифты, отступы, расположение элементов.",
55
+ "что такое api": "API (Application Programming Interface) - это набор правил и протоколов, который позволяет разным программам 'общаться' друг с другом. Это как меню в ресторане: вы выбираете блюдо (функцию API), и кухня (другая программа) его готовит и отдает вам.",
56
+ "что такое git": "Git - это распределенная система контроля версий. Она помогает разработчикам отслеживать изменения в коде, возвращаться к предыдущим версиям, работать над проектом совместно и не терять изменения.",
57
+ "где учиться программировать": "Существует множество ресурсов: интерактивные онлайн-курсы (Codecademy, Coursera, Stepik, Яндекс.Практикум), документация языков, книги, видеоуроки на YouTube, форумы (Stack Overflow), сообщества разработчиков."
58
+
59
+ # Добавьте сюда больше вопросов и ответов по кодингу!
60
  }
61
 
62
+ # --- Функция обработки запроса (логика остается той же) ---
63
 
64
  def respond(message, chat_history):
 
 
 
65
  print(f"Получено сообщение: {message}")
66
  user_message_lower = message.lower().strip().replace("?","").replace(".","").replace("!","") # Очищенный ввод для команд
67
 
 
72
  chat_history.append((message, bot_response))
73
  return "", chat_history
74
 
75
+ # 2. Попытка ответа на вопрос с помощью QA модели (упрощенная логика)
 
76
  if "?" in message and QA_LOADED and qa_pipeline:
 
77
  context = ""
78
  if chat_history:
 
79
  context_parts = []
80
+ for user_msg, bot_msg in chat_history[-2:]: # Последние 2 обмена
81
  context_parts.append(f"Пользователь: {user_msg}")
82
  context_parts.append(f"Бот: {bot_msg}")
83
  context = "\n".join(context_parts)
84
 
85
+ if len(context) > 50: # Нужен минимальный контекст
86
  print("Попытка ответа на вопрос через QA модель...")
87
+ print(f"Контекст: {context[:200]}...")
88
  print(f"Вопрос: {message}")
89
  try:
90
  qa_result = qa_pipeline(question=message, context=context)
91
  print(f"Результат QA: {qa_result}")
92
+ if qa_result and qa_result['score'] > 0.15: # Немного повысим порог
 
93
  bot_response = qa_result['answer']
94
  chat_history.append((message, bot_response))
95
  print(f"Ответ от QA модели: {bot_response}")
 
98
  print("QA модель не уверена в ответе.")
99
  except Exception as e:
100
  print(f"Ошибка при использовании QA модели: {e}")
 
101
 
102
+ # 3. Генерация ответа с помощью основной модели
103
  if GENERATOR_LOADED and generator:
104
  print("Генерация ответа с помощью основной модели...")
 
105
  prompt_history = []
106
+ for user_msg, bot_msg in chat_history[-3:]: # Последние 3 обмена
107
  prompt_history.append(f"Пользователь: {user_msg}")
108
  prompt_history.append(f"Бот: {bot_msg}")
109
  prompt_history.append(f"Пользователь: {message}")
110
+ prompt_history.append("Бот:")
111
 
112
  full_prompt = "\n".join(prompt_history)
113
+ print(f"Промпт для генератора: {full_prompt[-500:]}")
114
 
115
  try:
 
 
 
 
 
 
116
  generated_output = generator(full_prompt)[0]['generated_text']
 
 
 
117
  bot_response = generated_output
118
+
119
+ # Очистка
120
  if generated_output.startswith(full_prompt):
121
  bot_response = generated_output[len(full_prompt):].strip()
122
  else:
 
 
123
  last_user_line = f"Пользователь: {message}\nБот:"
124
+ if bot_response.strip().startswith(last_user_line.strip()):
125
  bot_response = bot_response.strip()[len(last_user_line.strip()):].strip()
 
126
  elif len(bot_response) > len(message) and message.lower() in bot_response[:len(message)*2].lower():
127
  parts = bot_response.split('\n')
128
+ if len(parts)>1: bot_response = '\n'.join(parts[1:]).strip()
 
 
129
 
 
130
  bot_response = re.sub(r'^\s*(пользователь|user|бот|bot)\s*[:\-]?\s*', '', bot_response, flags=re.IGNORECASE).strip()
131
 
132
+ if not bot_response or len(bot_response) < 3:
133
+ bot_response = knowledge_base.get("не найдено", "Хм, не знаю, что на это ответить...") # Используем "не найдено" из базы
134
  print("Сге��ерирован слишком короткий ответ, используется заглушка.")
135
 
136
  except Exception as e:
137
  print(f"Ошибка при генерации: {e}")
138
+ bot_response = knowledge_base.get("ошибка генерации", f"Упс, произошла ошибка при генерации: {e}") # Используем текст ошибки из базы
139
 
140
  else:
 
141
  bot_response = "К сожалению, мои основные модули сейчас недоступны."
142
  print("Ошибка: Генератор текста не загружен.")
143
 
 
146
  return "", chat_history
147
 
148
 
149
+ # --- Создание интерфейса Gradio с УЛУЧШЕННЫМ CSS ---
150
+
151
+ # Определяем CSS стили
152
+ custom_css = """
153
+ /* Общий фон */
154
+ .gradio-container {
155
+ background: linear-gradient(to bottom right, #e0f7fa, #f1f8e9); /* Приятный градиент */
156
+ border-radius: 15px;
157
+ padding: 25px;
158
+ }
159
+
160
+ /* Заголовок */
161
+ h1 {
162
+ color: #004d40; /* Темно-бирюзовый */
163
+ text-align: center;
164
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
165
+ margin-bottom: 15px;
166
+ }
167
+
168
+ /* Контейнер чата */
169
+ #chatbot {
170
+ background-color: #ffffff; /* Белый фон для сообщений */
171
+ border-radius: 10px;
172
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1); /* Легкая тень */
173
+ border: 1px solid #e0e0e0;
174
+ }
175
+
176
+ /* Сообщения пользователя */
177
+ #chatbot .user {
178
+ background-color: #e3f2fd; /* Голубоватый фон */
179
+ color: #0d47a1; /* Темно-синий текст */
180
+ border-radius: 15px 15px 0 15px; /* Скругление углов */
181
+ padding: 10px 15px;
182
+ margin: 5px;
183
+ align-self: flex-end; /* Выравнивание справа */
184
+ max-width: 85%;
185
+ }
186
+
187
+ /* Сообщения бота */
188
+ #chatbot .bot {
189
+ background-color: #f1f8e9; /* Светло-зеленоватый фон */
190
+ color: #33691e; /* Темно-зеленый текст */
191
+ border-radius: 15px 15px 15px 0; /* Скругление углов */
192
+ padding: 10px 15px;
193
+ margin: 5px;
194
+ align-self: flex-start; /* Выравнивание слева */
195
+ max-width: 85%;
196
+ }
197
+
198
+ /* Поле ввода текста */
199
+ textarea {
200
+ border: 1px solid #b0bec5; /* Сероватая рамка */
201
+ border-radius: 8px !important; /* !important нужен для переопределения стандартных стилей gradio */
202
+ padding: 12px !important;
203
+ background-color: #ffffff;
204
+ transition: border-color 0.3s ease;
205
+ }
206
+ textarea:focus {
207
+ border-color: #0277bd !important; /* Синяя рамка при фокусе */
208
+ box-shadow: 0 0 5px rgba(2, 119, 189, 0.3);
209
+ }
210
+
211
+ /* Кнопки */
212
+ button {
213
+ border-radius: 8px !important;
214
+ transition: background-color 0.3s ease, box-shadow 0.3s ease !important;
215
+ font-weight: 500 !important;
216
+ }
217
+ button.primary { /* Основная кнопка Отправить */
218
+ background: linear-gradient(to right, #007991, #78ffd6) !important; /* Бирюзовый градиент */
219
+ color: white !important;
220
+ border: none !important;
221
+ }
222
+ button.primary:hover {
223
+ box-shadow: 0 4px 8px rgba(0, 121, 145, 0.3);
224
+ background: linear-gradient(to right, #006073, #5fddb8) !important; /* Чуть темнее при наведении */
225
+ }
226
+ button.secondary { /* Кнопка Очистить */
227
+ background-color: #cfd8dc !important; /* Светло-серый */
228
+ color: #37474f !important;
229
+ border: 1px solid #b0bec5 !important;
230
+ }
231
+ button.secondary:hover {
232
+ background-color: #b0bec5 !important; /* Темнее при наведении */
233
+ }
234
+ """
235
+
236
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo: # Применяем CSS и мягкую тему
237
  gr.Markdown(
238
  """
239
+ # 🤖 Nova Alpha 0.95 🎨
240
+ Улучшенный интерфейс! Задавайте вопросы или команды.
241
+ """, elem_id="title-markdown" # Можно задать ID для CSS
 
242
  )
243
 
244
+ chatbot = gr.Chatbot(label="Диалог", height=500, elem_id="chatbot")
245
+ with gr.Row():
246
  msg = gr.Textbox(
247
  label="Ваше сообщение",
248
+ placeholder="Спросите о Python или скажите 'привет'...",
249
+ scale=4
250
  )
251
+ submit_btn = gr.Button("Отправить", variant="primary", scale=1)
252
+ clear_btn = gr.Button("Очистить", variant="secondary", scale=1) # Добавили класс для CSS
 
253
 
 
 
254
  msg.submit(respond, [msg, chatbot], [msg, chatbot])
 
255
  submit_btn.click(respond, [msg, chatbot], [msg, chatbot])
256
+ clear_btn.click(lambda: (None, []), None, [msg, chatbot], queue=False)
257
 
258
+ demo.queue()
259
+ demo.launch(debug=True)