30 мар. 2025 г.·6 мин чтения

Коды сбоев маршрутизатора моделей, которые объясняют каждую передачу

Коды сбоев маршрутизатора помогают поддержке и продукту понять, почему запросы переключаются, заметить слабые подсказки и исправить правила маршрутизации, вызывающие повторные отказы.

Коды сбоев маршрутизатора моделей, которые объясняют каждую передачу

Почему скрытые передачи создают хаос в работе поддержки

Маршрутизатор отправляет запрос одной модели, а затем тихо переключается на другую. Пользователь видит только результат: более медленный ответ, другой тон или ответ, который упускает суть. В поддержку приходит жалоба, но не причина. Продукт видит падение качества, но не триггер.

Тихий откат лучше полной ошибки — он не останавливает приложение. Но он не объясняет, что пошло не так. Первая модель просто зависла? Запрос превысил лимит контекста? Вступила в силу квота у провайдера? Маршрутизатор переключился, потому что задача требовала инструмента, который первая модель не могла использовать? Лог, в котором стоит fallback_used, почти ничего не говорит.

Эта дыра быстро создаёт хаос в поддержке. Агент может пометить тикет как «плохой ответ», когда на самом деле дело было в сбое провайдера. Продукт может подумать, что подсказку нужно править, хотя маршрутизатор переключился из‑за слишком большого запроса. Две команды смотрят на один и тот же кейс и идут в разные стороны.

Нечёткие причины усугубляют проблему. Логи, полные ярлыков вроде error, retry или other, кажутся безобидными в момент разработки, но позже обходятся дорого. Они скрывают паттерны, смешивают разные проблемы и замедляют триаж. Если десять передач помечены одинаково, никто не понимает, что именно чинить: подсказки, бюджеты, лимиты, инструменты или настройки вендора.

Коды отказов маршрутизатора должны быть понятны людям, а не только машинам. Агент поддержки должен суметь прочитать причину передачи и объяснить её в одном предложении. Продукт должен уметь группировать эти причины и видеть, что продолжает ломаться. Хорошие логи превращают догадки о маршрутизации в конкретные действия.

Цель проста. Каждая передача должна отвечать на один простой вопрос: почему маршрутизатор переключил этот запрос на другую модель? Когда ответ ясен, поддержка отвечает быстрее, продукт исправляет реальную проблему, и тот же тикет с меньшей вероятностью вернётся на следующей неделе.

Когда передача требует кода отказа

Передача нуждается в коде отказа всякий раз, когда первый путь не смог закончить работу и маршрутизатор был вынужден сменить курс. Это включает переключение на другую модель, вызов резервного потока, обращение к инструменту или передачу кейса человеку. Если никто не может сказать, почему произошёл переход, лог не поможет ни поддержке, ни продукту.

Используйте код, когда передача отвечает на реальный вопрос. Почему более дешёвая модель сдалась? Почему маршрутизатор пропустил обычный путь? Почему система остановилась вместо повторной попытки? Хороший код превращает расплывчатое событие в конкретную причину, по которой команда может действовать.

Несколько моментов почти всегда заслуживают кода:

  • маршрутизатор переключил модели после неудачной попытки
  • маршрутизатор отправил задачу в инструмент, а инструмент не вернул пригодных данных
  • система остановилась, потому что исчерпало время или бюджет
  • ответ не прошёл проверки, и маршрутизатор пришлось повторить попытку или эскалировать
  • правило политики заблокировало запрос, хотя модель могла бы ответить

Держите ошибки пользователя отдельно от ошибок маршрутизатора. Если пользователь прислал неполные данные, противоречивые инструкции или запрос, который ваш продукт не поддерживает, отнесите это в одну группу. Если маршрутизатор выбрал неправильную модель, использовал плохой порог или отправил задачу по неверному пути, поместите это в другую. Разными проблемами управляют разные команды.

То же самое сделайте для лимитов модели и блокировок политики. Модель, которая не помещает контекст, не умеет соблюдать формат вывода или не решает задачу, — это не то же самое, что жёсткое правило, блокирующее медицинские советы, регулируемый контент или защищённые данные. Оба могут закончиться передачей, но лечатся по‑разному.

Маленькие различия в кодах важны. timeout — не то же самое, что cost_cap_hit. tool_error — не bad_output. bad_output — не policy_block. В работе поддержки такие метки меняют, кто ответственен за проблему. Инфра чинит медленные вызовы. Продукт чинит сломанные пути инструментов. Владельцы подсказок или моделей исправляют неверный JSON, слабые ответы и другие проблемы с выводом.

