Качество ответов всей LLM-системы в продакшене редко поднимается выше 90%. Такой потолок стоит принять до старта: если задача требует 99%, а ошибка стоит дорого, честная оценка на бумаге дешевле, чем полгода разработки с отказом в конце.
Второй счёт, который редко делают заранее: итоговое качество цепочки вызовов считается как произведение качества шагов. Три шага с точностью 95%, 80% и 99% дают на выходе около 75%, хотя каждый по отдельности выглядит прилично. Ниже разбор кейса классификации кодов услуг для 402-й формы, где точность одной ноды выросла с 73% до 94%, и арифметика, по которой можно прикинуть, сойдётся ли ваш проект по стоимости ошибки.
Почему в LLM-проектах реально достижимо качество не выше 90%
Автор разбора на Habr формулирует вывод без оговорок: на проде вряд ли удастся добиться качества ответов всей системы выше 90%. Ориентироваться он советует сразу на этот уровень, потому что часть проектов при высокой стоимости ошибки не сойдётся вообще. Это нормальный итог оценки: команда выяснила это на расчёте, а не после релиза.
За цифрой 90% стоит не свойство конкретной модели, а накопление ошибок по всей конструкции: несколько вызовов LLM, код между ними, правила оркестрации, парсинг ответов. Каждый элемент добавляет свой процент брака.
Чем качество отдельной ноды отличается от качества всей системы
Нода (шаг) - это один вызов LLM с фиксированным промптом и своей метрикой точности. Система - цепочка таких шагов плюс код, который готовит вход, валидирует выход и решает, что делать с отказом.
Разница видна на цифрах кейса: нода классификации кодов услуг выросла с 73% до 94%. Это метрика одного шага на похожих данных, а не обещание, что 94 из 100 заявок пройдут весь путь до корректной записи в форму. Как только к шагу добавляются извлечение текста, нормализация, проверка по справочнику и запись в систему, итог считается по всей цепочке.
Почему 90% - это ориентир, а не гарантия
Цифры 73% и 94% относятся к конкретной задаче: плоская классификация на 50 классов кодов услуг. Переносить их на извлечение реквизитов из договоров или на генерацию ответов в поддержке нельзя: другой шум на входе, другая цена ошибки, другое распределение классов.
Потолок около 90% задаёт рамку планирования, а не обещание заказчику. Дальше решает экономика. Если ошибка стоит 50 тысяч рублей, а поток 10 тысяч заявок в месяц, то 10% брака при 90% качества даёт убыток, который перекрывает экономию на операторах. Проект может быть технически успешным и всё равно не сойтись.
Кейс: как нода классификации кодов услуг выросла с 73% до 94%
Условие задачи: плоская классификация, 50 классов, где класс - это код и формальное обозначение услуги. По названию услуги нужно выбрать соответствующий код для 402-й формы. В справочнике, например, код 842 - «Разработка и установка программного обеспечения», код 7123 - «Грузовые перевозки автомобильным транспортом».
Первая версия промпта показала 98% правильных ответов на внутреннем бенчмарке. На проде качество оказалось 73%. Автор отдельно оговаривает, что поправил вводные, сохранив общий смысл реальной задачи, поэтому детали кейса могут отличаться от исходного проекта.
После провала на проде было три пути: набивать промпт всевозможными исключениями, разделить задачу на несколько вызовов LLM или динамически подставлять подходящие примеры. Прирост с 73% до 94% дала комбинация второго и третьего подхода вместе с переработкой набора примеров.
Подбор примеров и динамическая подстановка похожих кейсов
Статичный блок few-shot примеров работает одинаково для всех входов: 5-10 случаев из справочника лежат в промпте и для «грузовых перевозок», и для «разработки ПО». Модель тянется к тому, что ближе к примеру, а не к тому, что ближе к реальному названию услуги.
Динамическая подстановка меняет схему: под конкретный вход отбираются похожие кейсы и уходят в промпт вместо фиксированного набора. Отбор строится на поиске по названиям услуг и кодам, часто хватает обычного поиска по эмбеддингам или по ключевым словам. Для классификации кодов это важнее длины инструкции: модель видит 3-5 близких размеченных случаев и реже уходит в соседний класс.
Проценты прироста от каждого приёма в источнике не разложены, есть только общий результат: 73% на старте, 94% после переделки. Поэтому приёмы стоит подбирать по своему набору ошибок, а не копировать чужую последовательность шагов.
Разделение задачи на отдельные вызовы вместо одного большого промпта
Вторая причина провала в том, что в одном промпте живёт несколько задач со своей логикой. Автор описывает механику так: если внутри одного промпта много разных задач и для каждой прописана своя логика, даже при небольшом размере промпта часть правил может выпасть.
Пример перегруженного набора задач: извлечение 50 атрибутов из документа, где только для суммы прописан абзац правил. «Если это договор аренды, умножь стоимость месяца на срок договора в месяцах. Не включай неустойку в итоговую сумму…», и такие уточнения нужны для десятка полей. Модель держит в фокусе часть инструкций, остальные теряет, и какое именно правило выпадет в конкретном запуске, предсказать трудно.
Разделение на отдельные вызовы снижает нагрузку: у каждого шага свой короткий промпт, своя схема ответа и своя проверка. Ошибка локализуется в конкретном вызове, а не растворяется в общем результате. Цена - больше запросов и выше задержка, что для 50 классов на потоке заявок обычно приемлемо.
Почему раздувание промпта исключениями ведёт к переобучению под бенчмарк
Самый очевидный способ чинить ошибки - дописывать в промпт новое исключение. Разобрали неверный ответ на бенчмарке, добавили правило «если в названии услуги есть слово X, выбирай код Y», метрика на этом же наборе подросла. Цикл повторяется, промпт растёт.
Ловушка в том, что исключения пишутся под конкретные примеры, которые уже лежат в бенчмарке. Автор называет этот риск прямо: решение подгоняется под знакомые примеры, и промпт постепенно становится хорошим на знакомых данных. Рост метрики в этом случае измеряет степень подгонки, а не качество продукта.
Исходная точка кейса это наглядно показывает: 98% на внутреннем бенчмарке против 73% на проде. Оговорка по источнику: доступный текст обрывается на описании риска подгонки, поэтому вывод о переобучении подтверждён частично, как рабочая гипотеза автора, а не как измеренный эффект с контрольной группой.
Почему длинный контекст и обилие правил заставляют модель упускать информацию
Отдельная проблема - объём. В длинном контексте модель может упускать отдельные фрагменты: информация есть во входе, но в ответе она её не учитывает. Со стороны это выглядит так, будто модель «забыла» кусок промпта.
Механика та же, что с 50 атрибутами: чем больше правил и исключений, тем выше шанс, что часть выпадет. Каждое новое исключение повышает вероятность конфликта с предыдущим, а инструкция «при противоречии следуй более специфичному правилу» сама требует внимания модели.
Длину промпта стоит держать под контролем не из экономии токенов, а из-за деградации внимания. Если правило нельзя проверить кодом или вынести в отдельный вызов с узкой задачей, оно будет срабатывать через раз.
Как считать качество цепочки вызовов LLM через произведение шагов
Если система состоит из последовательных шагов и ошибка любого шага портит итог, качество цепочки считается как произведение точностей шагов: Q = p1 × p2 × … × pn, где pi - доля правильных результатов шага на данных, близких к проду.
Почему так: второй шаг получает корректный вход только в p1 случаях, третий - в p1 × p2. Ошибка раннего шага не компенсируется, потому что следующий вызов работает с испорченным входом и с высокой вероятностью выдаст испорченный выход.
Пример расчёта для контакт-центра: 95% × 80% × 99% ≈ 75%
Цепочка из трёх шагов: переписывание вопроса 95%, RAG (поиск и подстановка контекста) 80%, финальный ответ 99%. Перемножаем: 0,95 × 0,80 × 0,99 = 0,7524, то есть около 75%.
| Шаг | Точность шага | Накопленное качество |
|---|---|---|
| Переписывание вопроса | 95% | 95,0% |
| RAG: поиск и подстановка контекста | 80% | 76,0% |
| Финальный ответ | 99% | 75,2% |
Расклад показательный: финальный шаг с 99% ситуацию не спасает. Слабый средний шаг в 80% тянет итог вниз сильнее, чем помогает почти идеальная генерация. Оптимизировать в такой цепочке логичнее RAG, а не финальный ответ.
Оговорка: расчёт 95% × 80% × 99% ≈ 75% приведён в описании темы, в доступном фрагменте первоисточника эти вычисления не раскрыты. Формула произведения от этого не меняется, но конкретные проценты стоит воспринимать как иллюстрацию, а не как замер конкретной системы.
Почему добавление оркестрации со стоп-листом не вытягивает итог выше 80%
Оркестрация со стоп-листом выглядит как обходной путь: поставить над цепочкой ещё один слой, который проверяет ответ по списку запрещённых формулировок и при срабатывании останавливает или перезапускает обработку.
Считать надо честно: это дополнительный шаг со своей точностью, и он входит в произведение. Если слой ошибается в 5% случаев (пропускает проблемный ответ или блокирует корректный), итог падает ещё на 5% относительно предыдущего уровня. В примере контакт-центра итог остаётся ниже 80%.
Оркестрация полезна в другом: она не даёт отправить пользователю заведомо плохой ответ и ограничивает ущерб от отдельных сценариев. Ждать от неё роста общей точности выше суммы шагов не стоит. Обратный пример, где высокая точность достигается ценой нескольких слоёв проверки, разобран в материале про пять техник контроля качества LLM на Amazon Bedrock: каскадная верификация чисел и мультимодельный фейловер добавляют шаги, и итог всё равно считается по всей цепочке.
Как применить это к своему проекту: чек-лист оценки перед запуском
- Выписать все шаги цепочки, включая те, что кажутся техническими: извлечение текста, нормализация, классификация, проверка по справочнику, запись в систему.
- Оценить точность каждого шага на данных, близких к проду, а не только на внутреннем бенчмарке. Для классификации кодов услуг это значит взять реальные названия услуг с их шумом и опечатками.
- Перемножить точности и получить ожидаемое качество системы.
- Сравнить результат со стоимостью ошибки: сколько стоит один неверный код услуги, сколько таких ошибок в месяц допустимо, кто их разбирает.
- Заложить ориентир около 90% как потолок для всей системы и не обещать больше без измерений.
Если шаг генерирует текст, а не класс, оценка усложняется: нужен судья и разметка. Подходы к такой оценке с трейсингом разобраны в кейсе оценки AI-агентов для длинных отчётов.
Дальше выбор из двух вариантов. Либо расчёт сходится, и вы запускаете с известным уровнем брака и выстроенной проверкой: стратегии валидации по цене ошибки и объёму потока разобраны в статье про Human-in-the-Loop для LLM в бизнесе. Либо не сходится, и это нормальный вывод оценки, а не повод тянуть релиз бесконечно.
Как проверить, не переобучен ли ваш бенчмарк
- метрика на бенчмарке заметно выше прода, как 98% против 73%;
- промпт растёт исключениями под каждую ошибку из бенчмарка;
- новые кейсы с прода ломают то, что бенчмарк хвалит;
- правки промпта проверяются на тех же примерах, по которым искали ошибки.
Рабочая мера: держать отдельный набор примеров, который не используется при правке промпта, и прогонять его перед каждым релизом. Второй слой контроля - следить, насколько модель отличает тестовые формулировки от реальных: эффект evaluation awareness и расхождение бенчмарка с продом разобраны в статье как читать model card LLM.
Минимальный шаг, который стоит сделать до следующего релиза: выписать таблицу шагов с точностями и перемножить. Пять минут арифметики обычно дают более честный прогноз, чем ещё один раунд правок промпта.