
Это бонусный материл в серии о внедрении LLM в клиентские сервисы. Если в прошлых трех статьях я подробно разбирал удачные моменты, архитектуру и правильные шаги, то этот текст решил целиком посвятить разбору наших ошибок и факапов. Сейчас – менее красивая часть и реальный опыт PM: что происходит после демо, когда AI-пилот пытаются превратить в промышленную систему и команда сталкивается со скрытыми техническими проблемами.
На демо всё выглядело почти идеально. Бот отвечал живо, бизнес видел прогресс, команда сравнивала модели и крутила промпты. Потом пришли реальные пользователи, реальные данные и реальные ограничения. И выяснилось неприятное: мы лечили не то.
В какой-то момент команда уже всерьёз обсуждала замену модели. Казалось, что проблема в качестве генерации: ответы были уверенные, но иногда неверные. После разбора логов оказалось, что в части диалогов LLM вообще не должна была отвечать. Routing отправлял пользователя в ветку answer, хотя API возвращал partial, а сценарий должен был уходить в handoff.
Самые дорогие ошибки жили не в LLM. Они жили в routing, API, handoff, базе знаний, метриках и compliance-слое. Модель просто красиво озвучивала проблемы, которые система создала раньше.
Перелом случился, когда мы перестали спрашивать: «Почему LLM ответила неправильно?» – и начали спрашивать иначе: «Почему система вообще поставила модель в ситуацию, где правильного ответа у неё быть не могло?»
Вывод неприятный, но полезный: сильная LLM не компенсирует слабую архитектуру. Если у системы нет нормального routing, владельца knowledge base и понятного handoff, сравнение моделей часто становится дорогим отвлекающим манёвром.
Иногда замена модели – это не улучшение продукта, а способ быстрее увидеть старую архитектурную проблему.
Где на самом деле рождается ошибка
На уровне презентации AI-система часто выглядит почти неприлично просто: пользователь → LLM → ответ. В промышленном контуре так не работает. Между пользователем и финальным ответом появляются слои, и каждый из них может сломать диалог раньше, чем модель вообще начнёт генерировать текст.

Снаружи это выглядит как «LLM ошиблась». Внутри часто оказывается другое: не та ветка routing, пустой ответ API, устаревшая база знаний, guard только в prompt, handoff без контекста или метрики, которые спрятали точку сбоя.
Ошибка №1. Сделать LLM источником истины
На демо это выглядит эффектно: пользователь спрашивает, модель отвечает, все довольны. В реальной системе схема ломается почти сразу. Пользователь обычно спрашивает не абстрактную вещь, а конкретный факт: статус платежа, причину отказа, следующий шаг, срок обработки, условия договора или причину повторного контакта.
LLM может отлично понять вопрос и красиво сформулировать ответ. Но она не знает, что произошло в CRM пять минут назад, менялись ли правила продукта утром и был ли контакт с этим клиентом вчера. Если факт не пришёл из системы-источника, модель строит вероятный ответ. В финтехе вероятный ответ часто оказывается неправильным. И чем увереннее он звучит, тем хуже.
Простой пример: клиент спрашивает, прошёл ли платёж. Модель понимает интент, находит похожий сценарий и отвечает общими словами: «Платёж обычно обрабатывается в течение дня». Для презентации звучит нормально. Для клиента – бесполезно. Для продукта – риск, потому что конкретный платёж мог быть отклонён, зависнуть на проверке или уже пройти.
Что мы сделали: стали считать отсутствие факта не проблемой промпта, а архитектурным событием. Если факт не получен из system of record, сценарий не фантазирует. Он уходит в уточнение, повторный запрос к источнику, handoff или честный отказ от ответа.
Ошибка №2. Подключить RAG/API и решить, что архитектура готова
Следующий соблазн появляется быстро: «Окей, модели нужны факты. Давайте подключим RAG или API – и всё решено». Нет. Просто проблема переезжает на другой этаж.
RAG может вытащить устаревший документ. API – вернуть неполные данные. База знаний – оказаться без владельца. Инструмент – быть доступным в сценарии, где его нельзя использовать. Раньше модель ошибалась без фактов. Теперь она может ошибаться увереннее, потому что получила не тот факт, не в том контексте или без нужных ограничений.
Например, пользователь спрашивает срок обработки заявки. RAG находит старую инструкцию, где указан один срок. API по текущему продукту уже живёт по другим правилам. Модель видит официальный текст и уверенно отвечает по нему. Формально она не «галлюцинировала». Но пользователь всё равно получил неверную информацию.
Что мы сделали: пересобрали контур вокруг промпта. Разделили сценарии по допустимым действиям, добавили проверки перед вызовом инструментов, закрепили владельцев базы знаний и отдельно описали поведение при пустом, неполном или противоречивом ответе API.
Самое полезное правило оказалось простым: если API вернул empty, partial, conflict или timeout, LLM не генерирует финальный ответ как ни в чём не бывало. Сценарий уходит в безопасную ветку: уточнение, повторный запрос, handoff или отказ от ответа.
Что должно быть вокруг LLM
Во второй статье серии я подробно разбирал гибридную NLU-архитектуру. Здесь оставлю короткую прикладную версию – не как эталонную схему, а как чек-лист того, где искать сбой.

Для диагностики я бы начинал не с модели, а с соседних слоёв:
-
Routing – бот идёт не в тот сценарий. Проверяем состояние диалога, правила переходов и разрешённые действия.
-
API/RAG – ответ звучит уверенно, но не совпадает с фактом. Проверяем источник данных, свежесть knowledge и поведение при пустом ответе.
-
Guard/compliance – запреты лежат в prompt, но система всё ещё может вызвать лишний инструмент. Проверяем pre-checks, маскирование и права доступа.
-
Handoff – оператор начинает с нуля. Проверяем, передаются ли интент, summary, факты и причина эскалации.
-
Metrics/audit – в среднем всё хорошо, но одна точка собирает основную долю ошибок. Проверяем разрезы по состояниям, переходам и типам ошибок.
Ошибка №3. Считать handoff провалом автоматизации