Если при одной передаче есть две проблемы, логируйте первую причину, которая вынудила переключиться. Строго придерживайтесь этого правила. Чёткие метки лучше умных меток всегда.

Первый набор кодов, который стоит определить

Начните с малого. Большинству команд полезнее пять чётких кодов, чем тридцать пересекающихся ярлыков. Если вы запустите слишком много — люди перестанут доверять данным, потому что одно и то же событие будут помечать по‑разному.

Хороший стартовый набор покрывает самые распространённые причины, по которым запрос покидает первый путь. Держите имена простыми, короткими и убедитесь, что каждое значит только одно.

  • timeout — модель или зависимость работали слишком долго. Действие: повторить один раз, затем проверить задержки и лимиты очереди.
  • tool_error — маршрутизатор вызвал инструмент, и он упал. Действие: посмотреть логи инструмента и починить интеграцию.
  • policy_block — запрос попал под правило безопасности или бизнес‑политику. Действие: пересмотреть блокируемый ввод и правило, которое его остановило.
  • bad_format — ответ пришёл, но сломал схему или пропустил обязательные поля. Действие: ужесточить подсказку, схему или парсер.
  • low_confidence — маршрутизатор получил ответ, но оценка была слишком слабой для доверия. Действие: отправить на более сильную модель, резервный поток или человеку.

Эти коды работают, потому что каждый указывает на другого владельца. timeout часто относится к инфре. tool_error обычно — к команде, владеющей интеграцией. policy_block может принадлежать продукту, юристам или trust & safety. bad_format — это обычно задача по подсказкам или парсеру. low_confidence — сигнал о логике маршрутизации или оценке.

Избегайте ярлыков вроде failed, other или model_issue. Они экономят секунды при названии события, а потом тратят часы, потому что никто не понимает, что чинить. Код должен ответить на один простой вопрос: что команда должна проверить в первую очередь?

Также полезно разделять причину и результат. «Перенаправление на более крупную модель» — это результат, а не код отказа. low_confidence — причина. Это важно, когда команды просматривают сотни событий маршрутизации.

Если новый код не меняет следующего действия, вероятно, он пока не нужен.

Как по шагам добавить коды в маршрутизатор

Зафиксируйте одно событие передачи сначала, а не каждую странность маршрутизатора. Выберите момент, который создаёт больше всего путаницы для поддержки или продукта, например когда первая модель сдалась и включилась вторая. Если с первого дня пытаться пометить все крайние случаи, люди перестанут верить данным.

Для каждой передачи запишите одну причину, которую вы хотите, чтобы система сообщила. Держите формулировку простой. «Контекст слишком длинный» лучше, чем «ограничение обработки входа». «Совпадение политики безопасности» лучше, чем «эскалация соответствия». Хорошие коды читаются так, чтобы руководитель поддержки понял их с первого взгляда.

Простой паттерн работает хорошо:

  1. Назовите событие простыми словами, например «маршрутизатор переключился с дефолтной модели на резервную».
  2. Назначьте один код для основной причины, а не стек причин.
  3. Добавьте одно короткое предложение, которое объясняет, что это спровоцировало.
  4. Сохраните этот код и предложение в той же записи лога, что и передача.

Это короткое предложение очень важно. Код вроде ctx_limit помогает считать случаи, но предложение объясняет линию, которую пересёк маршрутизатор, например «разговор достиг лимита токенов после того, как клиент вставил политику возврата и три цепочки писем». Поддержка это прочитает быстро. Продукт сможет сработать.

Затем протестируйте черновые коды на старых логах маршрутизатора и закрытых тикетах. Ищите две проблемы. Во‑первых, некоторые передачи не подходят ни под один код. Во‑вторых, слишком много передач попадают под несколько кодов сразу. Оба признака говорят, что список ещё размытый.

Если два кода часто описывают одно и то же событие, уберите один. Если люди спорят, какой код использовать, перепишите оба, пока выбор не станет очевидным. Небольшой список, который все используют одинаково, лучше длинного списка, о котором никто не помнит.

Практическое правило: у каждой передачи должен быть один первичный код, одно короткое триггерное предложение и никаких дебатов после факта. Если руководитель поддержки и продукт‑менеджер читают один и тот же тикет и выбирают разные коды, набор кодов ещё нужно доработать.

