Пять технических граблей на пути к AI-агрегатору Telegram-каналов
Разработчик-одиночка создаёт приложение, которое собирает публикации из тематических Telegram-каналов, фильтрует дубли и шум с помощью AI-классификации и формирует короткий аудиодайджест. В процессе реализации он столкнулся с пятью неочевидными проблемами, которые серьёзно повлияли на архитектуру и экономику проекта.
Разработка ведётся одним человеком, и в её основе лежит идея превратить разрозненные публикации из Telegram-каналов в структурированный аудиодайджест. Для этого приложение собирает сообщения по заданным темам, удаляет повторы и информационный шум с помощью AI-классификации, а затем синтезирует речь. Однако путь от замысла до работающего продукта оказался сопряжён с рядом технических ограничений, которые автор подробно разобрал в своём отчёте. Пять ключевых «грабель» касаются доступа к данным, тарифных лимитов, дедупликации, затрат на озвучку и мониторинга статусов. Показательно, что ни одна из них не связана с качеством самой AI-модели — все ограничения лежат в инфраструктурном и экономическом слое, что делает этот опыт особенно ценным для небольших команд, строящих похожие сервисы на внешних зависимостях.
Первая проблема связана с отсутствием прямого доступа к Telegram API для чтения произвольных публичных каналов. Официальный API предназначен для ботов, а не для мониторинга чужих каналов, поэтому разработчик использовал сторонний бесплатный сервис, преобразующий публичный канал в RSS-ленту. Этот сервис имеет неофициальный лимит: примерно 13–15 запросов подряд в течение нескольких минут, после чего он отвечает ошибкой 429 и восстанавливается дольше, чем заявлено в документации. Фактически этот лимит стал определяющим для архитектуры: пауза между темами внутри пайплайна составляет 75 секунд, а полный цикл сбора по 12 темам занимает около 40–45 минут. Внешняя зависимость без SLA и официальной документации превратилась в жёсткое ограничение скорости всего продукта, и именно этот параметр, а не возможности AI-моделей, задаёт верхнюю границу частоты обновления дайджеста.
Вторая грабля касается экономики запусков. Используемый сервис автоматизации на базовом тарифе имеет лимит в 2500 запусков в месяц и не более 5 одновременных запусков. Изначально каждая из 12 тем имела собственное расписание, что при учащении до ежечасного умножало число засчитываемых запусков в 12 раз и выводило за пределы тарифа. Решением стала единая точка входа — «Оркестратор», который последовательно вызывает все темы изнутри себя. Внутренние вызовы не учитываются в лимите, считается только срабатывание самого Оркестратора. Это решение продиктовано исключительно тарифной моделью, а не архитектурной эстетикой: при другой схеме оплаты, вероятно, была бы выбрана параллельная схема с независимыми расписаниями. Показательно, что этот же переход к строгой последовательности позже неожиданно решил и другую проблему — с кэшем озвучки.
Третья проблема — дедупликация, которая изначально не работала. В пайплайне использовались два идентификатора: external_id (детерминированный хэш от ссылки на пост и даты) и cluster_id (хэш от точного текста описания, первые 200 символов). Проверка на 1003 записях за 14 дней показала 1002 уникальных cluster_id, то есть механизм кросс-канальной кластеризации практически никогда не срабатывал. Разные каналы описывают одно событие разными словами, и хэш от точного текста этого не улавливает в принципе. Позже экспериментальный механизм на сравнении заголовков со стоп-листом служебных слов и стеммингом дал точность около 89%, но он пока не подключён к реальной ленте. Отдельно стоит отметить, что исходная ошибка была ещё и логической: сравнение шло между заголовком и резюме, а не между заголовками разных публикаций, что и обнуляло результат.
Четвёртая грабля — двойная оплата озвучки. Многие каналы относятся сразу к нескольким темам, и при старой архитектуре каждая тема запускала пайплайн с собственным вызовом синтеза речи. Дедупликация по external_id происходила на бэкенде уже после генерации и оплаты аудио. Подсчёт за 14 дней выявил 2275 вызовов синтеза на 1003 уникальных атома, то есть около 56% озвучки было избыточным, что давало примерно 1300 рублей в месяц экономии. Фикс — кэш «атом уже озвучен в другой теме за последние 48 часов» — заработал только после того, как прогоны тем стали строго последовательными через Оркестратор. До этого из-за параллельного запуска с пересечением по времени в 1.5–2.3 минуты кэш систематически промахивался: тема, стартовавшая на минуту позже, читала кэш раньше, чем предыдущая успевала туда записать. Ирония в том, что сам кэш не потребовал ни единой правки — его починило изменение, сделанное ради другой задачи.
Пятая грабля — ложно-зелёный статус. При учащении цикла сбора с 4 раз в сутки до раза в час сбор материалов почти полностью остановился с первого же часа. Причина — исчерпание бесплатной дневной квоты классификатора (500 запросов в сутки). При этом Оркестратор продолжал отчитываться «success» на всех прогонах, так как ошибка ловилась на уровне отдельной темы, а email-алерт был отключён после более раннего инцидента. Без ручной проверки данных полный отказ сбора остался бы незамеченным. В дальнейшем классификатор был заменён на более дешёвую модель, а также готовится переход на батчевые вызовы (около 15 материалов за раз) с предварительными гейтами по дате, external_id и кросс-канальным совпадениям, чтобы сократить число обращений к модели.
Эти пять проблем наглядно демонстрируют, что даже при наличии AI-компонентов ключевые ограничения часто лежат в области инфраструктуры, тарифов и внешних зависимостей. Для российского рынка, где многие разработчики работают с Telegram и используют зарубежные сервисы автоматизации, подобные грабли могут быть особенно болезненны из-за санкционных ограничений и нестабильности платежей: бесплатные тарифы с неофициальными лимитами становятся единственной доступной опцией, а их поведение плохо предсказуемо. Опыт автора показывает, что архитектура должна быть гибкой и учитывать не только функциональные требования, но и экономические, а также операционные риски. Открытыми остаются вопросы масштабирования при росте числа тем, отказоустойчивости при отказе стороннего моста и прозрачного мониторинга, который не сводился бы к формальному «success». Их решение потребует дальнейших итераций, и, вероятно, следующий отчёт автора будет уже о граблях масштабирования.