Классификация текстов

Классификация отвечает на вопросы «о чём это сообщение, насколько серьёзно, какая эмоция, чего хочет автор». Устроена как воронка из трёх слоёв — от мгновенных правил до LLM — где дорогая модель подключается только там, где дешёвые правила не уверены.

Три слоя — почему не один

СлойЧто это
1. Regex (Tier-1)чистые правила, <1 мс на CPU, без сети/GPU. 11 категорий события + 4 уровня важности
2. NER keywordбыстрый словарный классификатор внутри NER-сервиса. 9 категорий, в т.ч. service_request
3. LLMуточняет категорию/важность/тональность по строгой JSON-схеме — только на спорных
Почему такБольшинство сообщений уверенно классифицируются правилами за доли миллисекунды. LLM дорогой и медленный — звать его на каждый материал нельзя. Поэтому regex решает сам, если уверен (≥ порога), и эскалирует в LLM только при низкой уверенности. Это экономит GPU на потоке, не теряя качества на сложных случаях.

Категории события

Слой 1 раскладывает материал по 11 рубрикам — каждое правило со своей уверенностью; побеждает рубрика с максимальной суммой совпадений:

military · disaster · utility · transport · crime · protest · political · economic · ecology · cultural · other

При создании инцидента рубрика переводится в один из 14 типов витрины: transport→ДТП, disaster→пожар, utility→отключение воды, military→дрон, crime→преступление и т.д.

Важность (severity)

Сквозной стандарт во всех слоях — ровно 4 уровня: low · medium · high · critical. Базовый уровень берётся от категории (пожар/военное → high, политика/митинг → low) и повышается словами-маркерами (погиб/смерть/жертвы → critical).

Почему такcritical отделён от highспециально — под смерти, теракты, массовые жертвы (эскалация и алерты идут именно по нему). Приоритетный выбор critical>high>medium>low гарантирует, что самый опасный сигнал не потеряется. Базовый уровень по категории даёт разумный дефолт даже без явных слов: пожар без слова «жертвы» всё равно high, а не low.

Тональность

Три класса: positive · neutral · negative. Считается как (позитив − негатив) / всего в диапазоне [−1, 1]; зона neutralвокруг нуля — буфер против шумных срабатываний на единичных эмоциональных словах.

Намерение и сигналы

Помимо «о чём» система ловит «чего хочет автор». Ключевой кейс — сделки с недвижимостью:

СигналЧто это
deal_intent (сделка)продажа / аренда / торги / банкротство / расселение / снос / переуступка / другое / none (9 типов)
lead (услуга)сантехник / электрик / клининг / ремонт / муж-на-час / другое (заявка из чата района)
geo_eventтип городского/геополитического события
topic, sentiment, toxicity, hate_speech…16 типов в реестре content_signal

Сделки и услуги распознаются гибридом: дешёвый regex-гейт (recall-favoring — пускает дальше всё, где есть признаки сделки) → LLM-подтверждение со строгой схемой. Цена, адрес и телефон достаются детерминированно регулярками, не моделью.

Почему такСделки детектятся до гео/тематического фильтра: объявления о продаже часто не проходят фильтр городских новостей, но это именно лиды по недвижимости — северная звезда продукта. Стой детект после фильтра — сделки терялись бы вместе с отсеянным шумом.

Словари (лексиконы) — чем всё управляется

Все списки слов и regex-правила вынесены из кода в БД (таблица lexicons) и редактируются из админки /admin/data → Словари. 10 видов:

Вид словаряЧто это
geo_toponymгео-маркеры (Ростов…) — считают «гео-релевантность»
topic_keywordтемы: инфраструктура/происшествие/ЖКХ/политика/экология/сообщество/соцпомощь
sentiment_positive / negativeсловарь тональности
deal_intentregex-гейт сделок (фрагменты склеиваются в один паттерн)
event_rule / severity_ruleregex-правила типа события и важности (с уверенностью)
hate_pattern / toxic_pattern / geopoliticalправила для флага hate-speech, токсичности, геополитики
Почему такСловари меняются часто и должны правиться без релиза. При этом пустая таблица не ломает воронку — каждый запрос падает на фолбэк к константам в коде (тем же самым, не копии — чтобы не было дрейфа). Редактирование живое (кэш сбрасывается при сохранении).
Честная оговоркаНесколько честных нюансов: (1) наборы категорий у слоёв немного расходятся (transportв regex против traffic в LLM) — следствие независимой эволюции; рассинхрон ловится флагами. (2) Вербовка и тревожный контент пока существуют только как типы тест-генератора — отдельного ML-детектора ещё нет. (3) Спам отсекается простым списком ключевых слов на уровне парсера, до триажа.