Мой блог
Как я убирал ИИ-маркеры из текстов Claude: три слоя защиты для Telegram-бота
Подробности изложены в материале первоисточника. Качественные языковые модели пишут грамотно, но их тексты мгновенно выдают себя шаблонными оборотами, длинными тире и навязчивыми антитезами. Я столкнулся с этой проблемой при разработке Telegram-бота для генерации контента, который превращает мои голосовые сообщения в готовые сценарии для соцсетей, и успешно решил её с помощью трехуровневой системы фильтрации.
В этом материале я подробно разберу архитектуру собственного пайплайна, объясню ограничения промптов и покажу, почему программные фильтры оказываются надежнее любых текстовых инструкций для ИИ.
Как устроен мой контент-бот
Мой персональный ассистент создан для того, чтобы избавить меня от рутинного набора текстов. Я просто наговариваю ключевую мысль голосом, выбираю нужный формат (например, сторис-сценарий, пост или карусель), а бот возвращает готовый материал, адаптированный под мой авторский стиль. В самом низу сообщения всегда формируется компактный блок с заданием для монтажеров и контент-менеджеров, содержащий тему, дедлайн и чек-лист действий.
Проект построен на современном стеке: в качестве основы используется Python 3.11 и асинхронный фреймворк aiogram 3. За распознавание речи отвечает модель Whisper через API Groq, а генерацией текстов занимаются продвинутые версии Claude Sonnet и Claude Haiku. Вся история генераций сохраняется локально в базе данных SQLite на Docker-томе, а деплой автоматизирован через Coolify на VPS.
Пайплайн: от голосового до готового текста
Обработка входящих данных начинается с получения файла. Бот принимает голосовые сообщения, видеофайлы, кружочки и аудиозаписи, скачивая их целиком в операционную память без создания промежуточных файлов на диске. Модуль распознавания речи отрабатывает быстро, используя модель whisper-large-v3-turbo с привязкой к русской локализации. Имя файла подбирается динамически в зависимости от типа входящего контента.
Если пользователь отправляет текстовую ссылку, бот предварительно выкачивает веб-страницу с помощью httpx и извлекает из неё чистый текст через BeautifulSoup. Полученные данные фиксируются в системе состояний FSM. Сам диалог выстроен через конечный автомат, где для каждого контентного формата предусмотрены отдельные шаги ввода, настройки параметров и бесконечный цикл правок.
Сборка промптов и вызов Claude
Все инструкции для нейросети хранятся в отдельном конфигурационном файле. Каждый запрос собирается динамически и включает в себя подробный контекст автора, описание конкретной задачи и строгие правила против искусственных маркеров на самом конце. Размещение запретов в конце промпта оказалось наиболее эффективным решением: модель гораздо лучше следует тем инструкциям, которые находятся ближе к самому тексту генерации.
Для оптимизации расходов и ускорения работы я активно использую системный кэш через параметр cache_control, так как базовый контекст весит несколько тысяч токенов. Температуру генерации я настраиваю индивидуально в зависимости от этапа: для создания структуры задается значение 0.7, для правок используется 0.3, а для чистки текста — 0.2. Готовый ответ аккуратно нарезается на фрагменты, чтобы не превышать лимиты Telegram.
Главная проблема: как распознать ИИ-маркеры
Первые версии сгенерированных текстов выглядели безупречно, однако любой опытный пользователь соцсетей легко считывал в них машинный почерк. Основные маркеры искусственного интеллекта можно разделить на три большие категории:
- Длинные тире, расставленные в местах, где живой автор поставил бы классическую запятую или точку.
- Характерные антитезы вроде «это не X, а Y» или «дело не в X, а в Y».
- Заученные клише вроде «важно понимать» или «стоит отметить», а также утяжеленные ритмические конструкции.
Слой 1: строгие правила в промпте
Изначально я попытался решить проблему «в лоб», добавив подробный чек-лист с примерами хорошего и плохого текста прямо в системный промпт. Однако выяснилось, что при наличии десятка различных путей генерации модель быстро забывает о запретах, особенно в длинных сценариях, где инструкция оказывается далеко от зоны вывода.
Тогда я вынес базовое правило в отдельную константу, которая автоматически прикрепляется к каждому запросу. Это улучшило ситуацию, но полностью избавиться от неестественных конструкций на больших объемах текста так и не удалось.
Слой 2: второй проход нейросети-чистильщика
На втором этапе я настроил отдельный вызов той же языковой модели, но уже в роли специализированного редактора. Текст отправлялся на повторную обработку с минимальной температурой и жестким указанием исправить стилистику, сохранив исходную разметку, эмодзи и заголовки.
Этот подход помог отсечь большинство сложных антитез, однако проблема с длинными тире осталась актуальной. Языковые модели оперируют токенами, поэтому абстрактная просьба убрать определенные символы воспринимается ими как рекомендация, которую они периодически игнорируют.
Слой 3: детерминированный фильтр на регулярных выражениях
Осознав, что текстовые инструкции не дают стопроцентной гарантии, я перенес проверку на уровень программного кода. Все вариации тире и минусов теперь отсекаются с помощью предварительно скомпилированного регулярного выражения, которое мгновенно заменяет их на стандартный дефис.
Для борьбы с антитезами был написан специальный детектор, который ищет паттерны внутри предложений и запускает прицельную попытку переписать сомнительный фрагмент. Если алгоритм находит потенциальную ошибку, он отправляет текст на единственную повторную доработку, исключая бесконечную трату токенов и ложные срабатывания.
Архитектура хранения данных и развертывание
Для хранения истории генераций вполне хватает возможностей встроенной базы данных SQLite. Взаимодействие с ней реализовано через стандартный синхронный драйвер с выносом операций в асинхронные потоки, что позволяет не блокировать основной цикл приложения. Доступ к боту надежно защищен middleware с проверкой списков разрешенных идентификаторов.
Процесс депонирования через Coolify имеет свою специфику: в Dockerfile предусмотрена обязательная пауза перед запуском основного скрипта. Это необходимо для того, чтобы старый и новый контейнеры не конфликтовали друг с другом при одновременном обращении к Telegram API за обновлениями.
Итоги и полезные выводы
Разработанная схема из трех уровней защиты доказала свою исключительную надежность в реальных условиях. Если бы я проектировал систему заново, то начал бы сразу с детерминированного программного фильтра, оставив нейросети только творческие задачи.
