Comments 10
Нормуль разбор, слои защиты.. Но меня зацепил Слой 2 (Валидатор). Ты возвращаешь payload на ретрай во второй экземпляр агента с system_kick. Получается, при каждом таком тупике заново скармливается модели весь контекст диалога + системный промпт на 6400 токенов ради короткого ответа?7... Не думал в ветке ретрая динамически подменять системный промпт на сильно урезанную версию (чисто под Ступень 4), чтобы не переплачивать за prompt-токены на повторных генерациях? Или контекстный кэш опенроутер здесь всё равно полностью нивелирует траты на повторный прогон?
Спасибо за коммент) отличный вопрос - видно что прочитали внимательно статью)) Наверное могу сказать что прямо в корень зрите! Отвечу вкратце: я по началу думал про урезание промпта на ретрае, но тут как раз решает контекстный кэш оpenrouter, который я в таблице показывал. Поскольку базовые 6,4 к. токенов на 90% сидят в кэше, повторный прогон стоит копейки. Да и блин, если я начну на ходу подменять системный промпт на "лёгкую" версию, я просто собью кэш и заплачу за этот "лёгкий" промпт полную стоимость, что экономически невыгодно (хоть и не мои деньги то, баланс не к моим картам привязан - но заказчик их контролит знатно). да и в рамках n8n + LangChain передавать "пинок" через payload в system_kick банально проще архитектурно, чем городить ветвление с подменой текстовых шаблонов в системной ноде. Но опять же - выше сказал своё ведение и решение ) За мысль спасибо, честно))
Логично, про сбивание кэша. вышло бы дороже, делаешь уклон на экономию бюджета заказчика-совсем токсичный чтоли он такой?)) Контроль кошелька на опережение хорошая темка, если является залогом долгого сотрудничества, но если по боку будет или нет тогда и париться незачем. По поводу n8n костылить шаблоны в ноде ради ретрая - такое себе, пинок через payload изящнее.
Почему автотесты это не поймают баг
Почему нельзя? Более того, он у вас уже есть - тот самый промпт на котором генерился пустой ответ.
Спасибо за комментарий) Поясню: в том-то и засада, что LLM стохастичны. Если температура выше нуля, модель на один и тот же промпт может 9 раз ответить нормально, а на 10-й уйти в глухую защиту и выдать пустоту. Всунуть этот кейс в автотест можно, но он будет так сказать, "мигать": тесты покажут зелёный свет, а в проде баг всё равно выстрелит. К тому же, если начать крутить системный промпт ради одной этой фразы, итогом будет сместить баланс запретов, и модель начнёт выдавать Reasoning Lock на сотне других живых диалогов, которых в тестах ещё нет.К сожалению классический QA тут сливается, эту дичь ловить приходится только динамически и прямо на лету, как раз через валидатор.
А если температуру 0 поставить воспроизводится? А если неколько раз прогнать и порог частоты воспроизведения подобрать и необходимое число испытаний? Взять в охапку ChatGPT и подумать с ней как здесь могут помочь матстат и теория надёжности.
покажут зелёный свет, а в проде баг всё равно выстрелит
Aways has been. И это ника не отменяет необходимость делать тесты, тобы не получилось почти как в анекдоте, выкатили новую версию с фиксами, пришёл чувак с тем же запросам и все опять упало) А потом ещё и выяснится что на том самом poison message новый солюшн даже и не проверяли...
ловить приходится только динамически и прямо на лету, как раз через валидатор.
Так это не отменяет необходимость QAить динамический валидатор, а тут и тот самый промпт пригодится
Спасибо за развернутый комментарий и отличные инженерные мысли! Про стат-анализ, теорию надежности и фиксацию temperature: 0 для дебага конечно абсолютно правильная база для классического бэкенда.
Однако в данном кейсе классический QA упирается в тупик. В одной из прошлых статей (https://habr.com/ru/articles/1076198/) я подробно описывал архитектуру этого агента. Промпт там не просто текст, это жесткая детерминированная карта тегов ([VERDICT:], [TASK:], [STAGE:]), совмещенная с жесткой иерархией Ступеней и JS-логикой внутри кастомных инструментов. Посмотреть на такое и становится понятно, почему автотесты на воспроизведение бессильны: 1. Комбинаторный взрыв в карте тегов. Модель обязана нарезать логику по строгим рельсам и не имеет права отвечать “из головы”. Как только на вход прилетает живая человеческая рефлексия (вне скриптов), в блоке на нулевой температуре модель гарантированно упирается в логический тупик: вызвать тул нельзя (нет триггера) = ответить от себя запрещено =единственный compliant-вывод, не нарушающий карту тегов = промолчать. Тестировать “мигание” или семантику? Да, мы можем зафиксировать temperature: 0 и отловить этот конкретный poison message. Но семантика человеческой речи бесконечна. Завтра клиент напишет метафору, послезавтра — скинет двусмысленный смайлик. Мы не можем написать миллион тестов на все оттенки человеческих мыслей, которые выбивают модель из детерминированной карты. А если мы начять крутить промпт и баланс запретов ради прохождения одного этого теста - так это гарантированно сместим веса детерминированной карты. На тесте всё будет “зеленым”, а в проде получится Reasoning Lock на сотне других живых диалогов, которых в базе тестов еще просто нет. Вы абсолютно правы в одном: QAить сам динамический валидатор — нужно. И именно для этого используется этот “отравленный” промпт на тестовом стенде. Но задача данного теста - проверить не то, что модель ответит хорошо, а то, что наш валидатор в n8n корректно перехватит пустоту, залогирует её через include_reasoning и сделает правильный ретрай с пинком. С рассуждающими LLM и жесткими бизнес-ограничениями физически нельзя гарантировать идеальное поведение модели тестами, поэтому фокус надежности смещается с “написать идеальный тест” на “построить отказоустойчивую архитектуру (слои защиты) вокруг модели”. И детерминированная карта тегов здесь как раз доказывает, что ловить такие глухие защиты нужно динамически и на лету.
Промпт там не просто текст, это жесткая детерминированная карта тегов ([VERDICT:], [TASK:], [STAGE:]),
А у вас логи не сохранились? Можно же просто послать в модель весь контекст который был на тот момент у модели и она по идее должна опять зависнуть с какой-то вероятностью, Вы же утверждаете что она может сама по себе зависнуть при некотором контексте, и так можно проверить ваш валидатор почти в e2e тесте.
ловить такие глухие защиты нужно динамически и на лету.
С тем что нужно в рантайме уметь обрабатывать ошибки в том числе пустые ответы никто не спорит) Но я за то что некоторые сценарии которые стрельнули на проде стоит добавить в регрессию.
Запустить тот же контекст в ллм-ку, чтобы она "опять зависла с какой-то вероятностью" - это отличный способ сжечь токены, но плохой способ построить надежный бэкенд к сожалению( я уже писал выше, этот poison message давно на стенде. Но мы тестируем им валидатор, а не стохастический "черный ящик" так сказать. впринципе то у LLM-агентов регрессия самой модели не гарантирует ровным счетом ничего: завтра юзер напишет ту же мысль, но другими словами, и база тестов радостно загорится зеленым, а прод снова упадет. Именно поэтому фокус надежности смещается с регрессии модели на жесткую рантайм-архитектуру вокруг нее. Могу вкратце рассказать что когда на 2х недельном бесплатном периоде после внедрения этого проекта, мне правок в промт прилетало что то около 6 штук (таких конкретных причём), и всё из за того что на стадии согласования ТЗ из 9 листов скринов ответов для нейронки, дословно, "...таких вариантов мы не продумали, надо как то сделать чтобы не повторилось Артём..."... наверное именно поэтому данный проект запомнится на долго мне)))
Опять вы почему-то настаиваете, что если у вас стохастическая система, то гарантировать ничего нельзя. Но, во-первых, любая система отчасти стохастическая. Во-вторых, можно с определенной вероятностью. Вы же понимаете разницу между вероятностью безотказной работы 99,9 % и 0.1%.
завтра юзер напишет ту же мысль, но другими словами, и база тестов радостно загорится зеленым, а прод снова упадет.
значит вы не пофиксили суть проблемы и не смогли воспроизвести ее в тестах. В вашем случае тест считается состоявшимся если модель сгенерировала пустой промпт, а фикс рабочим если приложение от этого не сломалось.
мы тестируем им валидатор, а не стохастический "черный ящик" так сказать
Это не отменяет необходимость делать е2е тесты, а то получится что компонент отдельно протестирован и работает, а когда выкатили систему с ним на прод - она при первом сообщении упала, потому что просто не проверили все вместе.
Я бы очень сомневался стоит ли сайнофить такой релиз на прод, если есть известные режимы работы системы которые приводили к инцидентам и которые не проверены в е2е тестах.
А если удалось вручную протестить е2е, вроде вы сами об этом писали, то стоит подумать с нейронками, как бы это засунуть в регрессию, чтобы потом случайно не разломать - для этого же регрессия и нужна.
Но дело хозяйское)
Reasoning Lock: ИИ‑агент в проде тратит токены и молчит — живой разбор бага