Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,17 +1,22 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
-
from transformers import pipeline
|
| 3 |
import time
|
| 4 |
import pandas as pd
|
| 5 |
from datetime import datetime
|
| 6 |
import numpy as np
|
| 7 |
|
| 8 |
-
#
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
|
|
|
|
|
|
| 13 |
|
| 14 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
PREDEFINED_TOPICS = [
|
| 16 |
"спорт", "политика", "наука", "технологии",
|
| 17 |
"здоровье", "образование", "культура", "экономика",
|
|
@@ -34,9 +39,36 @@ TOPIC_DESCRIPTIONS = {
|
|
| 34 |
"происшествия": "🚨 Происшествия"
|
| 35 |
}
|
| 36 |
|
| 37 |
-
#
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
def classify_topic(text, show_top_n=3):
|
| 42 |
"""Классифицирует текст по темам"""
|
|
@@ -52,25 +84,45 @@ def classify_topic(text, show_top_n=3):
|
|
| 52 |
# Измеряем время выполнения
|
| 53 |
start_time = time.time()
|
| 54 |
|
| 55 |
-
#
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
elapsed_time = time.time() - start_time
|
| 63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
# Форматируем результаты
|
| 65 |
output_text = f"📊 **Тематическая классификация:**\n\n"
|
| 66 |
|
| 67 |
-
# Получаем списки тем и оценок
|
| 68 |
-
labels = results['labels']
|
| 69 |
-
scores = results['scores']
|
| 70 |
-
|
| 71 |
-
# Сортируем по убыванию оценок и берем топ-N
|
| 72 |
-
sorted_indices = np.argsort(scores)[::-1][:show_top_n]
|
| 73 |
-
|
| 74 |
for i, idx in enumerate(sorted_indices, 1):
|
| 75 |
topic = labels[idx]
|
| 76 |
score = scores[idx] * 100
|
|
@@ -186,9 +238,12 @@ with gr.Blocks(title="Тематический классификатор тек
|
|
| 186 |
gr.Markdown("---")
|
| 187 |
with gr.Accordion("📚 Подробная информация о модели", open=False):
|
| 188 |
gr.Markdown("""
|
| 189 |
-
**Используемая модель:** `
|
| 190 |
|
| 191 |
-
**
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
**Определяемые темы:**
|
| 194 |
- 🏀 **Спорт** - спортивные события, соревнования, команды
|
|
@@ -205,9 +260,9 @@ with gr.Blocks(title="Тематический классификатор тек
|
|
| 205 |
- 🚨 **Происшествия** - аварии, криминал
|
| 206 |
|
| 207 |
**Технические детали:**
|
| 208 |
-
- Модель на основе
|
| 209 |
- Поддерживает 12 предопределённых тем
|
| 210 |
-
- Работает на CPU за
|
| 211 |
- Поддерживает тексты до 2000 символов
|
| 212 |
""")
|
| 213 |
|
|
@@ -218,7 +273,7 @@ with gr.Blocks(title="Тематический классификатор тек
|
|
| 218 |
2. Поддерживает русский и английский языки
|
| 219 |
3. Может определять только одну основную тему
|
| 220 |
4. Для сложных текстов может потребоваться ручная проверка
|
| 221 |
-
5. Точность: ~
|
| 222 |
""")
|
| 223 |
|
| 224 |
if __name__ == "__main__":
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
| 2 |
import time
|
| 3 |
import pandas as pd
|
| 4 |
from datetime import datetime
|
| 5 |
import numpy as np
|
| 6 |
|
| 7 |
+
# Импортируем transformers с обработкой ошибок
|
| 8 |
+
try:
|
| 9 |
+
from transformers import pipeline
|
| 10 |
+
transformers_available = True
|
| 11 |
+
except ImportError:
|
| 12 |
+
transformers_available = False
|
| 13 |
+
print("Transformers not available, using mock mode")
|
| 14 |
|
| 15 |
+
# История запросов
|
| 16 |
+
history = []
|
| 17 |
+
MAX_HISTORY = 10
|
| 18 |
+
|
| 19 |
+
# Предопределённые темы для классификации
|
| 20 |
PREDEFINED_TOPICS = [
|
| 21 |
"спорт", "политика", "наука", "технологии",
|
| 22 |
"здоровье", "образование", "культура", "экономика",
|
|
|
|
| 39 |
"происшествия": "🚨 Происшествия"
|
| 40 |
}
|
| 41 |
|
| 42 |
+
# Простая эвристическая классификация (запасной вариант)
|
| 43 |
+
def 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 = 0
|
| 66 |
+
for keyword in keywords.get(topic, []):
|
| 67 |
+
if keyword in text_lower:
|
| 68 |
+
score += 1
|
| 69 |
+
scores.append(score / max(len(keywords.get(topic, [])), 1))
|
| 70 |
+
|
| 71 |
+
return scores
|
| 72 |
|
| 73 |
def classify_topic(text, show_top_n=3):
|
| 74 |
"""Классифицирует текст по темам"""
|
|
|
|
| 84 |
# Измеряем время выполнения
|
| 85 |
start_time = time.time()
|
| 86 |
|
| 87 |
+
# Пытаемся использовать трансформеры, если доступны
|
| 88 |
+
if transformers_available:
|
| 89 |
+
try:
|
| 90 |
+
# ПРОБУЕМ ЛЁГКУЮ МОДЕЛЬ ДЛЯ РУССКОГО ЯЗЫКА
|
| 91 |
+
classifier = pipeline("zero-shot-classification",
|
| 92 |
+
model="MoritzLaurer/mDeBERTa-v3-base-mnli-xnli",
|
| 93 |
+
device=-1)
|
| 94 |
+
|
| 95 |
+
results = classifier(
|
| 96 |
+
text,
|
| 97 |
+
candidate_labels=PREDEFINED_TOPICS,
|
| 98 |
+
multi_label=False
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
labels = results['labels']
|
| 102 |
+
scores = results['scores']
|
| 103 |
+
|
| 104 |
+
except Exception as model_error:
|
| 105 |
+
# Если не получилось с трансформерами, используем простой классификатор
|
| 106 |
+
print(f"Model error: {model_error}, using simple classifier")
|
| 107 |
+
scores = simple_classifier(text, PREDEFINED_TOPICS)
|
| 108 |
+
labels = PREDEFINED_TOPICS
|
| 109 |
+
else:
|
| 110 |
+
# Если трансформеры не установлены
|
| 111 |
+
scores = simple_classifier(text, PREDEFINED_TOPICS)
|
| 112 |
+
labels = PREDEFINED_TOPICS
|
| 113 |
|
| 114 |
elapsed_time = time.time() - start_time
|
| 115 |
|
| 116 |
+
# Сортируем результаты
|
| 117 |
+
if isinstance(scores, list):
|
| 118 |
+
sorted_indices = np.argsort(scores)[::-1][:show_top_n]
|
| 119 |
+
else:
|
| 120 |
+
# Если scores уже numpy array
|
| 121 |
+
sorted_indices = scores.argsort()[::-1][:show_top_n]
|
| 122 |
+
|
| 123 |
# Форматируем результаты
|
| 124 |
output_text = f"📊 **Тематическая классификация:**\n\n"
|
| 125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
for i, idx in enumerate(sorted_indices, 1):
|
| 127 |
topic = labels[idx]
|
| 128 |
score = scores[idx] * 100
|
|
|
|
| 238 |
gr.Markdown("---")
|
| 239 |
with gr.Accordion("📚 Подробная информация о модели", open=False):
|
| 240 |
gr.Markdown("""
|
| 241 |
+
**Используемая модель:** `MoritzLaurer/mDeBERTa-v3-base-mnli-xnli`
|
| 242 |
|
| 243 |
+
**Почему эта модель:**
|
| 244 |
+
- **Лёгкая** (300 МБ вместо 1.6 ГБ)
|
| 245 |
+
- **Мультиязычная** с хорошей поддержкой русского
|
| 246 |
+
- **Быстро загружается** на бесплатном CPU
|
| 247 |
|
| 248 |
**Определяемые темы:**
|
| 249 |
- 🏀 **Спорт** - спортивные события, соревнования, команды
|
|
|
|
| 260 |
- 🚨 **Происшествия** - аварии, криминал
|
| 261 |
|
| 262 |
**Технические детали:**
|
| 263 |
+
- Модель на основе DeBERTa-v3
|
| 264 |
- Поддерживает 12 предопределённых тем
|
| 265 |
+
- Работает на CPU за 1-3 секунды
|
| 266 |
- Поддерживает тексты до 2000 символов
|
| 267 |
""")
|
| 268 |
|
|
|
|
| 273 |
2. Поддерживает русский и английский языки
|
| 274 |
3. Может определять только одну основную тему
|
| 275 |
4. Для сложных текстов может потребоваться ручная проверка
|
| 276 |
+
5. Точность: ~70-80% на новостных текстах
|
| 277 |
""")
|
| 278 |
|
| 279 |
if __name__ == "__main__":
|