Бот «Мигалка» обрабатывает 1000 каналов за секунды: LLM, векторные базы данных и PostGIS
Телеграм-бот «Мигалка» собирает сообщения примерно из тысячи телеграм-каналов и за секунды превращает их в адресные оповещения об опасности для конкретной локации пользователя, заменяя ручной мониторинг конвейером из LLM, векторной базы данных Qdrant и геокодирования через PostGIS.
Официальные предупреждения об ударах дронов и ракет часто опаздывают на часы или не приходят вовсе. Десятки телеграм-каналов сообщают быстрее, но читать их вручную невозможно: события из разных регионов смешиваются, а одно происшествие описывают десятки источников. Автоматический конвейер решает эту задачу без постоянной ручной модерации.
Разработчики бота «Мигалка» описали архитектуру системы, которая круглосуточно обрабатывает несколько сотен событий в день. Ключевая инженерная проблема: неструктурированный текст из сотен каналов нужно превратить в типизированные события с привязкой к месту, убрать дубли и доставить оповещение именно тем, кому оно релевантно. Ниже разбираю, из каких компонентов это собрано и как повторить подход.
Какие инструменты нужны для сборки?
- Telegram-скрейпер для чтения каналов и складывания постов во входящую очередь
- LLM с API (основная модель плюс резервная на случай сбоев) для извлечения структуры из текста
- Qdrant (векторные базы данных для хранения эмбеддингов, то есть числовых «отпечатков» текста, по которым ищут смысловые совпадения)
- PostgreSQL с расширением PostGIS для хранения событий, настроек пользователей и полигонов административных границ
- Redis для входящей очереди сообщений и контроля скорости отправки (чтобы не упереться в лимиты Telegram API)
- Google Maps API для геокодирования (превращения названия места в координаты и официальный адрес)
- Данные OpenStreetMap с полигонами административных границ
- Время на настройку промптов под каждую категорию опасности
Как устроен конвейер шаг за шагом?
-
Скрейпер читает каналы. Отдельный сервис забирает новые посты из примерно тысячи телеграм-каналов и кладёт их в очередь Redis.
-
LLM извлекает структуру. Каждое сообщение проходит через языковую модель, которая выполняет сразу несколько задач в одном вызове:
Задачи LLM на каждое сообщение:
- Проверить релевантность публикации выбранной теме
- Извлечь пары «регион + локация» (один пост может описывать события в нескольких городах)
- Сформулировать краткое описание для пользователя
- Проверить: событие действительно произошло в указанном месте или место лишь упомянуто в тексте
Один пост может породить несколько событий в разных местах или не породить ни одного. После этого этапа основным объектом системы становится событие, а не исходная публикация.
-
Промпты хранятся в базе. Промпты (инструкции для модели) настраиваются отдельно для каждой категории опасности и лежат в PostgreSQL. Их меняют без правки кода, поэтому добавление новой категории сводится к настройке инструкций и схемы результата.
-
Обработка сбоев LLM. Для вызовов модели предусмотрены тайм-ауты, резервная модель и повторные попытки с экспоненциальной задержкой (каждая следующая попытка ждёт дольше предыдущей). Внешний API может отвечать медленно, быть временно недоступным или вернуть результат, не соответствующий ожидаемой схеме.
-
Дедупликация через векторные базы данных. Одно событие за короткое время описывают десятки каналов. Сравнивать тексты напрямую бесполезно: «взрывы в районе промзоны» и «работа ПВО над городом» могут описывать одно и то же. Поэтому дедупликация двухуровневая:
-
Сначала эмбеддинги (числовые представления смысла текста) в Qdrant быстро отбирают потенциально похожие события по семантической близости. Дословное совпадение не требуется.
- Затем отдельно сравниваются локации: семантически одинаковые сообщения из разных городов объединять нельзя.
Найденный дубль не удаляется, а добавляется к существующему событию как дополнительный источник. Если новая публикация уточняет информацию, уже созданное оповещение обновляется.
-
Геокодирование привязывает текст к карте. LLM возвращает строку вроде «Шебекино». Дальше её нужно превратить в точку на дереве административных границ:
-
Название проходит через Google Maps API. Геокодер нормализует его и возвращает официальное название, регион, город и координаты. Если в посте написано «ТЦ Европейский», сервис поймёт, что это Москва, и определит точный адрес.
- По нормализованным данным ищется соответствующая территория среди полигонов OpenStreetMap в PostGIS. Цепочка административных уровней хранится в PostgreSQL как ltree (древовидная структура «Россия, Краснодарский край, Сочи, Центральный район»).
Сравнивать названия как строки неудобно: «Шебекино» и «Шебекинский городской округ» относятся к одной территории, а одинаковые названия встречаются в разных регионах. Дерево границ решает обе проблемы.
- Подбор получателей и доставка. Пользователь при настройке бота указывает локацию (от целого региона до района в городе) и категории опасности. Система сопоставляет дерево локации события с деревом локации пользователя и ставит оповещение в очередь доставки в PostgreSQL. Redis управляет скоростью отправки, чтобы не превысить лимиты Telegram.
Десять телеграм-каналов за три минуты публикуют сообщения о работе ПВО в Белгородской области. Формулировки разные: «громкие хлопки в районе Шебекино», «работа ПВО, Белгородская область», «над Шебекинским округом сбит дрон». Конвейер извлекает из каждого поста категорию «воздушная опасность» и локацию «Шебекино». Qdrant по эмбеддингам находит, что все десять сообщений семантически близки, PostGIS подтверждает совпадение по географии. Пользователь, подписанный на оповещения по Белгородской области, получает одно сообщение с кратким описанием и десятью источниками, а не десять одинаковых уведомлений.
Что делать с этим прямо сейчас, по ролям
Разработчику бота или сервиса оповещений. Связка LLM плюс Qdrant плюс PostGIS воспроизводима на любом потоке неструктурированных сообщений. Ключевой приём: хранить промпты в базе, а не в коде, тогда новые категории событий добавляются без деплоя.
Автору Дзена, работающему с новостным контентом. Принцип дедупликации через эмбеддинги применим для мониторинга источников: можно собирать публикации по теме и автоматически группировать похожие, чтобы не пересказывать одну и ту же новость.
Предпринимателю в РФ. Все компоненты доступны: Qdrant — опенсорс (открытая модель векторной базы данных, которую можно развернуть на своём сервере), PostgreSQL и PostGIS свободны, Redis свободен. Для LLM можно использовать как зарубежные API, так и российские модели. Google Maps API работает, но при ограничениях можно заменить на Nominatim (открытый геокодер на данных OpenStreetMap).
Нет резервной модели. Если LLM-провайдер лёг на пять минут, без фолбэка система перестаёт обрабатывать сотни постов. Обязательно настройте запасную модель и повторные попытки с экспоненциальной задержкой.
Дедупликация только по тексту. Без проверки географии система объединит «взрывы в Шебекино» и «взрывы в Курске» как один инцидент, потому что тексты семантически близки. Второй уровень с проверкой локации не опционален, а обязателен.
Один промпт на все категории. Универсальный промпт для разных типов событий (воздушная тревога, рейды, стихийные бедствия) работает заметно хуже, чем отдельный промпт под каждую категорию. Держите промпты в базе и настраивайте под задачу.
Игнорирование лимитов Telegram. Без контроля скорости отправки через Redis бот быстро упрётся в лимиты API и перестанет доставлять сообщения.
Архитектура «Мигалки» ценна не экзотическим стеком, а тем, что каждый компонент решает конкретную проблему: LLM превращает хаос в структуру, векторные базы данных (Qdrant) убирают дубли без дословного сравнения, PostGIS привязывает текст к карте. По моим наблюдениям, большинство попыток собрать подобную систему спотыкаются именно на дедупликации: без двухуровневой проверки (семантика плюс география) пользователь либо тонет в повторах, либо теряет разные события из похожих сообщений. Честная оговорка: система работает без постоянной ручной модерации, но LLM может галлюцинировать (уверенно выдумывать то, чего не было). В критичных для безопасности сценариях стоит добавить механизм, где пользователи проверяют сообщения друг друга, что авторы «Мигалки» и сделали.
Конвейер LLM плюс Qdrant плюс PostGIS с промптами в базе и двухуровневой дедупликацией уже работает на потоке в несколько сотен событий в день. Если вы строите любую систему мониторинга, от новостного агрегатора до службы оповещений, начните с этой связки: она воспроизводима на открытых компонентах и масштабируется без ручной модерации.

Основатель dzen.guru. Эксперт по монетизации и продвижению на Дзен. Автор курса «Старт на Дзен 2026».
Читайте также

Как отключить Gemini на телефоне как голосовой помощник и настроить его для быта
Google Gemini уже умеет помогать не только на работе, а и в быту: от диагностики сломанного крана до списка продуктов по содержимому холодильника, и 4 июня…

Gemini Notebook записывает лекции и делает квизы на 100 языках: гайд для студентов
Gemini Notebook получил голосовой ввод лекций, разговор с конспектами на ~100 языках и аудиозапись прямо в мобильном приложении, и всё это уже можно применить…
Визуально-языковые модели за $200: разработчик собрал VLM на 628 млн параметров на одной GPU
Разработчик из сообщества открытых моделей собрал визуально-языковую модель на базе французской Baguettotron и визуального энкодера InternViT за 200 долларов…
Комментарии