Что записывать вместе с каждой передачей

Аудит ваших переходов маршрутизатора
Закажите консультацию, чтобы проверить, почему запросы переходят между моделями, инструментами или ручными путями.

Запись передачи должна отвечать на один вопрос быстро: почему маршрутизатор переключил модели и что пользователь при этом почувствовал? Если лог просто говорит «отправлено на резервную модель», поддержка не поймёт, случилось ли это из‑за подсказки, сбоя инструмента, таймаута или неверного выбора модели.

Полезные записи компактны, но не размыты. В большинстве команд пяти элементов контекста хватает:

  • исходная модель и целевая модель
  • триггер переключения, код отказа, метка времени и тип запроса
  • версия подсказки или шаблона, плюс любой инструмент, функция или шаг поиска, которые использовались
  • влияние на пользователя, например задержка, повтор, частичный ответ, жёсткая ошибка или отсутствие видимого эффекта
  • одна короткая заметка, которую поддержка может прочитать за секунды

Это последнее поле легко пропустить и дорого терять. Заметка вроде «несоответствие схемы инструмента после запроса по биллингу» намного лучше, чем общий код, который заставляет кого‑то рыться в сырых логах. Держите её краткой и фактической. Одного предложения достаточно.

Версию подсказки команды тоже часто пропускают. Если версия 18 начинает вызывать передачи, а версия 17 — нет, у вас есть очевидное место для проверки. То же касается инструментов. Если большинство передач происходит после одного шага поиска или одного API‑вызова, модель может быть не основной проблемой.

Отделяйте влияние на пользователя от технической причины. Таймаут, который запускает резервный путь, может быть безвредным, если пользователь получил хороший ответ через секунду. Тот же таймаут гораздо важнее, если пользователь ждал восемь секунд, увидел ошибку и повторил запрос.

Если вы собираете только пять вещей, собирайте то, что изменилось, почему это изменилось, когда это изменилось, что почувствовал пользователь и одну простую заметку на человеческом языке. Этого достаточно, чтобы поддержка и продукт начали принимать решения.

Простой пример из работы поддержки

Клиент пишет в поддержку: «С меня списали два раза, нужен возврат». Маршрутизатор сначала отправляет сообщение самой дешёвой модели. Эта модель быстрая и недорогая, поэтому она обрабатывает первую проходку для большинства тикетов.

Её задача узкая. Она должна определить тип проблемы и извлечь поля, нужные потоку возврата, такие как email аккаунта, номер заказа и дата списания. В этом случае модель пометила тикет как запрос на возврат, но вернула только email и расплывчатое резюме.

Маршрутизатор не должен просто передать кейс более сильной модели и уйти. Он должен прикрепить код вроде missing_required_fields и указать, каких полей не хватало. Это говорит команде, что дешевая модель не «сломалась абстрактно». Она не выполнила конкретный контракт.

Короткий след событий может выглядеть так:

  • дешевая модель: классифицировать тикет и извлечь поля
  • код передачи: missing_required_fields с указанием order_id и charge_date
  • средняя модель: повторно извлечь поля и запустить инструмент поиска заказа
  • код передачи: tool_timeout с именем инструмента и временем ожидания
  • премиальная модель: задать однo уточняющий вопрос и надежно зафиксировать кейс

Второй переход здесь ещё важнее. Средняя модель лучше справилась с извлечением, нашла вероятный заказ и вызвала инструмент биллинга. Инструмент завис на 12 секунд и отработал таймаут. Маршрутизатор эскалировал снова, теперь с tool_timeout и указанием имени инструмента, ID запроса и длины таймаута.

Без таких кодов люди часто винят ту модель, которая была последней в цепочке. Это плохая привычка. Резервная модель лишь поглотила проблему.

С кодами в логах поддержка видит, что клиенты часто не указывают номера заказов в письмах о возврате, значит нужно улучшить форму ввода. Продукт видит, что endpoint поиска биллинга тормозит в пиковые часы, значит команда чинит сервис, а не тратит дни на настройку подсказок. Передачи перестают выглядеть случайными — они указывают на реальную причину.

Ошибки, которые делают данные бесполезными

Исправить непонятные логи отказов
Поможем назвать коды отказов так, чтобы поддержка и продукт понимали их сразу.

Плохие данные маршрутизации тратят время дважды. Поддержка читает лог передачи, пожимает плечами и догадывается. Продукт видит отчёт, доверяет ему и исправляет не то.

