Обновить

Комментарии 6

P.S. Про pytest в изолированном контейнере — спасибо, что напомнили. У нас джун чуть не уронил прод, запустив subprocess.run() в сгенерированном коде на рабочей машине. С тех пор все LLM-тесты гоняем строго в одноразовых Docker-контейнерах без сети и с read-only маунтами.

У вас доступ к проду с рабочей машины?

Доброе утро!

Спасибо, что поделились — это как раз практическое подтверждение сценария из врезки к шагу 4.

Здесь важно не столько наличие Docker само по себе, сколько модель доверия: сгенерированный код по умолчанию считается недоверенным и получает минимальные полномочия — одноразовая среда, отсутствие сети, исходники доступны только для чтения. Контейнеризация для DevOps давно стала базовой практикой; существенна она именно там, где исполняется чужой — в данном случае модельно сгенерированный — код, а не там, где просто привычно.

subprocess.run() особенно показателен: он позволяет коду запускать внешние программы. Если модель сформировала исполняемую команду, путь или аргументы неудачно либо под влиянием недоверенного контекста, этот процесс на рабочей машине действует с правами пользователя, запустившего тест. Именно от такого класса ошибок и нужна изоляция.

Оговорка: одноразовый контейнер без сети заметно уменьшает радиус поражения, но не должен быть единственным рубежом. Если рабочая станция в принципе имеет пути к production-контуру — через VPN, учётные данные, CI/CD, внутренние API или облачные секреты, — нужны и ограничения на уровне сетевой топологии, IAM и управления секретами. Сегментация доступа и изоляция исполнения должны работать как независимые контуры защиты.

Интересно, как у вас устроен следующий этап: код, прошедший тесты в песочнице, обязательно попадает на human review или при каких-то условиях может автоматически пройти дальше по конвейеру?

Зачем джуну прод?

У меня был почти зеркальный кейс, только не с кодом, а с генерацией чек-листа по ТЗ.

HTTP 200, JSON валиден, схема пройдена, результат сохранился — с точки зрения пайплайна всё зелёное. Открываю результат: 271 строка, где рядом с нормальными проверками модель добавила цели исследования, элементы матрицы рисков, служебные формулировки про готовность и вопросы, на которые исходное ТЗ вообще не отвечало. После этого для меня окончательно развалилось «валидный = пригодный».

Для таких артефактов нет удобного execution oracle, как у кода, поэтому пришлось переносить жёсткий гейт ближе к источнику: существенный пункт результата должен иметь связь с конкретным требованием или фрагментом исходного документа. То, что источником не подтверждается, не становится успешным результатом — максимум уходит на ручную проверку.

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

По сути, у меня получилось очень похоже на ваш принцип «детерминированное раньше вероятностного», только детерминированная часть строится вокруг traceability и контракта результата, а LLM остаётся скорее детективом, чем судьёй.

Интересно, как бы вы строили такой гейт для текстового артефакта без исполнимого оракула: claim → source binding, отдельный контроль покрытия или уже human review на остатке?

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

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

У текста исполнимого оракула нет вовсе. Поэтому положительный вердикт для текста — не «верно», а составной и ограниченный: трассируемо + не противоречит модели требований + покрыт критичный инвентарь + соответствует контракту. Прошёл гейт — значит автоматика не нашла повода забраковать, а не «пригодно». Вот эта асимметрия и есть суть: у кода есть чем добыть положительное свидетельство, у текста — почти только отрицательное.

По вашей развилке — не «или-или», а три слоя, детерминированное первым:

  1. claim → source binding — да, но слабая нижняя граница. Пункт может верно ссылаться на REQ-017 и всё равно нарушать контракт: усилить модальность (может → должен), ввести число, которого в ТЗ нет. Поэтому сильная проверка — не «есть ли источник», а «не противоречит ли пункт формальной модели требований». ТЗ сначала разбирается системным анализом в модель (ID, модальности, числовые границы, взаимоисключения), и пункт валится по противоречию ей правилом (if item.modality==MUST and req.modality==MAY: reject), а не мнением LLM. Вот это уже больше, чем судьи и детективы.

  2. покрытие — обязательно и ортогонально первому. Faithfulness ловит лишнее, покрытие — тихо потерянное. Меряется только против замкнутого инвентаря требований, с весом по критичности: пропущенное критичное — жёсткий reject, а не warning.

  3. human review — только на калиброванном остатке: слабая привязка, спорное покрытие критичного, конфликт проверок. Не 271 строка, а серая зона с причиной.

Честная граница: всё упирается в качество модели ТЗ. Если ТЗ — проза, то сам шаг «разобрать в формальную модель» — это ещё один вызов LLM, то есть генератор, которому нужен свой гейт: пропустил извлекатель половину требований — покрытие покажет 100% на неполном множестве. Уязвимость просто сдвигается вверх по конвейеру.

Этот класс — оракул для неисполнимого LLM-софта через привязку к требованиям — разбирает Wang et al., ASE'26 (REAG, Requirements-Augmented Generation, arXiv:2608.12970): оракул строят из требований, а не из эталонного ответа, и упираются в то же узкое место — точность привязки к источнику, а не генерация.

Поэтому вопрос по существу: ТЗ у вас структурировано (нумерованные требования, покрытие разностью множеств) или инвентарь извлекаете из прозы? Там и проходит реальная граница детерминированного ядра — в прозе половина «детерминированного» на деле детектив.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации