marry1908's picture
Update app.py
8e56d7c verified
import gradio as gr
import time
import pandas as pd
from datetime import datetime
import numpy as np
# Импортируем transformers с обработкой ошибок
try:
from transformers import pipeline
transformers_available = True
except ImportError:
transformers_available = False
print("Transformers not available, using mock mode")
# История запросов
history = []
MAX_HISTORY = 10
# Темы для классификации
PREDEFINED_TOPICS = [
"спорт", "политика", "наука", "технологии",
"здоровье", "образование", "культура", "экономика",
"путешествия", "развлечения", "погода", "происшествия"
]
TOPIC_DESCRIPTIONS = {
"спорт": "🏀 Спорт",
"политика": "🏛️ Политика",
"наука": "🔬 Наука",
"технологии": "💻 Технологии",
"здоровье": "🏥 Здоровье",
"образование": "📚 Образование",
"культура": "🎭 Культура",
"экономика": "💰 Экономика",
"путешествия": "✈️ Путешествия",
"развлечения": "🎬 Развлечения",
"погода": "☀️ Погода",
"происшествия": "🚨 Происшествия"
}
def simple_classifier(text, topics):
"""Простой классификатор на основе ключевых слов"""
text_lower = text.lower()
scores = []
# Ключевые слова для каждой темы
keywords = {
"спорт": ["матч", "игра", "команда", "победил", "счёт", "футбол", "хоккей", "соревнование"],
"политика": ["президент", "правительство", "закон", "выборы", "парламент", "министр", "депутат"],
"наука": ["учёный", "исследование", "открытие", "лаборатория", "эксперимент", "научный"],
"технологии": ["компьютер", "смартфон", "интернет", "программа", "гаджет", "робот", "искусственный интеллект"],
"здоровье": ["врач", "больница", "лечение", "болезнь", "пациент", "медицина", "здоровый"],
"образование": ["школа", "университет", "студент", "учитель", "экзамен", "урок", "образование"],
"культура": ["фильм", "музыка", "театр", "выставка", "художник", "писатель", "книга"],
"экономика": ["деньги", "банк", "компания", "рынок", "цена", "экономика", "финансы"],
"путешествия": ["отпуск", "отель", "пляж", "горы", "путешествие", "турист", "страна"],
"развлечения": ["кино", "сериал", "игра", "концерт", "развлечение", "отдых"],
"погода": ["температура", "дождь", "снег", "солнце", "погода", "климат", "ветер"],
"происшествия": ["авария", "пожар", "происшествие", "инцидент", "катастрофа", "чрезвычайная ситуация"]
}
for topic in topics:
score = 0
for keyword in keywords.get(topic, []):
if keyword in text_lower:
score += 1
scores.append(score / max(len(keywords.get(topic, [])), 1))
return scores
def classify_topic(text, show_top_n=3):
"""Классифицирует текст по темам"""
# Проверка ошибок
if not text or text.strip() == "":
return "⚠️ Пожалуйста, введите текст для анализа", "", []
if len(text) > 2000:
return "⚠️ Текст слишком длинный (максимум 2000 символов)", "", []
try:
# Измеряем время выполнения
start_time = time.time()
# Пытаемся использовать трансформеры, если доступны
if transformers_available:
try:
classifier = pipeline("zero-shot-classification",
model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli",
device=-1)
results = classifier(
text,
candidate_labels=PREDEFINED_TOPICS,
multi_label=False
)
labels = results['labels']
scores = results['scores']
except Exception as model_error:
# Если не получилось с трансформерами, используем простой классификатор
print(f"Model error: {model_error}, using simple classifier")
scores = simple_classifier(text, PREDEFINED_TOPICS)
labels = PREDEFINED_TOPICS
else:
# Если трансформеры не установлены
scores = simple_classifier(text, PREDEFINED_TOPICS)
labels = PREDEFINED_TOPICS
elapsed_time = time.time() - start_time
# Сортируем результаты
if isinstance(scores, list):
sorted_indices = np.argsort(scores)[::-1][:show_top_n]
else:
# Если scores уже numpy array
sorted_indices = scores.argsort()[::-1][:show_top_n]
# Форматируем результаты
output_text = f"📊 **Тематическая классификация:**\n\n"
for i, idx in enumerate(sorted_indices, 1):
topic = labels[idx]
score = scores[idx] * 100
description = TOPIC_DESCRIPTIONS.get(topic, topic)
# Прогресс-бар
bar_length = 20
filled = int(score * bar_length / 100)
progress_bar = "█" * filled + "░" * (bar_length - filled)
output_text += f"{i}. **{description}** - {score:.1f}%\n"
output_text += f" {progress_bar}\n\n"
output_text += f"\n⏱️ **Время обработки:** {elapsed_time:.2f} секунд"
# Сохраняем в историю
timestamp = datetime.now().strftime("%H:%M:%S")
top_topic = labels[sorted_indices[0]]
history.insert(0, {
'time': timestamp,
'text': text[:50] + ("..." if len(text) > 50 else ""),
'topic': TOPIC_DESCRIPTIONS.get(top_topic, top_topic),
'confidence': f"{scores[sorted_indices[0]]*100:.1f}%"
})
# Ограничиваем историю
if len(history) > MAX_HISTORY:
history.pop()
# Создаём DataFrame для таблицы
df = pd.DataFrame(history)
return output_text, f"✅ Текст успешно обработан за {elapsed_time:.2f} сек", df
except Exception as e:
return f"❌ **Ошибка:** {str(e)}", "", []
def clear_history():
"""Очищает историю запросов"""
global history
history = []
return pd.DataFrame()
# Создаём интерфейс
with gr.Blocks(title="Тематический классификатор текста", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🏷️ Тематический классификатор текста")
gr.Markdown("Определяет основную тему текста: спорт, политика, наука, технологии и другие")
with gr.Row():
with gr.Column(scale=2):
# Входные элементы
text_input = gr.Textbox(
label="📝 Введите текст для анализа",
placeholder="Например: 'Сегодня на матче сборная России победила со счётом 3:1...'",
lines=5,
max_lines=10
)
with gr.Row():
top_n_slider = gr.Slider(
minimum=1,
maximum=5,
value=3,
step=1,
label="🔢 Количество топ-тем для показа"
)
analyze_btn = gr.Button("🚀 Определить тему", variant="primary", size="lg")
clear_btn = gr.Button("🧹 Очистить историю", variant="secondary")
# Примеры для ТЕМАТИЧЕСКОЙ классификации
gr.Markdown("### 📌 Готовые примеры")
examples = gr.Examples(
examples=[
["Сегодня на стадионе «Лужники» прошёл финальный матч чемпионата России по футболу. Команда «Спартак» одержала победу со счётом 2:1 над ЦСКА."],
["Парламент принял новый закон о цифровой экономике, который регулирует использование криптовалют и блокчейн-технологий."],
["Учёные из МГУ открыли новый метод лечения рака с помощью наночастиц. Клинические испытания показали эффективность в 85% случаев."],
["Компания Apple представила новый iPhone с революционной камерой и процессором собственной разработки. Продажи начнутся с следующей недели."],
["Врачи рекомендуют увеличить потребление овощей и фруктов для профилактики сердечно-сосудистых заболеваний. Исследования подтвердили снижение риска на 30%."],
["Министерство образования анонсировало реформу ЕГЭ. Изменения коснутся формата экзаменов по математике и русскому языку."],
["В Эрмитаже открылась выставка французских импрессионистов. В экспозиции представлены работы Моне, Ренуара и Дега."]
],
inputs=text_input,
label="Кликните на любой пример"
)
with gr.Column(scale=3):
# Результаты
output_md = gr.Markdown(label="📊 Результаты классификации")
status_text = gr.Textbox(label="✅ Статус", interactive=False)
gr.Markdown("### 📋 История запросов")
history_table = gr.Dataframe(
headers=["Время", "Текст", "Тема", "Уверенность"],
datatype=["str", "str", "str", "str"],
interactive=False,
)
# Обработчики событий
analyze_btn.click(
fn=classify_topic,
inputs=[text_input, top_n_slider],
outputs=[output_md, status_text, history_table]
)
clear_btn.click(
fn=clear_history,
inputs=[],
outputs=[history_table]
)
# Информационный блок
gr.Markdown("---")
with gr.Accordion("📚 Подробная информация о модели", open=False):
gr.Markdown("""
**Используемая модель:** `MoritzLaurer/mDeBERTa-v3-base-mnli-xnli`
**Почему эта модель:**
- **Лёгкая** (300 МБ вместо 1.6 ГБ)
- **Мультиязычная** с хорошей поддержкой русского
- **Быстро загружается** на бесплатном CPU
**Определяемые темы:**
- 🏀 **Спорт** - спортивные события, соревнования, команды
- 🏛️ **Политика** - политические новости, выборы, законы
- 🔬 **Наука** - научные открытия, исследования
- 💻 **Технологии** - IT, гаджеты, программы
- 🏥 **Здоровье** - медицина, лечение, здоровье
- 📚 **Образование** - обучение, экзамены, школы
- 🎭 **Культура** - искусство, музыка, кино
- 💰 **Экономика** - финансы, бизнес, рынки
- ✈️ **Путешествия** - туризм, страны
- 🎬 **Развлечения** - фильмы, игры, шоу
- ☀️ **Погода** - климат, температура
- 🚨 **Происшествия** - аварии, криминал
**Технические детали:**
- Модель на основе DeBERTa-v3
- Поддерживает 12 предопределённых тем
- Работает на CPU за 1-3 секунды
- Поддерживает тексты до 2000 символов
""")
gr.Markdown("---")
gr.Markdown("""
### ⚠️ Ограничения и примечания
1. Максимальная длина текста: **2000 символов**
2. Поддерживает русский и английский языки
3. Может определять только одну основную тему
4. Для сложных текстов может потребоваться ручная проверка
5. Точность: ~70-80% на новостных текстах
""")
if __name__ == "__main__":
demo.launch(debug=False)