Самая распространённая проблема — ленивое маркирование. Если половина передач попадает в other, у вас не таксономия, у вас мусорное ведро.

Несколько ошибок причиняют большую часть вреда:

  • один catch‑all код всё заправляет. Когда other становится по умолчанию, никто не понимает — передача из‑за плохого поиска, таймаута, политической блокировки или слабого ответа?
  • стоимость и качество смешивают. too_expensive и low_confidence — разные события. Одно — правило бюджета, другое — правило производительности.
  • баги подсказок прячут под model_failed. Это неверно. Если маршрутизатор передал сломанную подсказку, модель не была первой причиной сбоя.
  • никто не может объяснить код простыми словами. Если руководитель поддержки не может прочитать код и объяснить его новичку в одном предложении, код слишком расплывчат или технически сложен.
  • значения кодов постоянно меняются. Если needs_escalation в апреле значит одно, а в июне другое, ваша линия тренда мертва.

Простая человеческая формулировка помогает больше, чем умное название. «Превышен контекст‑виндов» годится. «Событие семантического деградации» почти ничего не говорит.

Хороший тест: дайте список кодов человеку из поддержки и человеку из продукта. Попросите обоих отсортировать десять реальных передач одинаково. Если они часто не совпадают, коды нужно поправить до запуска.

Стабильные определения важны так же, как и сами коды. Зафиксируйте значение, запишите один краткий пример для каждого кода и добавляйте новый код только тогда, когда старый набор явно не описывает повторяющуюся проблему. Это делает данные «скучными», а это именно то, что вам нужно.

Быстрая проверка перед релизом

Выстроить бережливые AI-операции
Улучшите маршрутизацию, наблюдаемость и инфраструктуру без лишних процессов.

Если ваши коды отказов трудно читать, люди перестанут их использовать. Агент поддержки должен понять код за несколько секунд и знать, что делать дальше. Если ему всё ещё нужно спрашивать инженера, что значит fallback_reason_7, код провалил свою задачу.

Каждый код должен указывать на одно понятное действие. «Контекст слишком велик» может означать обрезать разговор и повторить. «Блокировка по безопасности из‑за upstream модели» может значить отправить кейс на ручную проверку. Когда один код может означать три разных исправления, поддержка будет догадываться, и данные быстро замусорятся.

Короткая предпродажная проверка ловит большинство ошибок:

  • Прочитайте вслух пять образцовых кодов человеку из поддержки. Если он колеблется — переименуйте.
  • Сопоставьте каждый код с одним следующим шагом. Если две команды поступят по‑разному, разделите код.
  • Фильтруйте логи по коду и версии подсказки вместе. Так продукт ловит плохие релизы подсказок.
  • Фиксируйте влияние на пользователя, а не только событие системы. «Пользователь увидел задержку 12 секунд» важнее, чем «маршрутизатор перезапускал дважды».
  • Сгруппируйте повторяющиеся передачи в одном представлении, чтобы видеть петли, повторы и тупики.

Этот последний пункт легко пропустить. Одна передача может выглядеть безобидной. Пять передач на одном запросе обычно значат, что маршрутизатор запутался, подсказка слабая или модель постоянно падает одинаково. Вам нужен экран, который показывает полный путь по порядку с метками времени.

Небольшой пример из поддержки показывает это наглядно. Запрос на возврат начинается у дешёвой модели, переходит к более крупной, затем уходит в правило‑поток. Если лог просто говорит «перенаправлено», никто не поймёт почему. Если он показывает «intent low confidence», затем «tool response too slow», затем «manual review required», поддержка объяснит задержку, а продукт увидит, где запрос ушёл не туда.

Перед релизом вытяните один день тестового трафика и задайте два простых вопроса. Может ли поддержка действовать по этим кодам без помощи инженеров? Может ли продукт группировать отказы по коду, версии подсказки и влиянию на пользователя? Если ответ нет — исправьте имена и логи до того, как реальные пользователи начнут попадать в маршрутизатор.

Дальнейшие шаги для команд поддержки и продукта

Список кодов имеет значение только если люди пользуются им каждую неделю. Начните с последнего месяца передач и сортируйте по частоте. Когда один и тот же код часто появляется в одном потоке, это реальная закономерность, а не случайный шум.

