Spaces:
Runtime error
Runtime error
# --- Создание интерфейса Gradio с УЛУЧШЕННЫМ и БОЛЕЕ КОНТРАСТНЫМ CSS --- | |
# Определяем CSS стили | |
custom_css = """ | |
/* Общий фон */ | |
.gradio-container { | |
/* background: linear-gradient(to bottom right, #e0f7fa, #f1f8e9); */ /* Убрали градиент, может мешать */ | |
background-color: #f4f7f9; /* Спокойный светло-серый фон */ | |
border-radius: 15px; | |
padding: 25px; | |
color: #333; /* Основной цвет текста */ | |
} | |
/* Заголовок */ | |
h1 { | |
color: #1a237e; /* Глубокий индиго */ | |
text-align: center; | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Читаемый шрифт */ | |
margin-bottom: 15px; | |
font-weight: 600; | |
} | |
#title-markdown p { /* Стили для параграфа под заголовком */ | |
text-align: center; | |
color: #546e7a; /* Серо-синий */ | |
margin-top: -10px; | |
margin-bottom: 25px; | |
} | |
/* --- СТИЛИ ЧАТА --- */ | |
/* Контейнер чата */ | |
#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); /* Легкая внутренняя тень */ | |
} | |
/* Сообщения пользователя */ | |
#chatbot .user-message .message-bubble-border { | |
border: none !important; /* Убираем стандартную рамку gradio */ | |
} | |
#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; | |
} | |
/* Сообщения бота */ | |
#chatbot .bot-message .message-bubble-border { | |
border: none !important; /* Убираем стандартную рамку gradio */ | |
} | |
#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; | |
} | |
/* Блоки кода внутри сообщений бота */ | |
#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; /* Предотвратить перенос слов в коде */ | |
} | |
#chatbot .bot-message .message-bubble pre code { | |
background-color: transparent !important; /* Убираем фон у самого тега code */ | |
color: #2d3748; /* Цвет текста кода */ | |
font-family: 'Consolas', 'Monaco', 'Courier New', monospace; /* Моноширинный шрифт */ | |
font-size: 0.9em; /* Размер шрифта кода */ | |
padding: 0; /* Убираем внутренние отступы тега code */ | |
white-space: pre; /* Сохраняем пробелы и переносы */ | |
} | |
/* --- ОСТАЛЬНЫЕ ЭЛЕМЕНТЫ --- */ | |
/* Поле ввода текста */ | |
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; /* Слегка увеличим шрифт ввода */ | |
} | |
textarea:focus { | |
border-color: #80bdff !important; | |
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); | |
outline: none; /* Убираем стандартный outline */ | |
} | |
/* Кнопки */ | |
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; /* Убираем рамки по умолчанию */ | |
} | |
button:active { | |
transform: translateY(1px); /* Эффект нажатия */ | |
} | |
button.primary { /* Кнопка "Отправить" */ | |
background-color: #007bff !important; /* Синий цвет */ | |
color: white !important; | |
} | |
button.primary:hover { | |
background-color: #0056b3 !important; /* Темнее при наведении */ | |
box-shadow: 0 2px 5px rgba(0, 123, 255, 0.3); | |
} | |
button.secondary { /* Кнопка "Очистить" */ | |
background-color: #6c757d !important; /* Серый цвет */ | |
color: white !important; | |
} | |
button.secondary:hover { | |
background-color: #5a6268 !important; /* Темнее при наведении */ | |
box-shadow: 0 2px 5px rgba(108, 117, 125, 0.3); | |
} | |
""" | |
# --- Python код остается тем же, что и в предыдущем ответе --- | |
# (начиная с import gradio as gr...) | |
# ... весь остальной Python код без изменений ... | |
import gradio as gr | |
from transformers import pipeline, set_seed | |
import random | |
import re # Для регулярных выражений (очистка текста) | |
# --- Загрузка моделей (выберите нужные) --- | |
# Модель-генератор (например, русская или английская) | |
GENERATOR_MODEL_NAME = 'sberbank-ai/rugpt3small_based_on_gpt2' # Или 'distilgpt2' | |
try: | |
generator = pipeline('text-generation', model=GENERATOR_MODEL_NAME, max_length=100, num_return_sequences=1, truncation=True, pad_token_id=50256) | |
print(f"Генератор текста ({GENERATOR_MODEL_NAME}) загружен.") | |
GENERATOR_LOADED = True | |
except Exception as e: | |
print(f"ОШИБКА: Не удалось загрузить генератор текста! {e}") | |
generator = None | |
GENERATOR_LOADED = False | |
# QA Модель (например, мультиязычная) | |
QA_MODEL_NAME = 'timpal0l/mdeberta-v3-base-squad2' | |
try: | |
qa_pipeline = pipeline('question-answering', model=QA_MODEL_NAME) | |
print(f"QA модель ({QA_MODEL_NAME}) загружена.") | |
QA_LOADED = True | |
except Exception as e: | |
print(f"ОШИБКА: Не удалось загрузить QA модель! {e}") | |
qa_pipeline = None | |
QA_LOADED = False | |
# --- Встроенные знания и команды (Дополнены ответы про кодинг) --- | |
knowledge_base = { | |
# Мета-информация | |
"кто ты": "Я Nova, модель Alpha 0.96, работающая на платформе Hugging Face Spaces. Я стараюсь отвечать на вопросы и поддерживать диалог, используя предопределенные ответы и нейросетевые модели.", | |
"что ты умеешь": "Я могу отвечать на некоторые вопросы по программированию и другим темам из моей базы знаний, пытаться отвечать на вопросы по контексту диалога (если есть QA-модель) и поддерживать беседу. Я НЕ МОГУ выполнять команды по написанию произвольного кода, но могу дать общие объяснения или простые примеры.", # Уточнено про код | |
"как дела": "Как у программы, у меня все по плану! Готова обрабатывать ваши запросы.", | |
"помощь": "Спросите меня о чем-нибудь, например, 'что такое переменная в программировании?' или 'расскажи про python'. Я постараюсь ответить. Также знаю команды: 'кто ты', 'что ты умеешь'.", | |
# --- НОВЫЕ ОТВЕТЫ на запросы КОДА --- | |
"напиши код": "Я не могу писать произвольный код по запросу. Моя функция - давать информацию и объяснения. Возможно, вы имели в виду пример кода для какой-то задачи? Попробуйте спросить конкретнее, например: 'пример цикла for на python'.", | |
"сгенерируй код": "Генерация сложного кода пока не входит в мои возможности. Я могу объяснить концепции или показать базовые синтаксические конструкции. Какой пример вас интересует?", | |
"напиши скрипт": "К сожалению, я не пишу готовые скрипты. Опишите задачу, и я постараюсь объяснить, какие шаги или концепции программирования могут понадобиться для ее решения.", | |
"код на питоне": "Пайтон - отличный язык! Уточните, какой именно аспект или пример кода на Python вас интересует? Например, 'как объявить переменную на python?' или 'пример функции на python'.", | |
"пример кода": "Конечно! Какой пример кода вы хотели бы увидеть? Например, 'пример условного оператора if' или 'пример простого класса на python'.", | |
"hello world на python": "Самый классический пример! Вот 'Hello, World!' на Python:\n```python\nprint(\"Hello, World!\")\n```", | |
"пример цикла for на python": "Вот пример цикла `for`, который печатает числа от 0 до 4:\n```python\nfor i in range(5):\n print(i)\n```", | |
"пример функции на python": "Вот простая функция на Python, которая складывает два числа:\n```python\ndef add_numbers(a, b):\n return a + b\n\nresult = add_numbers(5, 3)\nprint(result) # Выведет 8\n```", | |
"как объявить переменную на python": "Переменная в Python объявляется простым присваиванием значения. Например:\n```python\nmy_variable = 10\nuser_name = \"Alice\"\nis_active = True\n```", | |
# Основы Программирования (остальное из 0.95) | |
"что такое программирование": "Программирование - это процесс написания инструкций (кода) для компьютера, чтобы он выполнял определенные задачи. Это как составление очень точного рецепта для машины.", | |
"зачем нужно программирование": "Программирование позволяет создавать программы, веб-сайты, игры, автоматизировать задачи, анализировать данные и многое другое. Оно лежит в основе почти всех современных технологий.", | |
"что такое алгоритм": "Алгоритм - это пошаговая инструкция или набор правил для решения определенной задачи. Например, рецепт приготовления блюда - это алгоритм.", | |
"основные концепции программирования": "Ключевые идеи включают: переменные (хранение данных), типы данных (числа, строки), условные операторы (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 clean_text(text): | |
if not isinstance(text, str): return "" | |
text = text.lower().strip() | |
text = re.sub(r"^[?!.,\s]+|[?!.,\s]+$", "", text) | |
text = re.sub(r"\s+", " ", text) | |
return text | |
def clean_generated_output(generated_text, prompt): | |
if not generated_text or not isinstance(generated_text, str): return "" | |
if not prompt or not isinstance(prompt, str): prompt = "" | |
cleaned = generated_text | |
prompt_clean = prompt.strip() | |
if prompt_clean and cleaned.startswith(prompt_clean): | |
cleaned = cleaned[len(prompt_clean):].strip() | |
cleaned = re.sub(r'^\s*(ответ|бот|пользователь|user|bot)\s*[:\-]?\s*', '', cleaned, flags=re.IGNORECASE | re.MULTILINE).strip() | |
last_lines = prompt_clean.split('\n') | |
if len(last_lines) >= 2: | |
last_user_line = last_lines[-2].strip() | |
if last_user_line.lower().startswith(("пользователь:", "user:")): | |
user_message_only = last_user_line.split(":", 1)[1].strip() | |
if user_message_only and cleaned.lower().startswith(user_message_only.lower()): | |
end_of_echo_pos = len(user_message_only) | |
following_text = cleaned[end_of_echo_pos:].lstrip() | |
if re.match(r'^(бот|bot)\s*[:\-]?\s*', following_text, flags=re.IGNORECASE): | |
following_text = re.sub(r'^(бот|bot)\s*[:\-]?\s*', '', following_text, flags=re.IGNORECASE).strip() | |
cleaned = following_text | |
cleaned = re.sub(r'^\s*(ответ|бот|пользователь|user|bot)\s*[:\-]?\s*', '', cleaned, flags=re.IGNORECASE | re.MULTILINE).strip() | |
return cleaned | |
# --- Основная Функция Обработки (Alpha 0.96 Логика) --- | |
def respond(message, chat_history): | |
print("-" * 30) | |
print(f"ВХОД: '{message}'") | |
user_message_clean = clean_text(message) | |
bot_response = "" # Инициализация переменной | |
# 1. Точное совпадение в knowledge_base | |
if user_message_clean in knowledge_base: | |
bot_response = knowledge_base[user_message_clean] | |
print(f"Ответ [Точный]: {bot_response[:100]}...") # Логгируем начало ответа | |
# 2. Запрос кода | |
if not bot_response: # Только если не нашли точный ответ | |
code_request_patterns = ["напиши код", "напиши скрипт", "сгенерируй код", "создай код", "write code", "generate code", "create script", "code example for", "пример кода для"] | |
is_code_request = any(user_message_clean.startswith(pattern) for pattern in code_request_patterns) | |
if is_code_request: | |
bot_response = knowledge_base.get("напиши код", "Я не могу писать произвольный код, но могу дать объяснение или пример. Уточните ваш запрос.") | |
print(f"Ответ [Запрос кода]: {bot_response}") | |
# 3. QA модель | |
if not bot_response and "?" in message and QA_LOADED and qa_pipeline: | |
context = "" | |
if chat_history: | |
context_parts = [] | |
for user_msg, bot_msg in chat_history[-2:]: | |
context_parts.append(f"Пользователь: {user_msg}") | |
if bot_msg: context_parts.append(f"Бот: {bot_msg}") | |
context = "\n".join(context_parts) | |
if len(context) > 50: | |
print("Попытка ответа через QA...") | |
try: | |
qa_result = qa_pipeline(question=message, context=context) | |
print(f"Результат QA: score={qa_result.get('score', 0):.2f}, answer='{qa_result.get('answer', '')[:50]}...'") | |
if qa_result and qa_result['score'] > 0.25: # Уверенность > 25% | |
answer = qa_result['answer'].strip() | |
if answer: | |
bot_response = answer | |
print(f"Ответ [QA]: {bot_response[:100]}...") | |
else: print("QA модель дала пустой ответ.") | |
else: print("QA модель не уверена.") | |
except Exception as e: print(f"Ошибка при использовании QA модели: {e}") | |
# 4. Генерация | |
if not bot_response and GENERATOR_LOADED and generator: | |
print("Попытка генерации ответа...") | |
prompt_history = [] | |
for user_msg, bot_msg in chat_history[-3:]: | |
prompt_history.append(f"Пользователь: {user_msg}") | |
if bot_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'] | |
print(f"Сырой ответ генератора: {generated_output}") | |
cleaned_generated = clean_generated_output(generated_output, full_prompt) | |
print(f"Очищенный ответ генератора: {cleaned_generated}") | |
if cleaned_generated and len(cleaned_generated) > 5: # Минимальная длина для осмысленного ответа | |
bot_response = cleaned_generated | |
print(f"Ответ [Генерация]: {bot_response[:100]}...") | |
else: | |
print("Генерация не удалась или слишком короткая.") | |
except Exception as e: | |
print(f"Ошибка при генерации: {e}") | |
bot_response = knowledge_base.get("ошибка генерации", "Произошла ошибка при попытке сгенерировать ответ.") | |
# 5. Ответ по умолчанию (если ничего не сработало) | |
if not bot_response: | |
bot_response = knowledge_base.get("не найдено", "К сожалению, я пока не знаю, как на это ответить.") | |
print("Ответ [Не найдено/Заглушка]") | |
# Добавляем в историю и возвращаем | |
chat_history.append((message, bot_response)) | |
return "", chat_history # Очищаем поле ввода | |
# --- Gradio Интерфейс --- | |
with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue=gr.themes.colors.blue, secondary_hue=gr.themes.colors.slate)) as demo: # Тема с цветами | |
gr.Markdown("# 🤖 Nova Alpha 0.96 ✨ <br> Улучшенный интерфейс и знания о коде", elem_id="title-markdown") | |
chatbot = gr.Chatbot( | |
label="Диалог", | |
height=550, | |
elem_id="chatbot", | |
bubble_full_width=False, | |
avatar_images=(None, "https://img.icons8.com/plasticine/100/bot.png") # Аватарка для бота | |
) | |
with gr.Row(): | |
msg = gr.Textbox( | |
label="Ваше сообщение", | |
placeholder="Спросите о Python или скажите 'привет'...", | |
scale=4, | |
show_label=False, | |
container=False # Убираем контейнер текстбокса для лучшего выравнивания | |
) | |
submit_btn = gr.Button("➤ Отправить", variant="primary", scale=1, min_width=120) # Иконка и мин. ширина | |
clear_btn = gr.Button("🗑️ Очистить", variant="secondary", scale=1, min_width=120) # Иконка и мин. ширина | |
# Обработчики | |
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) |