Бесконечная зона поражения при обновлениях языковых моделей (LLM)

Бесконечная зона поражения при обновлениях языковых моделей (LLM)

Наша система делала одну вещь, и делала ее хорошо: она превращала запросы на естественном языке в вызовы API.

Пользователями были аналитики, менеджеры по работе с клиентами и руководители операционных отделов. Они знали, какие данные им нужны, но сбор их вручную означал необходимость выгрузки из четырех дашбордов, двух инструментов бизнес-аналитики (BI) и конструктора отчетов Salesforce. С помощью нашей системы они вводили запрос на обычном английском языке. Такой запрос, как «Составить отчет об объемах продаж за период с января по март 2026 года для Северо-Восточного региона с разбивкой по городам», преобразовывался в вызов API, который система могла обработать:

json

{

  «description»: «Пользователь запросил объем продаж за указанный диапазон дат, вот вызов API для получения ответа»,

  «api_call»: «/api/sales_volume»,

  «post_body»: {

    «start_date»: «2026-01-01»,

    «end_date»: «2026-03-31»,

    «region»: «northeast»

  }

}

Остальная часть конвейера представляла собой традиционную разработку. Система отправляла вызов в нужный бэкенд — у нас были интеграции с внутренними отчетными порталами, Salesforce и несколькими собственными сервисами, — применяла JSON-запрос, сгенерированный большой языковой моделью (LLM), для фильтрации и формирования ответа, а затем доставляла его по электронной почте, в виде документа Drive или в виде диаграммы, отображаемой в браузере.

К середине 2025 года система генерировала несколько сотен отчетов в месяц. Эти отчеты использовались руководством и аналитиками, а также распространялись среди внешних заинтересованных сторон. Она стала стандартным способом получения нерегулярных (ad-hoc) данных для большинства команд.

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

json

{

  «description»: «Пользователь запросил объем продаж за указанный диапазон дат, вот вызов API для получения ответа»,

  «api_call»: «/api/sales_volume»,

  «post_body»: {

    «start_date»: «2026-01-01»,

    «end_date»: «2026-03-31»,

    «region»: «northeast»

  }

}

Мы создали ее на базе Claude Sonnet 3.5 в начале 2025 года. Мы без происшествий обновились до версии 3.7 и до версии 4.0. К моменту выхода Sonnet 4.5 мы успокоились насчет стабильности и предсказуемости LLM при решении того, что мы считали простой задачей. Обновления моделей стали рутинными, похожими на минорное обновление версии хорошо работающей библиотеки.

Затем мы развернули версию 4.5. Для значительного процента запросов модель начала сворачивать содержимое post_body в поле description. За этим последовало два типа сбоев.

Во-первых, параметры фильтрации не доходили до API. Наша система считывала post_body в качестве источника истинных данных для полезной нагрузки запроса, а это поле возвращалось пустым. Вызов API происходил без диапазона дат или фильтра по региону. В зависимости от вызываемого API бэкенд либо возвращал объем продаж за все время или по всем регионам, либо выдавал ошибку 500.

Во-вторых, модель начала задавать в своем ответе уточняющие вопросы. Это было в новинку. Более ранние версии всегда использовали подход «лучших усилий» к неоднозначным запросам и возвращали структурированный объект. Sonnet 4.5, будучи более осторожной, иногда вместо этого отвечала вопросом. У нашей системы не было сценария для такого поведения. Она была построена на допущении, что каждый вызов модели приведет к вызову API. В ней не было компонента с участием человека (human-in-the-loop) и состояния для хранения частично завершенного запроса. Это привело к сбоям в нижестоящих системах сразу по нескольким направлениям.

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

Почему традиционная инженерная дисциплина здесь не работает

Разработка программного обеспечения опирается на способность ограничивать масштаб последствий изменений. Когда вы обновляете драйвер или библиотеку, вы читаете примечания к выпуску (release notes), чтобы узнать, стоит ли ожидать критических изменений. Модульные тесты (unit tests) очерчивают границы того, что потенциально могло измениться. Вы можете использовать следующее свойство: изменяемая система достаточно детерминирована, чтобы ее поведение можно было предсказать или по крайней мере достаточно плотно протестировать для обретения уверенности. Радиус поражения ограничен по определению.

Системы на базе LLM разрушают это предположение. Компонент, который производит ваш результат, не находится под вашим контролем. Вы не можете выполнить diff (поиск различий) при обновлении версии модели с 4.0 до 4.5. Это тотальная замена функциональности, от которой зависит ваша система.

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

Анатомия сбоя