В предыдущей статье я писал, почему иногда лучше автоматизировать 70%, а не 90%. Здесь важен один вывод: handoff – это не аварийный выход и не поражение бота. Это часть продукта.
Но сам факт передачи оператору ещё ничего не гарантирует. Если после handoff оператор заново спрашивает то, что клиент уже сказал боту, пользователь воспринимает это как провал всей системы: «Меня прогнали через робота и всё равно начали сначала».
Внутри команды это часто выглядит невинно: бот «корректно эскалировал». Снаружи – раздражение клиента и лишняя нагрузка на оператора. Автоматизация вроде бы есть, но ценность теряется на последнем метре.
Что мы сделали: начали проектировать handoff как отдельный сценарий. У передачи появилась причина, краткое summary, статус последнего API-запроса и подсказка, почему бот не продолжил разговор сам.
Хороший handoff – это не просто «переключить на человека». Это передать человеку уже собранный контекст, чтобы разговор не начинался заново.
Ошибка №4. Смотреть на средний success rate и не видеть точку сбоя
На первых демо почти любой AI-пилот выглядит бодро: большинство диалогов проходит нормально, средние показатели растут. Можно выдохнуть. Но вот тут как раз лучше не выдыхать.
Самый неприятный вывод: общий success rate выглядел нормально, но один переход сценария давал почти 43% всех зафиксированных ошибок.
Мини-кейс выглядел так: общая метрика казалась терпимой, но пользователи застревали на одном переходе после распознавания намерения. Причина – routing не различал похожие состояния: где можно дать общий ответ, где нужно запросить API, а где нужен handoff.
Сверху это выглядело как «LLM иногда ошибается». В деталях оказалось, что LLM просто получала неправильную задачу. Её просили ответить там, где сначала нужно было получить факт или передать разговор человеку.
Что поменяли: разделили переход на три ветки – answer, fetch_fact, handoff; добавили проверку наличия факта и начали логировать причину выбора ветки. После этого команда увидела конкретную точку сбоя, а не абстрактное «модель иногда чудит».
Ошибка №5. Пытаться заменить контроль system prompt’ом
Это, пожалуй, самая опасная иллюзия. На первый взгляд всё логично: добавим в system prompt правила, запретим раскрывать персональные данные, попросим соблюдать политики и при сомнении переводить на человека.
Проблема в том, что prompt не является контролем. Он не управляет доступом к данным, не определяет права пользователя, не ведёт журнал аудита, не гарантирует, что запрещённый инструмент не будет вызван, и не доказывает, почему система приняла именно такое решение.
Если вся безопасность держится на system prompt, это не безопасность. Это надежда. А надежда – плохой control plane.
Что мы сделали: вынесли критичные ограничения в исполняемый слой правил. Перед вызовом инструмента система проверяет сценарий, основание для использования данных, поля для передачи модели, маскирование, логирование и необходимость handoff.
Проще говоря, prompt может объяснять модели желательное поведение. Но права, запреты, доступы и аудит должны жить не в тексте инструкции, а в коде и правилах системы.
Когда не надо начинать с замены модели
Я бы не начинал с выбора новой LLM, если:
-
модель не получает факт из system of record;
-
API может вернуть пустой или противоречивый ответ, а сценарий не знает, что делать дальше;
-
routing не различает «ответить», «запросить данные», «передать человеку» и «отказаться от ответа»;
-
handoff не передаёт оператору контекст;
-
у базы знаний нет владельца и процесса обновления;
-
compliance живёт только в system prompt;
-
метрики показывают общий success rate, но не точку сбоя.
В такой ситуации замена модели может дать красивое демо, но не исправит продукт. Она просто быстрее подсветит старые проблемы.
Что логировать, чтобы потом не гадать
Если вы не можете восстановить путь решения, вы не поймёте, где реально сломался диалог. Минимальный набор логирования:
-
intent, состояние диалога и выбранная ветка routing;
-
факт вызова API/RAG и статус ответа: ok, empty, partial, conflict, timeout;
-
была ли генерация LLM или сценарий ушёл в безопасную ветку;
-
причина handoff, итог диалога и тип ошибки.
После этого разговор с командой меняется. Уже не «модель странно ответила», а «на таком-то состоянии routing выбрал answer, хотя API вернул partial и нужен был handoff». Это другой уровень диагностики.
Перед запуском LLM стоит проверить не модель, а систему
Финальный короткий чек-лист:
-
Откуда модель получает факт, на основании которого отвечает?
-
Что система делает при пустом, неполном или противоречивом ответе API?
-
Кто владелец базы знаний и как обновляются правила?
-
Где граница, после которой бот обязан уйти в handoff?
-
Какие ограничения enforced кодом, а не prompt’ом?
-
Какие метрики показывают точку сбоя, а не среднюю температуру?
Выбор модели перестал быть главным конкурентным преимуществом. Почти любая команда может подключить современную LLM. Сложнее другое – превратить её в надёжный промышленный инструмент.
Самые дорогие ошибки часто живут не в модели: API не отдаёт нужные данные, routing ведёт не туда, база знаний никому не принадлежит, метрики скрывают точку сбоя, а compliance пытаются заменить system prompt.
Поэтому перед следующим AI-пилотом я бы задал команде один вопрос: если завтра заменить нашу LLM на ещё более умную, продукт действительно станет лучше? Или мы просто быстрее увидим старые проблемы в новой обёртке?
ссылка на оригинал статьи https://habr.com/ru/articles/1056376/