Разберём guardrails в ИИ: какие проверки окружают модель на входе, при получении контекста, на выходе и перед внешним действием. Четыре места проверки образуют карту контроля. Один фильтр закрывает одну точку и оставляет открытыми остальные.
Определение и четыре места проверки
Guardrails — это проверки, которые приложение выполняет вокруг вызова модели. Документация NVIDIA NeMo Guardrails описывает несколько точек применения: input rails обычно проверяют запрос до вызова модели, retrieval rails проверяют или преобразуют найденный контекст, output rails проверяют ответ до возврата клиенту, execution rails управляют собственными действиями, tool rails проверяют вызовы инструментов и их результаты. Диалоговые потоки Colang ведут многошаговый разговор.
Четыре места в простом workflow выглядят так. Вход: кто пришёл и что просит. Контекст: какие данные разрешено показать модели. Выход: что модель вернула и в каком формате. Действие: что приложение собирается сделать во внешнем мире.
В документации NVIDIA сказано, что библиотека применяет контроли в нескольких точках взаимодействия с LLM, а точная последовательность зависит от выбранного движка и конфигурации. Это важное свойство: разработчик задаёт карту проверок в настройках.
Проверки различаются по природе. Простое правило сравнивает строку или значение. Модельный фильтр запускает отдельную модель. Права доступа живут в приложении. Человеческое подтверждение стоит перед необратимой операцией. Документация NVIDIA прямо перечисляет этот набор: Colang-потоки, собственные Python-действия, отдельные модели безопасности, самопроверки LLM и сторонние сервисы. Совет из той же документации — брать самый лёгкий контроль, который удовлетворяет политике, и оценивать конфигурацию целиком.
Политика в system prompt — одна мера из набора. Она влияет на формулировки модели и не заменяет серверную проверку прав. AWS в описании Bedrock Guardrails перечисляет шесть настраиваемых политик: модерация контента, обнаружение атак на промпт, классификация запрещённых тем, редактирование персональных данных, проверка привязки к источнику и проверки автоматического рассуждения. Microsoft в документации по content filtering для Foundry Models описывает фильтрацию промпта и ответа ансамблем классификационных моделей, а также отдельные фильтры для атак на промпт, косвенных атак, защищённого материала, привязки к источнику и персональных данных.
Практический вывод для читателя: нарисуйте четыре клетки и подпишите, что именно проверяется в каждой. Пустая клетка показывает место, где отдельной проверки ещё нет.
Ограничения задачи и запретные ресурсы
Ограничения задачи выписываются до промпта. Начните с ролей: кто обращается к системе и что ему разрешено. Затем перечислите ресурсы, которых агент касаться не должен: чужие записи, платёжные операции, отправка писем, изменение заказов.
В учебном примере помощника магазина роль customer имеет права read_order с условием совпадения владельца, draft_reply при авторизованном заказе, а list_all_orders, refund, send_email и update_order запрещены. Все эти права заданы для условного учебного примера. Смысл в том, что запрет закреплён в таблице прав на стороне приложения.
Документация NVIDIA формулирует тот же принцип для агентных сценариев: проверяйте имена инструментов, аргументы и результаты до того, как приложение на них отреагирует; держите аутентификацию и авторизацию в приложении или сервисе, владеющем защищаемым ресурсом; обращайтесь с выводом модели как с недоверенным вводом; используйте списки разрешённого; изолируйте учётные данные от модели.
Отдельно стоит вопрос объёма данных. В учебном примере сервер находит нужный заказ и проверяет владельца до выдачи данных модели. Полный список заказов модели не передаётся. Это снижает цену ошибки: если модель всё же попросит чужую запись, у неё не будет данных для ответа.
Таблица прав для примера:
| Действие | Роль customer | Условие |
|---|---|---|
| read_order | allow | owner_id совпадает с principal |
| draft_reply | allow | заказ авторизован |
| list_all_orders | deny | — |
| refund | deny | — |
| send_email | deny | — |
| update_order | deny | — |
Проверьте свою задачу по трём вопросам. Какие данные модель видит заранее? Какие действия она может инициировать? Что произойдёт, если она ошибётся в каждом из них? Ответы на эти вопросы и есть реальные ограничения.
Входная проверка и отказ после генерации
Последовательная входная проверка может остановить недопустимый запрос до вызова модели. Отказ после генерации отбрасывает уже готовый ответ. Это разные точки с разной ценой.
В документации NVIDIA input rails описаны как проверка промпта до возврата вывода модели; они обычно выполняются до вызова прикладной LLM. При включённой опции IORails с опережающей генерацией проверка промпта идёт параллельно с генерацией ответа, а сгенерированный ответ отбрасывается, если входная проверка заблокировала промпт. Это экономит задержку, но не отменяет блокировку.
Отказ после генерации нужен там, где вход выглядит допустимым. Пример: пользователь спрашивает статус своего заказа, модель отвечает уверенно, но статус не совпадает с серверной записью. Входная проверка здесь ничего не поймает — запрос законный. Ловит сверка факта на выходе.
Порядок для учебного примера: сначала доверенная сессия и допустимость запрошенного действия, затем проверка владельца до раскрытия контекста, затем разбор JSON и полная схема, затем совпадение номера заказа с разрешённым запросом и статуса с серверной записью, затем список разрешённых действий и подтверждения перед внешней операцией.
Разница в поведении при отказе. При последовательной входной проверке блокировка может остановить запрос до вызова модели; при опережающей генерации ответ уже создаётся и затем отбрасывается при блокировке. Выходная блокировка уже потратила генерацию, поэтому её выгодно ставить после дешёвых проверок формата. Документация Microsoft описывает свою механику: промпт, отнесённый к фильтруемой категории и уровню, возвращает ошибку HTTP 400, а отфильтрованный ответ помечается значением finish_reason, равным content_filter.
Практическое правило: дешёвые детерминированные проверки ставьте раньше дорогих. Формат, схема и права стоят меньше, чем вызов отдельной модели-судьи.
Формат и допустимые значения результата
Формат проверяется независимо от того, насколько уверенно звучит текст. Модель может вернуть синтаксически корректный JSON с неверным содержимым, и наоборот.
Ниже полный ручной учебный вход: доверенная сессия, две серверные записи и права роли. Это вымышленные данные для проверки; модели передают только авторизованную запись после проверки владельца.
{
"principal": {
"customer_id": "customer-7",
"role": "customer"
},
"orders": [
{
"order_id": 105,
"owner_id": "customer-7",
"status": "shipped"
},
{
"order_id": 106,
"owner_id": "customer-9",
"status": "processing"
}
],
"permissions": {
"customer": {
"read_order": "allow only when order.owner_id == principal.customer_id",
"draft_reply": "allow only with an authorized order",
"list_all_orders": "deny",
"refund": "deny",
"send_email": "deny",
"update_order": "deny"
}
}
}
Полная схема успешного ответа; отказ по доступу останавливает процесс до модели и не оформляется объектом этой схемы.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "OrderStatusReply",
"type": "object",
"required": [
"order_id",
"status"
],
"additionalProperties": false,
"properties": {
"order_id": {
"type": "integer",
"minimum": 1
},
"status": {
"type": "string",
"enum": [
"processing",
"shipped",
"delivered",
"cancelled"
]
}
}
}
Ручной правильный ответ для заказа 105.
{
"order_id": 105,
"status": "shipped"
}
Для проверки сравнивают формат, разрешённый номер заказа и статус из серверной записи.
Разбор ошибок формата и значений:
| Случай | Что вернула модель | Результат проверки |
|---|---|---|
| H | ключи без двойных кавычек | разбор JSON не проходит до схемы |
| G | status in_transit | схема не проходит: значения нет в перечислении |
| E | order_id 106 при запросе 105 | формат проходит, привязка к запросу не проходит |
| F | order_id 105, status delivered | формат проходит, сверка с записью не проходит |
Случай H показывает, что разбор идёт раньше схемы: строка без кавычек вокруг ключей не является допустимым JSON. Случай G показывает границу перечисления: неизвестный статус не подменяется ближайшим разрешённым без установленного правила. Случай E показывает, что валидный формат не даёт разрешения читать чужой заказ. Случай F показывает, что уверенный текст не заменяет сверку с серверной записью.
Документация Microsoft описывает проверку привязки к источнику: она определяет, опирается ли ответ на предоставленные материалы. В описании AWS Bedrock Guardrails проверки автоматического рассуждения сверяют ответ с набором логических правил. AWS заявляет для проверок автоматического рассуждения точность до 99 процентов и объяснения решений; это утверждение вендора о своём продукте.
Практический порядок: разбор, схема, привязка к запросу, сверка с источником истины. Каждый шаг отбрасывает свой класс ошибок.
Сверка ресурса, адресата и прав перед записью
Перед записью проверяются четыре вещи: ресурс, адресат, права и разрешение пользователя. Все четыре проверяются на серверной стороне.
Ресурс: существует ли объект и тот ли это объект. В примере сервер находит заказ по номеру и сверяет владельца. Запрос «Где мой заказ 106?» при principal customer-7 даёт несовпадение: владелец 106 — customer-9. Модели не передаются ни запись 106, ни её владелец, ни статус. Внешний ответ — «Заказ недоступен в вашем аккаунте», внутренняя причина — owner_mismatch.
Адресат: кому уйдёт результат. Отправка письма — внешняя операция с необратимым эффектом. В примере send_email запрещён для роли customer.
Права: что разрешено роли. Приложение сверяет действие с таблицей прав. Документация NVIDIA советует держать аутентификацию и авторизацию в приложении или сервисе, владеющем ресурсом, и использовать списки разрешённых действий.
Разрешение пользователя: подтверждение не расширяет права. При запрете действие не выполняется даже после фразы «я разрешаю». Это ключевое свойство. Подтверждение подтверждает намерение, а таблица прав определяет допустимость.
Пример запрещённого вызова: модель предлагает инструмент refund для заказа 105. Заказ свой, текст вежливый, но для роли customer возврат запрещён. Инструмент не вызывается, фактического возврата не происходит.
Документация Microsoft описывает проверку соответствия задаче: она выявляет расхождения, включая неверные вызовы инструментов и несоответствие ввода или вывода инструмента намерению пользователя. Это отдельный класс проверок, который проверяет выбранные действия.
Практический порядок перед записью: подтвердите существование ресурса, сверьте владельца, проверьте право роли, запросите подтверждение для необратимого шага. Отказ оформляйте до вызова инструмента.
Ложное срабатывание и пропуск фильтра
Два типа ошибок воспроизводятся на простом словесном фильтре. Учебный антипример: строка переводится в нижний регистр, и если она содержит подстроку «всех» или «письмо», фильтр возвращает BLOCK, иначе ALLOW. Токенизации, синонимов и регулярных выражений здесь нет.
Результаты по четырём точным строкам:
| Строка | Решение фильтра | Оценка |
|---|---|---|
| «Где мой заказ 105?» | ALLOW | корректный пропуск |
| «Покажи заказы всех клиентов» | BLOCK | совпало с запретом, но защиту не доказывает |
Не отправляйте письмо. Где мой заказ 105? |
BLOCK | ложное срабатывание |
| «Где мой заказ 106?» | ALLOW | пропуск запроса к недоступному ресурсу |
Третья строка — ложное срабатывание. Пользователь упомянул письмо, чтобы его не отправляли, и спросил о своём заказе. Ответ о своём заказе разрешён, отправка письма не вызывается. Фильтр заблокировал законный справочный запрос.
Четвёртая строка — пропуск. Фильтр пропустил запрос к чужому заказу, потому что в строке нет запрещённых подстрок. Останавливает его отдельная проверка владельца. Это показывает, что словесный фильтр и проверка прав ловят разные классы случаев.
Вторая строка показывает ловушку оценки. Фильтр заблокировал запрос списка всех клиентов, и это совпало с запретом list_all_orders. Совпадение на одном примере не доказывает защиту: тот же фильтр пропустил четвёртую строку.
Документация NVIDIA прямо советует оценивать и атаки, и законные входы, чтобы измерять обходы и ложные срабатывания, блокирующие законные запросы. Там же сказано, что ни одна отдельная защита не гарантирует защиту от любого состязательного промпта, и рекомендуется эшелонированная оборона: обнаружение взлома, самопроверки LLM, эвристики, контроль тем, проверка инструментов и узкие права приложения.
Практический вывод: держите набор законных запросов рядом с набором атак. Один пример совпадения ничего не подтверждает.
Причина отказа и безопасный следующий шаг
Отказ должен быть понятным пользователю и безопасным для системы. Внутренняя причина и внешнее сообщение различаются.
В примере при несовпадении владельца внешний ответ — «Заказ недоступен в вашем аккаунте». Внутренняя причина — owner_mismatch. В пользовательском ответе нет чужих данных: ни владельца, ни статуса чужого заказа. По одной строке запроса нельзя заключить, что пользователь намеренно атаковал систему.
Для запрета списка всех заказов допустимый ответ — «Могу помочь только с вашим заказом. Укажите его номер». Это безопасный следующий шаг: пользователь получает путь к решению своей задачи.
Документация NVIDIA описывает три исхода проверки: PASSED, MODIFIED и BLOCKED. Поток может остановиться, вернуть настроенный отказ или изменить содержимое. Логирование результата без блокировки — отдельный шаблон приложения, который реализуется намеренно. Для аудита библиотека возвращает структурированный ответ с активированными проверками, выполненными действиями, вызовами LLM и статистикой времени; OpenTelemetry даёт трассировку запросов.
Документация Microsoft советует проверять finish_reason, чтобы понять, был ли ответ отфильтрован, и убеждаться, что в результатах фильтрации нет объекта ошибки, означающего, что фильтры не выполнялись. Там же описан случай недоступности системы фильтрации: запрос завершается без фильтрации, и это видно по сообщению об ошибке в результатах.
Практический порядок при отказе: зафиксируйте внутреннюю причину кодом, верните пользователю понятное сообщение, предложите безопасный следующий шаг. Не раскрывайте чужие данные и не подтверждайте догадки о намерениях пользователя.
Повторная проверка после изменения модели или правил
После изменения модели, промпта или правил набор примеров прогоняется заново. Документация NVIDIA советует версионировать вместе зависимость библиотеки, конфигурацию guardrails, промпты, собственные действия и версии внешних моделей и сервисов; повторять регрессионные и состязательные оценки перед выкаткой; сравнивать результаты с предыдущей версией и использовать поэтапный выпуск с откатом.
Там же описан способ проверки без генерации: методы check() и check_async() на LLMRails и IORails прогоняют входные и выходные проверки без вызова генерации ответа приложения. Проверки при этом могут обращаться к моделям и сервисам, настроенным для этих проверок. В автоматические тесты добавляются представительные случаи: разрешённые, заблокированные и изменённые.
Для регрессионной проверки сохраните все девять описанных случаев: четыре входных запроса, четыре ошибочных ответа и запрещённый refund. После смены модели или правил повторите те же случаи и сравните решения с ручным эталоном. Если законный запрос о заказе 105 с просьбой не отправлять письмо блокируется, зафиксируйте ложное срабатывание. Если запрос к чужому заказу 106 проходит проверку владельца, зафиксируйте пропуск.
Документация NVIDIA предупреждает, что нет универсальных показателей точности, полноты и доли ложных срабатываний, не зависящих от развёртывания: они зависят от выбранного детектора, набора сущностей, языка, порога и данных приложения. Оценивать качество проверок нужно на размеченном наборе. После выкатки стоит следить за задержкой, ошибками и распределением решений; сдвиг распределения сам по себе не указывает причину — трафик, поведение модели или конфигурацию политики.
Практический порядок: зафиксируйте версии, прогоните набор без генерации, сравните решения с эталоном, выпускайте поэтапно с возможностью отката.
Частые вопросы
Что такое guardrails в ИИ простыми словами?
Это проверки вокруг модели: на входе, при получении контекста, на выходе и перед внешним действием. Они ограничивают то, что модель видит, что она может вернуть и что приложение сделает по её ответу. Документация NVIDIA NeMo Guardrails описывает эти точки как отдельные виды проверок.
Какие примеры guardrails существуют?
Модерация контента, обнаружение атак на промпт, контроль запрещённых тем, редактирование персональных данных, проверка привязки к источнику, проверка вызовов инструментов и прав доступа. AWS в описании Bedrock Guardrails перечисляет шесть настраиваемых политик, включая проверки автоматического рассуждения. Microsoft в документации по content filtering добавляет фильтры защищённого материала и соответствия задаче.
Чем входная проверка отличается от выходной?
Входная проверка оценивает запрос. Выходная проверяет уже сгенерированный ответ перед возвратом клиенту. В документации NVIDIA input rails обычно выполняются до вызова прикладной модели; при опережающей генерации IORails проверка идёт параллельно с созданием ответа. Если она блокирует запрос, сгенерированный ответ отбрасывается.
Может ли один фильтр защитить систему?
Нет. Документация NVIDIA советует эшелонированную оборону и прямо указывает, что ни одна отдельная защита не гарантирует защиту от любого состязательного промпта. Учебный антипример на двух подстроках показывает ложное срабатывание на законном запросе и пропуск запроса к чужому ресурсу.
Как проверить guardrails перед выкаткой?
Прогоните набор представительных примеров без вызова генерации через check() или check_async(), добавьте разрешённые, заблокированные и изменённые случаи в автоматические тесты, сравните решения с предыдущей версией. Документация NVIDIA советует версионировать конфигурацию, промпты и версии моделей вместе и выпускать поэтапно с откатом.