Смотрите на повторяющиеся отказы глазами пользователя. Проблема маршрутизатора редко бывает только проблемой маршрутизатора. Причина может лежать в подсказке, которая просит недостающий контекст, в инструменте, который таймаутится, или в политике, которая блокирует запрос, хотя тот должен проходить. Хорошие коды отказов избавляют поддержку от догадок и дают продукту ясное место для проверки.

Простая рабочая рутина достаточна:

  • вытяните самые частые коды за последний месяц
  • выберите один код и проследите его до подсказки, инструмента или политики
  • первыми исправляйте правила маршрутизации, которые причиняют пользователю наибольшую боль
  • перепишите имена кодов и их описания простым языком, понятным обеим командам

Порядок должен определять пользовательская боль. Если клиенты с запросами на возврат постоянно переправляются по цепочке, исправьте это прежде, чем тратить время на редкий резервный путь, который влияет только на внутренних пользователей. Частота важна, но фрустрация важнее.

Поддержка и продукт должны также поделиться одним коротким глоссарием. Если поддержка читает tool_context_missing, а продукт — retrieval_mismatch, код уже делает свою работу плохо. Давайте отказам имена, которые новичок поймёт за десять секунд. Это ускорит триаж и сократит бессмысленные споры.

Небольшой ежемесячный обзор обычно достаточен. Выберите один код, проверьте несколько реальных разговоров и решите, куда относится исправление. Иногда это правка подсказки. Иногда — новая попытка в инструменте. Иногда правило маршрутизатора вообще неправильно.

Если одна и та же проблема маршрутизации постоянно отскакивает между поддержкой, продуктом и инженерами, внешняя помощь может сэкономить время. Oleg Sotnikov на oleg.is работает как Fractional CTO и консультант стартапов по AI‑ориентированной разработке, инфраструктуре и автоматизации — это может быть полезно, когда проблемы передач затрагивают подсказки, инструменты и ops одновременно.

Часто задаваемые вопросы

Что такое код отказа маршрутизатора?

Код отказа маршрутизатора называет причину, по которой запрос покинул свой первоначальный путь. Он говорит поддержке и продукту — переключение случилось из‑за timeout, проблемы с инструментом, правила политики, некорректного вывода или низкой уверенности.

Когда нужно логировать код при передаче?

Логируйте код каждый раз, когда первый путь не смог завершить задачу и маршрутизатор изменил курс. Это включает переключение моделей, повторную попытку через другой поток, вызов инструмента, который упал, или передачу кейса человеку.

Сколько кодов отказа стоит начать использовать?

Начните с небольшой группы, обычно около пяти кодов. Команды более последовательно сортируют события, когда каждый код означает одну понятную вещь и указывает на первое действие.

Какие коды подходят для первой версии?

Надёжный начальный набор — timeout, tool_error, policy_block, bad_format и low_confidence. Эти коды соответствуют разным владельцам, поэтому люди сразу понимают, куда смотреть.

Нужно ли разделять ошибки пользователей и маршрутизатора?

Да. Отделяйте ошибки пользователя — пропуски данных или неподдерживаемые запросы — от ошибок маршрутизатора, таких как неверные пороги или выбор модели. Их решают разные команды, смешивание замедляет триаж.

Что должно включать каждое событие передачи?

Запишите, что изменилось, почему это произошло, когда это случилось, как это повлияло на пользователя и одну короткую заметку, которую человек прочитает за пару секунд. Включите исходную и целевую модель, код, метку времени, тип запроса, версию подсказки и вовлечённые инструменты.

Как выбрать один код, когда возникло несколько проблем?

Выберите первую причину, которая заставила переключиться, и используйте её как основной код. Если сначала случился tool_timeout, логируйте это первым и строго придерживайтесь правила выбора одного кода.

Почему использование "other" — плохая идея?

other скрывает паттерны и превращает реальные проблемы в шум. Если значительная часть трафика попадает в other, поддержка начинает гадать, а продукт исправляет не то.

Как проверить, подходят ли коды перед запуском?

Прогоните старые тикеты и логи через черновые коды и попросите одного человека из поддержки и одного из продукта пометить те же случаи. Если они часто не совпадают — переименуйте коды или разделите расплывчатые.

Что делать, если одна и та же проблема постоянно возвращается?

Отслеживайте повторы по коду, версии подсказки, инструменту и влиянию на пользователя. Если одна и та же проблема постоянно скачет между командами, сначала исправьте общую причину. При необходимости привлекайте внешнюю помощь, когда подсказки, инструменты и ops все участвуют.