Пристегните ремни, гики! Сегодня мы погрузимся в самые глубины кодинга, где искусственный интеллект встречается с суровой реальностью продакшена. Забудьте про скучные мануалы и заумные доклады – перед вами история, полная драматизма, неожиданных поворотов и, конечно же, ценных уроков, которые помогут вам не наступить на те же грабли. Мы, авторы TechLoot, всегда на передовой технологического прогресса, и сегодня расскажем вам о том, как даже самые умные нейросети могут подкинуть сюрпризы, если не знать, как с ними правильно общаться. И да, речь пойдет о том, как даже мощный
Claude AI может устроить настоящий хаос, если вы расслабитесь и перестанете следить за его «поведением». Готовы узнать, почему ваш
Claude AI официальный может внезапно начать чудить, и как обеспечить стабильность даже при работе с самыми передовыми моделями на
Claude AI сайте? Поехали!
Наш проект начинался просто, как и многие гениальные идеи: у нас была система, которая умела одно, но делала это блестяще. Она превращала вопросы на естественном языке в вызовы API. Нашими пользователями были аналитики, менеджеры по работе с клиентами и руководители операций. Они прекрасно знали, какие данные им нужны, но ручная сборка означала вытягивание информации из четырех дашбордов, двух BI-инструментов и конструктора отчетов Salesforce. С нашей системой они просто вводили запрос на обычном английском языке. Запрос типа "Скомпилировать отчет об объеме продаж за январь-март 2026 года для Северо-Восточного региона, с разбивкой по городам" переводился в вызов API, который система могла выполнить:
json
{
"description": "User requested sales volume for the given date range, here is the API call to get the response",
"api_call": "/api/sales_volume",
"post_body": {
"start_date": "2026-01-01",
"end_date": "2026-03-31",
"region": "northeast"
}
}
Остальная часть конвейера была вполне обычной инженерией. Система отправляла вызов на нужный бэкэнд (у нас были интеграции с внутренними порталами отчетности, Salesforce и несколькими собственными сервисами), применяла большую языковую модель (LLM) (генерируемый JSON-запрос для фильтрации и формирования ответа) и доставляла его по электронной почте, в виде документа Google Drive или визуализировала в виде диаграммы в браузере.
К середине 2025 года система генерировала несколько сотен отчетов в месяц. Эти отчеты использовались руководством и аналитиками, а также распространялись среди внешних заинтересованных сторон. Она стала основным способом получения специальных данных для большинства команд.
Контракт между LLM и остальной частью системы представлял собой структурированный JSON-объект, как описано в примере выше.
json
{
"description": "User requested sales volume for the given date range, here is the API call to get the response",
"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. Не было компонента "человек в цикле" и состояния для хранения частично выполненного запроса. Это привело к сбоям в последующих системах по нескольким причинам.
Мы откатились до 4.0. Это было сложнее, чем должно было быть: между развертываниями 4.0 и 4.5 наша команда добавила новые интеграции API, все из которых были квалифицированы под 4.5. Откат модели означал повторную квалификацию каждой из них под 4.0 в условиях ограниченного времени.
Почему традиционная инженерная дисциплина здесь не справляется
Разработка программного обеспечения основывается на способности ограничивать эффект изменений. Когда вы обновляете драйвер или библиотеку, вы читаете примечания к выпуску, чтобы узнать, стоит ли ожидать критических изменений. Модульные тесты ограничивают то, что могло измениться. Вы можете использовать следующее свойство: изменяемая система достаточно детерминирована, чтобы ее поведение можно было предсказать или, по крайней мере, достаточно плотно проанализировать, чтобы дать вам уверенность. Радиус поражения ограничен конструкцией.
Системы, основанные на LLM, нарушают это предположение. Компонент, который производит ваш вывод, не находится под вашим контролем. Вы не можете провести сравнение между обновлением модели с 4.0 до 4.5. Это полная замена функциональности, от которой зависит ваша система.
Именно это мы подразумеваем под бесконечным радиусом поражения: изменение, чьи последующие эффекты невозможно перечислить заранее, потому что пространство входных данных (естественный язык) и режимы отказа (все, что модель может сделать по-другому) являются неограниченными.
Анатомия сбоя
Последующий анализ показал, что наш промпт всегда был недостаточно детализирован. Мы сказали модели вернуть JSON-объект с тремя полями. Мы описали, для чего предназначено каждое поле. Мы явно не указали, что описание должно быть строкой на естественном языке и не должно содержать сериализованных представлений других полей.
Более ранние версии модели выводили это ограничение из контекста. Sonnet 4.5, очевидно, лучше справляясь с "помощью" в форматировании, решила, что запрос на уточнение или предоставление тела запроса в описании делает ответ более полезным. С точки зрения модели, это была разумная интерпретация неоднозначной инструкции. Однако это нарушило предположения, на которых была построена наша система.
Ошибка была не в модели. Ошибка заключалась в нашем предположении, что модель будет продолжать заполнять наши пробелы в спецификации, как это было всегда. Три успешных обновления приучили нас верить, что эти пробелы безопасны.
Режимы структурированного вывода и API для использования инструментов могли бы поймать этот конкретный сбой на уровне схемы. Мы не использовали их по инженерным причинам, выходящим за рамки этой статьи. Но схемы ограничивают только синтаксис, а не семантику. Схема не может указать, что уточняющий вопрос не должен появляться в системе без пути для уточнения, или что диапазон дат никогда не должен молчаливо принимать значение "все время". Схемы решают более простую половину проблемы.
Архитектура "сначала оценки"
Дисциплина, которая устраняет этот пробел, заключается в том, чтобы рассматривать набор оценок — а не промпт — как формальную спецификацию системы. Промпт — это реализация спецификации. Модель — это интерпретатор. Оценки — это сама спецификация, и любое изменение модели или промпта допустимо только в том случае, если оно проходит их.
На практике оценка представляет собой тройку: входные данные, свойство, которому должен соответствовать вывод, и функция оценки. Для нашей системы оценка, которая поймала бы регрессию 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-в-качестве-судьи вносит свою собственную дисперсию в результаты. И набор может поймать только те режимы отказа, которые вы задумали указать — вы не можете оценить свой путь к безопасности от категории сбоев, которую вы никогда не представляли. Мы усвоили этот урок на горьком опыте: никто в нашей команде никогда не писал утверждения, что "поле описания не должно содержать команду curl", потому что никто не думал, что модель поместит ее туда.
Оценки не являются панацеей. Они дают вам возможность ограничить радиус поражения изменения единственным доступным способом, когда базовая функция является черным ящиком: путем плотного отбора входных-выходных данных, которые вас действительно волнуют, и отказа от развертывания, когда это поведение меняется.
Дорожная карта
Инженерное сообщество еще не разработало набор знаний для написания эффективных оценок. Нет общепринятых стандартов того, что означает "покрытие" в пространствах входных данных на естественном языке. Системы CI/CD не были созданы для регулирования вероятностных результатов тестов. По мере того, как агенты берут на себя все более автономную работу — написание кода, перемещение денег, планирование изменений инфраструктуры — разрыв между "модель прошла наши дымовые тесты" и "мы знаем, что эта система будет делать в продакшене" становится центральной инженерной проблемой следующих нескольких лет.
Команды, которые закроют этот пробел, будут теми, кто перестанет рассматривать оценки как второстепенную проблему контроля качества и начнет рассматривать их как фактическую спецификацию того, чем является их система.
Виджай Сагар Гуллапалли — инженер-основатель ИИ в Adopt AI и патентообладатель USPTO.
Сарат Махавратаюджула — старший инженер-программист в Sherwin-Williams.