Анализ после инцидента (post-mortem) показал, что наш промпт всегда был недостаточно детализирован. Мы велели модели вернуть объект JSON с тремя полями. Мы описали назначение каждого поля. Мы прямо не указали, что описание должно быть строкой на естественном языке и не должно содержать сериализованные представления других полей.

Более ранние версии модели выводили это ограничение из контекста. Sonnet 4.5, очевидно, стремясь быть более «полезной» в выборе формата, решила, что запрос уточнений или предоставление тела запроса в описании сделает ответ более ценным. С точки зрения модели, это была разумная интерпретация неоднозначной инструкции. Однако это нарушило допущения, на которых была построена наша система.

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

Режимы структурированного вывода и API вызова инструментов (tool-use) позволили бы выявить этот конкретный сбой на уровне схемы. Мы не использовали их по инженерным причинам, выходящим за рамки данной статьи. Но схемы ограничивают только синтаксис, а не семантику. Схема не может указать, что уточняющий вопрос не должен появляться в системе, не имеющей сценария для уточнения, или что диапазон дат никогда не должен молчаливо сбрасываться по умолчанию на все время. Схемы решают более легкую половину проблемы.

Архитектура с приоритетом тестов (evals-first)

Дисциплина, которая устраняет этот разрыв, заключается в том, чтобы рассматривать комплект оценочных тестов (evaluation suite) — а не промпт — в качестве формальной спецификации системы. Промпт является реализацией спецификации. Модель — это интерпретатор. Тесты (evals) — это сама спецификация, и любое изменение модели или промпта является валидным тогда и только тогда, когда оно проходит эти тесты.

На практике тест представляет собой триод: входные данные, свойство, которому должен удовлетворять результат, и функция оценки. Для нашей системы тест, который мог бы обнаружить регрессию в версии 4.5, выглядит примерно так:

python

def test_description_contains_no_serialized_payload(response):

    desc = response[«description»].lower()

    forbidden = [«curl», «post_body», «{«, «http://», «https://»]

    assert not any(token in desc for token in forbidden),

        f»description leaked structured content: {response[‘description’]}»

Несколько сотен таких свойств — некоторые написаны вручную для заведомо важных инвариантов, некоторые сгенерированы как регрессионные тесты на основе реального производственного трафика, а некоторые оценены LLM-в-роли-судьи (LLM-as-judge) на предмет более расплывчатых качеств, таких как тон — становятся барьером. Обновления моделей и изменения промптов следует рассматривать как пулл-реквесты (pull requests), которые должны сделать этот набор тестов зеленым, прежде чем они будут объединены (merged).

Тесты дорого создавать и поддерживать. Они устаревают по мере изменения вашего продукта. Оценка с помощью LLM-судьи вносит собственную вариативность в результаты. И этот набор тестов может выявить только те сценарии сбоев, о которых вы додумались упомянуть — вы не сможете обеспечить безопасность с помощью тестов против категории сбоев, которую вы никогда не воображали. Мы усвоили этот урок на горьком опыте: никто в нашей команде никогда не писал утверждение (assertion) о том, что «поле описания не должно содержать команду curl», потому что никому и в голову не приходило, что модель может ее туда поместить.

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

План развития

Инженерному сообществу еще только предстоит выработать свод знаний по написанию эффективных тестов. Не существует общепринятых стандартов того, что означает «покрытие» в пространствах входных данных на естественном языке. Системы CI/CD не были созданы для того, чтобы служить барьером для вероятностных результатов тестов. По мере того как агенты берут на себя все больше автономной работы — пишут код, переводят деньги, планируют изменения инфраструктуры, — разрыв между «модель прошла наши дымовые тесты (smoke tests)» и «мы знаем, как эта система поведечет себя в продакшене» становится главной инженерной проблемой ближайших нескольких лет.

Команды, которые сократят этот разрыв, — это те, кто перестанет относиться к тестам как к второстепенному инструменту обеспечения качества и начнут рассматривать их как реальную спецификацию того, чем является их система.

Виджай Сагар Гуллапалли (Vijay Sagar Gullapalli) — главный инженер по искусственному интеллекту в Adopt AI и изобретатель с патентом USPTO.

Сарат Махавратаяджула (Sarat Mahavratayajula) — старший инженер-программист в Sherwin-Williams.

Добро пожаловать в сообщество VentureBeat!

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

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

Оркестрация

Смотреть все

Подпишитесь на свежие новости!

Глубокая аналитика для руководителей в области корпоративного ИИ, данных и безопасности

Подписаться по RSS

RSS-ленты обновляются каждые 15 минут.