- BrainTools - https://www.braintools.ru -
«…Давайте я сделаю, на моих токенах потестите…»
Я разработчик из Минска (работаю официально, в статусе НПД). Занимаюсь автоматизацией на связке Self‑Hosted n8n + Redis. Внедряю автономных ИИ‑агентов для мессенджеров и связываю их с amoCRM.
Дисклеймер: в статье упоминается Meta: организация признана террористической и запрещена в РФ)
Поделюсь, как говорится, «мясом» из своей практики. В статье я максимально постараюсь отразить и технический абсурд, плавно переходящий в явное кидалово от инфомошенников.
Во‑первых — это не хейт и не попытка кого‑то «разоблачить». Ленты мессенджеров завалены рекламой от «ИИ‑агентств» и «продавцов успешного‑успеха», которые рекламируют услугу под ключ «…ваш цифровой сотрудник за пару дней…». Данный разбор — это попытка показать (а может кому‑то и знакомо), что скрывается за шаблонными промо‑роликами и почему доверить реальный проект таким «спецам» обойдётся дорого.
Во‑вторых — все упоминания брендов и платформ в статье — не реклама и не антиреклама. Названия систем я оставил исключительно ради сохранения контекста, и реального отражения примера.
История статьи началась, наверное, можно сказать, в 2 этапа. Сначала — в марте этого года — ко мне обратился заказчик с интересным ТЗ: стек Нельзяграмм+ amoCRM + Google Sheets при плотном трафике до 5000 диалогов в месяц (таргет что тогда, что по сей день заходит «на ура»). Заказчиками были две сестры — у них семейный бренд, ателье дизайнерских украшений. До обращения ко мне они своими силами опробовали готовые платформы ботов, где платишь за подписку и выбираешь пакет услуг в зависимости от трафика. В итоге судя по первому дню триала, их расходы по самым средним подсчётам составили бы около 1100$ в месяц(!). Поскольку моя статья не о том, какая архитектура была у них развёрнута, пойдём дальше.
На втором этапе истории, пару недель назад, мне попадается в ленте мегакрутое, а главное, «заманчивое», по меркам бизнеса, предложение из таргета: креатив глаголит «…АИ‑ассистенты любой сложности задач за 2–3 дня…» Хм… естественно, я перешёл в профиль (красивые посты, рилсы с «экспертным» разбором болей бизнеса и их решением, и к тому же недельные курсы по тому, как решать эти боли [1]), и незамедлительно написал в директ, без долгих «здрасьте и тому подобное»: решил прогнать «подрядчика» по реальному ТЗ моего действующего клиента, о котором я написал ранее. Ответ последовал через пару минут.
Наверное, первое, что подумает большинство обычных бизнесменов, получив такой сочный и незамедлительный ответ: «Во как! Вот это сервис — сразу решение и сумма, которая стоит как треть бюджета таргета! Да ещё и оплачивать могут сами. Беру!» Но знающий человек поймёт, что цену озвучили просто за модное слово «нейросеть», и по схеме залётного рилса хук‑боль‑решение. Далее диалог набирает более интересный оборот — включаю немного инженерии и спрашиваю про склейку сообщений. «Подрядчик» тут же интересуется: «Ваш бизнес в Беларуси?». О‑па… К чему был этот вопрос — я, если честно, могу только предполагать, вариантов навскидку хватает.
Я не стал уточнять, к чему был вопрос про локацию бизнеса (кстати, далее эта тема никак и не развивалась — к чему спрашивать было?!). Возвращаю диалог в техническое русло и описываю реальную проблему: в прошлом проекте облачный Make/Integrow (назвал первый попавшийся в поиске конструктор ботов) постоянно дропал Нельзяграм‑вебхуки, когда клиенты слали по три сообщения подряд. Бот тупо дублировал ответы и списывал токены за каждое сообщение клиента. Спрашиваю как решается такой момент и от чего зависит данное решение — от LLM выбранной или от чего? Упоминаю что мол слышал про «какие‑то Claude и n8n»… В общем, по максимуму «переключаюсь» в роль бизнесмена, который интересуется технологией, но особо не в курсе деталей.
Последующее «пояснение» моего оппонента в данном диалоге, мягко говоря, вызвало у меня контраст эмоций [2] — я не сдержался и начал смеяться.
«…Про сообщения входящие в ***bot норм решение ставить задержку 15 сек например, можно больше и тогда успевают собраться сообщения…»
В голове у меня включается рубрика NO COMМENTS. Ирония здесь даже не в том, что подрядчик, на мой взгляд, явно навязывает решение, в котором есть скрытая реклама платформы, на которой он «разрабатывает цифровых сотрудников», а в том, что человек явно никогда не работал с n8n, но точно знает, что он «затупит».
В чем реальная проблема такого подхода? Таймаут — это не debounce! В конце статьи я наглядно покажу, как решается проблема, когда в диалоге юзер пишет одно сообщение в несколько коротких (… привет — а можно — узнать стоимость‑?…). Пока продолжу демонстрацию этого общения до его логического конца.
Погасив эмоции [3], вызванные ответом ранее, я дожимаю тему. Пишу, что знаю примеры, когда владельцы бизнеса уже обжигались на ***Sender (опять же, как и ранее, назвал первый попавшийся в поиске конструктор) с аналогичной задержкой. Три сообщения подряд вызывали три параллельных потока, тройной счет за LLM и «кашу» в диалоге. Спрашиваю уже прямо, как говориться «в лоб», держу марку дотошного заказчика: «Как система защищена от Race Condition? »
Следующий ответ мне последовал через минут 30, что было не характерно для данного диалога — прошлые ответы приходили в течение пары минут. Уровень моего интереса [4] начал возрастать, скажу я вам. В голове прокрутилось уйма сценариев ожидаемого ответа — без пафоса говорю, реально интрига набирала обороты!) И…наконец‑то долгожданный ответ:
На этом моменте я понял, что продолжать диалог и устраивать расспрос «подрядчика» нет никакого смысла. Также сыграло роль и то, что после долгого ожидания ответа, когда в голове я прокрутил много вариантов ответа, я увидел вполне логичное и «рабочее» решение. Хотя, с одной стороны, подрядчик честно не стал писать что‑то в духе «втюхивания успешного успеха» и тому подобное, а прямо предложил свой «триал», а подойдёт или нет — решите потом. С другой стороны данный ответ — попытка замаскировать отсутствие архитектуры «щедростью на токенах». Реальность — это систему не спасет от падения.
Я вежливо и сдержано написал, что нам нужно бронебойное решение, которое не ляжет в первую же распродажу.
Давайте включим калькулятор и посчитаем реальную экономику этого «бизнес — решения за $500». Подрядчик уверенно заявил в смете: «50$ токены Claude». В ТЗ указано было, что в месяц объём около 5000 диалогов. Зафиксировали. Теперь банально, строго для наглядности, скриншот из Open Router с ценой на самую дешёвую модель из линейки Anthropic — Claude 3 Haiku, чтобы расчёт был минимальным…
.. и на самую дорогую (применяемую для общения в директ) модель — чтобы расчёт был максимальным:
Считать расходы на токены каждый может по‑своему, и цифры конечно же будут разные. Предполагаю все знают, что на платформах — конструкторах цены на API со значительной накруткой. В данном примере мне не было сказано какая модель будет применяться в принципе.
В нормальной разработке, и тем более, на платформах‑конструкторах, никакой фиксированной абонентки в 50 баксов (как и любой другой суммы) за нейронку быть не может в принципе! Всё должно работать прозрачно: сколько по факту «наговорил» напрямую у провайдера — столько и оплатил (это называется система Pay‑as‑you‑go). А фикса в смете — это либо вас пытаются развести, либо «цифровой сотрудник» тупо заблокируется посреди месяца, когда кончатся лимиты. Зачем вообще гадать, впишется no‑code в лимиты или нет?! Систему надо сразу строить нормально, которая экономит деньги при любом сценарии.
А теперь я отложу в сторону чужие no‑code “решения и разработки” и разберу, как debounce — механизм может быть реализован, чтобы экономить на токенах и не «плодить кашу» в директе. Сразу обозначу: это сугубо пример моего решения в n8n для наглядности, а не самореклама! Постараюсь вкратце и без лишней «воды», чтобы не превращать статью в том «Война и мир».
Если описать моё решение в одном предложении — это использование дебоунса как временной буфер‑накопитель с блокировкой по флагу.
Юзер пишет дробно в течении 10–15 секунд — для наглядности реальный скриншот переписки ниже:
Когда приходит первое сообщение (как на скриншоте «здравствуйте! Хочу персональный») мы не бежим дергать LLM. Мы начинаем строить пошаговый механизм:
1) Прием сообщения и буферизация: Нода Redis 1 (я их буду нумеровать) выполняет атомарную операцию LPUSH/ RPUSH, мгновенно сохраняя сырые данные в Redis‑список; Ключ структуры данных: ig_buf:{userId}; Payload: JSON‑объект, содержащий chatId, text сообщения и временную метку ts;
2) Проверка флага блокировки: Нода Redis: выполняет операцию GET для проверки существования распределенной блокировки по ключу флага ig_debounce:{userId}
3) Ветвление потоков: Нода IF проверяет состояние полученного ключа:
а) Ключ существует (Флаг активен): Текущая сессия вебхука классифицируется как повторный сетевой запрос (retry от серверов Meta) либо как быстрое досылаемое сообщение от юзера (как последующие сообщения «браслет — дата рождения 10.10.1990» на скриншоте выше). Поток сбрасывается. При этом новые данные уже сохранены в буфере List (Шаг 1), а тот самый Race Condition (про который я так дотошно расспрашивал «подрядчика» в переписке ранее) на уровне ИИ‑обработки полностью исключается!
б) Ключ отсутствует (Первичное сообщение): Данное сообщение уже признается инициатором новой диалоговой сессии после паузы, и, следовательно, идёт далее по контуру воркфлоу.
4) Выставление флага блокировки (Lock): Поток, успешно прошедший «проверку» в ноде IF, вызывает ноду Redis 3 (операция SET с флагами блокировки). В Redis создается ключ ig_debounce:{userId} со значением «1» и жестким TTL = 15 секунд.
5) Аккумуляция фрагментов (Временное окно «тишины»): Основной поток переходит в состояние ожидания на ноде Wait ровно на 15 секунд. Внутри этого «ожидания» — параллельные входящие сообщения от того же userId беспрепятственно стекаются в буферig_buf:{userId} (Шаг 1). Избыточные дублирующие вебхуки жестко отсекаются на Шаге 3, предотвращая спам‑генерацию ноды ИИ агента.
6) Опустошение буфера и склейка текста: По истечении 15 секунд нода Wait активируется. Нода Redis 1 с помощью пакетной операции (или последовательных POP) извлекает весь накопленный массив сообщений из списка. Данные передаются в JS‑ноду Combine All Text для склейки и защиты от дублей текста (если к примеру юзер напишет два раза «привет»), а затем направляются в ноду «мозговой обработки» — ИИ агенту.
7) Автоматический сброс сессионного флага: По окончании 15 секунд база данных Redis автоматически уничтожает ключ ig_debounce:{userId} по механизму TTL (времени жизни ключа). Воркфлоу полностью возвращается в исходное состояние и готов к открытию следующего окна агрегации для данного пользователя. Проще говоря, все последующие сообщения уже будут восприниматься как новый поток данных.
Чтобы не быть голословным, а также показать «внутреннюю кухню» всего вышеперечисленного механизма, прикрепляю скриншот не просто воркфлоу, а именно аутпута ноды Redis: Get Final Prompt. На нём отлично видно, как все дробные сообщения склеились в один связанный поток перед отправкой к ИИ‑агенту:
No‑code платформы, с которых начиналась моя статья — это хорошее решение для простых ИИ ‑ботов и воронок «вопрос‑ответ», собранных за один — два дня. И это реально удобное решение, когда нет связки с CRM, сложных действий (заполнение кастомных полей и перемещение по этапам сделки, и тому подобное) и особенно, когда клиенту нужно было сделать всё «ещё вчера».
Но когда их пытаются навязать под Enterprise нагрузку с глубокой интеграцией (как в ТЗ в начале статьи) — они превращаются в скрытый налог на бюджет клиента из‑за переплаты за лишние токены. Грамотная архитектура экономит деньги в любом сценарии.
В этой публикации я постарался максимально просто разобрать только логику [5] дебаунса. Но на реальном трафике всплывает множество проблем куда более «опасных» и коварных для разработчика. Пример — потеря вебхуков со стороны Meta. После обновления протоколов Conversation Routing в этом году, реальный практический стандарт потерь для кастомных приложений (n8n и пр.) составляет от 7% до 30% в пиковые часы. Это неизбежно ведет к дублированию сделок в CRM, либо отсутствию ответа юзеру в директ так как в воркфлоу не приходит вебхук вообще(!).
Для решения этой проблемы применяется механика двухсторонней привязки, которая намертво связывает chatId из Instagram и leadId в amoCRM через, мною любимые, быстрые Redis‑ключи. О том, как эта связка спасает систему от гонки данных при массовом таргете и капризах API Meta, подробно с кодом и главное со скриншотами из реального продакшена, я напишу в следующей статье.
Всем добра! Надеюсь, моя статья пройдёт модерацию, и я смогу продолжить делиться своими фичами и реальными кейсами! P.S. буду рад комментариям и обсуждениям!)
Автор: gotham_engineer
Источник [7]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/34542
URLs in this post:
[1] боли: http://www.braintools.ru/article/9901
[2] эмоций: http://www.braintools.ru/article/9540
[3] эмоции: http://www.braintools.ru/article/9387
[4] интереса: http://www.braintools.ru/article/4220
[5] логику: http://www.braintools.ru/article/7640
[6] внимание: http://www.braintools.ru/article/7595
[7] Источник: https://habr.com/ru/articles/1071580/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1071580
Нажмите здесь для печати.