marry1908/topic-classification
0
1import gradio as gr2import time3import pandas as pd4from datetime import datetime5import numpy as np6 7# Импортируем transformers с обработкой ошибок8try:9 from transformers import pipeline10 transformers_available = True11except ImportError:12 transformers_available = False13 print("Transformers not available, using mock mode")14 15# История запросов16history = []17MAX_HISTORY = 1018 19# Темы для классификации20PREDEFINED_TOPICS = [21 "спорт", "политика", "наука", "технологии", 22 "здоровье", "образование", "культура", "экономика",23 "путешествия", "развлечения", "погода", "происшествия"24]25 26 27TOPIC_DESCRIPTIONS = {28 "спорт": "🏀 Спорт",29 "политика": "🏛️ Политика", 30 "наука": "🔬 Наука",31 "технологии": "💻 Технологии",32 "здоровье": "🏥 Здоровье",33 "образование": "📚 Образование",34 "культура": "🎭 Культура",35 "экономика": "💰 Экономика",36 "путешествия": "✈️ Путешествия",37 "развлечения": "🎬 Развлечения",38 "погода": "☀️ Погода",39 "происшествия": "🚨 Происшествия"40}41 42 43def simple_classifier(text, topics):44 """Простой классификатор на основе ключевых слов"""45 text_lower = text.lower()46 scores = []47 48 # Ключевые слова для каждой темы49 keywords = {50 "спорт": ["матч", "игра", "команда", "победил", "счёт", "футбол", "хоккей", "соревнование"],51 "политика": ["президент", "правительство", "закон", "выборы", "парламент", "министр", "депутат"],52 "наука": ["учёный", "исследование", "открытие", "лаборатория", "эксперимент", "научный"],53 "технологии": ["компьютер", "смартфон", "интернет", "программа", "гаджет", "робот", "искусственный интеллект"],54 "здоровье": ["врач", "больница", "лечение", "болезнь", "пациент", "медицина", "здоровый"],55 "образование": ["школа", "университет", "студент", "учитель", "экзамен", "урок", "образование"],56 "культура": ["фильм", "музыка", "театр", "выставка", "художник", "писатель", "книга"],57 "экономика": ["деньги", "банк", "компания", "рынок", "цена", "экономика", "финансы"],58 "путешествия": ["отпуск", "отель", "пляж", "горы", "путешествие", "турист", "страна"],59 "развлечения": ["кино", "сериал", "игра", "концерт", "развлечение", "отдых"],60 "погода": ["температура", "дождь", "снег", "солнце", "погода", "климат", "ветер"],61 "происшествия": ["авария", "пожар", "происшествие", "инцидент", "катастрофа", "чрезвычайная ситуация"]62 }63 64 for topic in topics:65 score = 066 for keyword in keywords.get(topic, []):67 if keyword in text_lower:68 score += 169 scores.append(score / max(len(keywords.get(topic, [])), 1))70 71 return scores72 73def classify_topic(text, show_top_n=3):74 """Классифицирует текст по темам"""75 76 # Проверка ошибок77 if not text or text.strip() == "":78 return "⚠️ Пожалуйста, введите текст для анализа", "", []79 80 if len(text) > 2000:81 return "⚠️ Текст слишком длинный (максимум 2000 символов)", "", []82 83 try:84 # Измеряем время выполнения85 start_time = time.time()86 87 # Пытаемся использовать трансформеры, если доступны88 if transformers_available:89 try:90 classifier = pipeline("zero-shot-classification", 91 model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli",92 device=-1)93 94 results = classifier(95 text, 96 candidate_labels=PREDEFINED_TOPICS,97 multi_label=False98 )99 100 labels = results['labels']101 scores = results['scores']102 103 except Exception as model_error:104 # Если не получилось с трансформерами, используем простой классификатор105 print(f"Model error: {model_error}, using simple classifier")106 scores = simple_classifier(text, PREDEFINED_TOPICS)107 labels = PREDEFINED_TOPICS108 else:109 # Если трансформеры не установлены110 scores = simple_classifier(text, PREDEFINED_TOPICS)111 labels = PREDEFINED_TOPICS112 113 elapsed_time = time.time() - start_time114 115 # Сортируем результаты116 if isinstance(scores, list):117 sorted_indices = np.argsort(scores)[::-1][:show_top_n]118 else:119 # Если scores уже numpy array120 sorted_indices = scores.argsort()[::-1][:show_top_n]121 122 # Форматируем результаты123 output_text = f"📊 **Тематическая классификация:**\n\n"124 125 for i, idx in enumerate(sorted_indices, 1):126 topic = labels[idx]127 score = scores[idx] * 100128 description = TOPIC_DESCRIPTIONS.get(topic, topic)129 130 # Прогресс-бар131 bar_length = 20132 filled = int(score * bar_length / 100)133 progress_bar = "█" * filled + "░" * (bar_length - filled)134 135 output_text += f"{i}. **{description}** - {score:.1f}%\n"136 output_text += f" {progress_bar}\n\n"137 138 output_text += f"\n⏱️ **Время обработки:** {elapsed_time:.2f} секунд"139 140 # Сохраняем в историю141 timestamp = datetime.now().strftime("%H:%M:%S")142 top_topic = labels[sorted_indices[0]]143 history.insert(0, {144 'time': timestamp,145 'text': text[:50] + ("..." if len(text) > 50 else ""),146 'topic': TOPIC_DESCRIPTIONS.get(top_topic, top_topic),147 'confidence': f"{scores[sorted_indices[0]]*100:.1f}%"148 })149 150 # Ограничиваем историю151 if len(history) > MAX_HISTORY:152 history.pop()153 154 # Создаём DataFrame для таблицы155 df = pd.DataFrame(history)156 157 return output_text, f"✅ Текст успешно обработан за {elapsed_time:.2f} сек", df158 159 except Exception as e:160 return f"❌ **Ошибка:** {str(e)}", "", []161 162def clear_history():163 """Очищает историю запросов"""164 global history165 history = []166 return pd.DataFrame()167 168# Создаём интерфейс169with gr.Blocks(title="Тематический классификатор текста", theme=gr.themes.Soft()) as demo:170 gr.Markdown("# 🏷️ Тематический классификатор текста")171 gr.Markdown("Определяет основную тему текста: спорт, политика, наука, технологии и другие")172 173 with gr.Row():174 with gr.Column(scale=2):175 # Входные элементы176 text_input = gr.Textbox(177 label="📝 Введите текст для анализа",178 placeholder="Например: 'Сегодня на матче сборная России победила со счётом 3:1...'",179 lines=5,180 max_lines=10181 )182 183 with gr.Row():184 top_n_slider = gr.Slider(185 minimum=1,186 maximum=5,187 value=3,188 step=1,189 label="🔢 Количество топ-тем для показа"190 )191 192 analyze_btn = gr.Button("🚀 Определить тему", variant="primary", size="lg")193 clear_btn = gr.Button("🧹 Очистить историю", variant="secondary")194 195 # Примеры для ТЕМАТИЧЕСКОЙ классификации196 gr.Markdown("### 📌 Готовые примеры")197 examples = gr.Examples(198 examples=[199 ["Сегодня на стадионе «Лужники» прошёл финальный матч чемпионата России по футболу. Команда «Спартак» одержала победу со счётом 2:1 над ЦСКА."],200 ["Парламент принял новый закон о цифровой экономике, который регулирует использование криптовалют и блокчейн-технологий."],201 ["Учёные из МГУ открыли новый метод лечения рака с помощью наночастиц. Клинические испытания показали эффективность в 85% случаев."],202 ["Компания Apple представила новый iPhone с революционной камерой и процессором собственной разработки. Продажи начнутся с следующей недели."],203 ["Врачи рекомендуют увеличить потребление овощей и фруктов для профилактики сердечно-сосудистых заболеваний. Исследования подтвердили снижение риска на 30%."],204 ["Министерство образования анонсировало реформу ЕГЭ. Изменения коснутся формата экзаменов по математике и русскому языку."],205 ["В Эрмитаже открылась выставка французских импрессионистов. В экспозиции представлены работы Моне, Ренуара и Дега."]206 ],207 inputs=text_input,208 label="Кликните на любой пример"209 )210 211 with gr.Column(scale=3):212 # Результаты213 output_md = gr.Markdown(label="📊 Результаты классификации")214 status_text = gr.Textbox(label="✅ Статус", interactive=False)215 216 gr.Markdown("### 📋 История запросов")217 history_table = gr.Dataframe(218 headers=["Время", "Текст", "Тема", "Уверенность"],219 datatype=["str", "str", "str", "str"],220 interactive=False,221 )222 223 # Обработчики событий224 analyze_btn.click(225 fn=classify_topic,226 inputs=[text_input, top_n_slider],227 outputs=[output_md, status_text, history_table]228 )229 230 clear_btn.click(231 fn=clear_history,232 inputs=[],233 outputs=[history_table]234 )235 236 # Информационный блок237 gr.Markdown("---")238 with gr.Accordion("📚 Подробная информация о модели", open=False):239 gr.Markdown("""240 **Используемая модель:** `MoritzLaurer/mDeBERTa-v3-base-mnli-xnli`241 242 **Почему эта модель:**243 - **Лёгкая** (300 МБ вместо 1.6 ГБ)244 - **Мультиязычная** с хорошей поддержкой русского245 - **Быстро загружается** на бесплатном CPU246 247 **Определяемые темы:**248 - 🏀 **Спорт** - спортивные события, соревнования, команды249 - 🏛️ **Политика** - политические новости, выборы, законы250 - 🔬 **Наука** - научные открытия, исследования251 - 💻 **Технологии** - IT, гаджеты, программы252 - 🏥 **Здоровье** - медицина, лечение, здоровье253 - 📚 **Образование** - обучение, экзамены, школы254 - 🎭 **Культура** - искусство, музыка, кино255 - 💰 **Экономика** - финансы, бизнес, рынки256 - ✈️ **Путешествия** - туризм, страны257 - 🎬 **Развлечения** - фильмы, игры, шоу258 - ☀️ **Погода** - климат, температура259 - 🚨 **Происшествия** - аварии, криминал260 261 **Технические детали:**262 - Модель на основе DeBERTa-v3263 - Поддерживает 12 предопределённых тем264 - Работает на CPU за 1-3 секунды265 - Поддерживает тексты до 2000 символов266 """)267 268 gr.Markdown("---")269 gr.Markdown("""270 ### ⚠️ Ограничения и примечания271 1. Максимальная длина текста: **2000 символов**272 2. Поддерживает русский и английский языки273 3. Может определять только одну основную тему274 4. Для сложных текстов может потребоваться ручная проверка275 5. Точность: ~70-80% на новостных текстах276 """)277 278if __name__ == "__main__":279 demo.launch(debug=False)