Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,40 +1,195 @@
|
|
| 1 |
-
#
|
| 2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import gradio as gr
|
| 4 |
from transformers import pipeline, set_seed
|
| 5 |
import random
|
| 6 |
import re # Для регулярных выражений (очистка текста)
|
| 7 |
|
| 8 |
-
# --- Загрузка моделей (
|
|
|
|
|
|
|
| 9 |
try:
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
print("Генератор текста загружен.")
|
| 13 |
GENERATOR_LOADED = True
|
| 14 |
except Exception as e:
|
| 15 |
print(f"ОШИБКА: Не удалось загрузить генератор текста! {e}")
|
| 16 |
generator = None
|
| 17 |
GENERATOR_LOADED = False
|
| 18 |
|
|
|
|
|
|
|
| 19 |
try:
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
print("QA модель загружена.")
|
| 23 |
QA_LOADED = True
|
| 24 |
except Exception as e:
|
| 25 |
print(f"ОШИБКА: Не удалось загрузить QA модель! {e}")
|
| 26 |
qa_pipeline = None
|
| 27 |
QA_LOADED = False
|
| 28 |
|
| 29 |
-
# --- Встроенные знания и команды (
|
| 30 |
knowledge_base = {
|
| 31 |
# Мета-информация
|
| 32 |
-
"кто ты": "Я Nova, модель Alpha 0.
|
| 33 |
-
"что ты умеешь": "Я могу
|
| 34 |
"как дела": "Как у программы, у меня все по плану! Готова обрабатывать ваши запросы.",
|
| 35 |
-
"помощь": "Спросите меня о чем-нибудь, например, 'что такое переменная в программировании?' или '
|
| 36 |
-
|
| 37 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
"что такое программирование": "Программирование - это процесс написания инструкций (кода) для компьютера, чтобы он выполнял определенные задачи. Это как составление очень точного рецепта для машины.",
|
| 39 |
"зачем нужно программирование": "Программирование позволяет создавать программы, веб-сайты, игры, автоматизировать задачи, анализировать данные и многое другое. Оно лежит в основе почти всех современных технологий.",
|
| 40 |
"что такое алгоритм": "Алгоритм - это пошаговая инструкция или набор правил для решения определенной задачи. Например, рецепт приготовления блюда - это алгоритм.",
|
|
@@ -55,205 +210,145 @@ knowledge_base = {
|
|
| 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(
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
# 2.
|
| 76 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
context = ""
|
| 78 |
if chat_history:
|
| 79 |
context_parts = []
|
| 80 |
-
for user_msg, bot_msg in chat_history[-2:]:
|
| 81 |
context_parts.append(f"Пользователь: {user_msg}")
|
| 82 |
-
context_parts.append(f"Бот: {bot_msg}")
|
| 83 |
context = "\n".join(context_parts)
|
| 84 |
-
|
| 85 |
-
|
| 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.
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
except Exception as e:
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
print("Генерация ответа с помощью основной модели...")
|
| 105 |
prompt_history = []
|
| 106 |
-
for user_msg, bot_msg in chat_history[-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 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
if
|
| 121 |
-
bot_response =
|
|
|
|
| 122 |
else:
|
| 123 |
-
|
| 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("ошибка генерации",
|
| 139 |
-
|
| 140 |
-
else:
|
| 141 |
-
bot_response = "К сожалению, мои основные модули сейчас недоступны."
|
| 142 |
-
print("Ошибка: Генератор текста не загружен.")
|
| 143 |
-
|
| 144 |
-
chat_history.append((message, bot_response))
|
| 145 |
-
print(f"Финальный ответ: {bot_response}")
|
| 146 |
-
return "", chat_history
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
# --- Создание интерфейса Gradio с УЛУЧШЕННЫМ CSS ---
|
| 150 |
|
| 151 |
-
#
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 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 |
-
|
| 170 |
-
|
| 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 |
-
|
| 200 |
-
|
| 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 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 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) #
|
| 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)
|
|
|
|
| 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 |
"что такое алгоритм": "Алгоритм - это пошаговая инструкция или набор правил для решения определенной задачи. Например, рецепт приготовления блюда - это алгоритм.",
|
|
|
|
| 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()
|
| 219 |
+
text = re.sub(r"^[?!.,\s]+|[?!.,\s]+$", "", text)
|
| 220 |
+
text = re.sub(r"\s+", " ", 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)
|