Guardrails в нашем LLM-шлюзе — это проверка входящего запроса перед вызовом модели. Она добавляет к запросу 40–55 мс и решает по настраиваемой текстовой политике, а не по зашитой в модель таксономии. Вердикт выносят два независимых фактора: классификатор Shieldstral задаёт зону риска, а компактный судья решает внутри неё и может наложить вето.
Если коротко — для бизнеса
- Цена — 40–55 мс на запрос в режиме блокировки; в режиме наблюдения добавка практически нулевая.
- Политика — наш собственный текст. Её меняют без дообучения модели, и в ней явно перечислено, что нарушением не считается.
- Сотрудник, вставивший резюме, договор или свой пароль, не должен упираться в блокировку. Единичные персональные данные внесены в исключения политики, а блокировка без второго мнения возможна только при очень высокой уверенности (p ≥ 0.97). Один известный промах — свой пароль — разобран в результатах.
- Если классификатор недоступен, запрос проходит, но каждый такой пропуск виден в метрике с алертом. Обратный режим под нагрузкой ложно блокировал 33% запросов при 3 одновременных и 75% при 8.
- На регрессионном наборе из 58 синтетических кейсов связка правильно отработала 56.
О цикле «LLM-шлюз»
Две статьи о собственном LLM-шлюзе компании. «Мы» — это автор и AI-агенты, которым он делегировал часть исследований и правок. Компания обезличена, цифры настоящие.
- SurfCap-α: как семантический роутер выбирает модель
- Guardrails в LLM-шлюзе: почему Shieldstral ← вы здесь
Термины за минуту
- Guardrails — проверки вокруг вызова модели, которые не пропускают запрещённое политикой. Здесь — только проверка входа.
- Джейлбрейк — запрос, который пытается заставить модель обойти её собственные ограничения.
- Инъекция промпта — инструкция, подмешанная в текст, который модель прочитает. Косвенная — спрятана не в реплике пользователя, а в документе, ответе инструмента или истории диалога.
- Политика модерации — текст, описывающий, что считается нарушением и что — нет.
- Таксономия рисков — фиксированный список категорий вреда, на котором обучена модель-классификатор.
- Логпробы и калиброванная вероятность — логарифмы вероятностей токенов ответа. Из логпробов токенов «yes» и «no» получается непрерывная вероятность нарушения p, а не просто да/нет.
- Судья с ограниченным декодированием — LLM, которой разрешено ответить только одним из заранее заданных вариантов.
- Fail-open / fail-closed — что делать, если проверка недоступна: пропустить запрос или заблокировать его.
- Режимы
off/monitor/enforce— проверка выключена; идёт в фоне и только помечает; блокирует нарушение ответом HTTP 403. - F1 — гармоническое среднее точности и полноты классификатора, от 0 до 100.
- Radix-кэш — кэш общего префикса промпта на стороне сервера инференса: повторяющееся начало запроса не пересчитывается.
Зачем и от чего
Кому особенно полезен раздел:Бизнес и продуктАрхитекторы
Шлюз обслуживает чат-интерфейсы, агентов и интеграции. Поэтому в него попадает не только то, что написал человек, но и документы, результаты инструментов и история диалога.
Модель угроз сводится к четырём категориям:
- Джейлбрейки и инъекции промпта. В том числе косвенные: инструкция спрятана в документе или ответе инструмента [12].
- Массовая выгрузка данных. Просьба вытащить через модель базу персональных или конфиденциальных данных.
- Кража учётных данных. Попытки добыть чужие пароли, токены и ключи.
- Незаконный и вредный контент.
Исходные условия определили выбор сильнее, чем бенчмарки:
- Запросы в основном на русском.
- Детектор должен работать внутри контура, на той же GPU, где уже стоят другие модели.
- Большая доля легитимных запросов содержит персональные данные: сотрудник вставляет резюме, договор или свой же пароль. Стандартный классификатор блокирует такие запросы, и доверие к системе заканчивается в первый же день.
Изначально планировался Llama Guard в готовом прокси. Исследование кандидатов показало, что такая схема не подходит ни по языку, ни по гибкости политики.
Подходы в литературе
Кому особенно полезен раздел:ML и исследователиАрхитекторы
Стандартом стал подход Llama Guard [1]: небольшая LLM, дообученная классифицировать реплики по фиксированной таксономии рисков и отвечать «safe / unsafe» с категорией. Так же устроены ShieldGemma [2], WildGuard [3], Granite Guardian [4] и Qwen3Guard [5]. Различаются они по трём осям.
- Таксономия. Зашита в веса или передаётся текстом в запросе. Во втором случае политику можно менять без дообучения.
- Языки. Большинство моделей обучены преимущественно на английском. PolyGuard [6] показывает, насколько падает качество на других языках. LionGuard 2 [13] и PL-Guard [14] приходят к тому же с другой стороны: для неанглийского трафика нужна локализация и свои данные.
- Форма ответа. Либо генерация с категорией, либо один токен «yes / no», из логпробов которого получается калиброванная вероятность.
Shieldstral [7] ставит модерацию как бинарный вопрос: «нарушает ли этот текст приложенную политику?». Политика передаётся текстом, ответ — один токен. Это совмещает оба полезных свойства: свою политику и дешёвый калиброванный скор.
Две недавние линии работ задают границы подхода:
- Работа [8] показывает, что мониторы безопасности в основном ловят то, от чего сама модель и так отказывается. Один классификатор — слабая защита.
- Потоковая модерация ответов [9] [10] — отдельная задача со своими моделями.
Наконец, литература об инъекциях [11] [12] сходится в одном: недоверенным нужно считать не только реплику пользователя, но и любой текст, который модель прочитает.
Сравнение кандидатов и выбор Shieldstral
Кому особенно полезен раздел:АрхитекторыML и исследователи
Выбрали Shieldstral-1.0-3B: это единственный кандидат, который одновременно понимает русский, принимает политику текстом, отвечает одним токеном и помещается на уже занятую GPU.
| Модель | Размер | Русский | Политика | Решение |
|---|---|---|---|---|
| Shieldstral-1.0-3B | 3B | да (12 языков) | текстом в запросе | выбрана |
| Qwen3Guard-Gen | 0.6B / 4B / 8B | да (119 языков) | фиксированные классы | запасной вариант, если важна задержка |
| Qwen3Guard-Stream | 0.6B / 4B | да | фиксированные классы | отложена: нет поддержки в сервинге |
| Llama Guard 4 / 3-1B | 12B / 1B | нет | фиксированная таксономия | отклонена |
| Granite Guardian 4.1 | 8B | нет | набор рисков, сильна в RAG | отклонена |
| Nemotron Content Safety | 4B | нет | фиксированная таксономия | отклонена |
| gpt-oss-safeguard | 21B (3.6B активных) | не проверяли | текстом | отклонена: слишком медленная для первой ступени |
| NER-модели для ПДн | ~300M | да | извлечение спанов | не решают задачу классификации |
Решение опиралось на пять доводов:
- Русский язык. Он входит в число языков обучения. Это сразу отсекло Llama Guard, Granite Guardian и Nemotron.
- Своя политика без дообучения. Нам нужна не общая таксономия вреда, а своя: с массовой выгрузкой данных и с явным списком того, что нарушением не считается. У Qwen3Guard с его фиксированными классами такой возможности нет.
- Калиброванный скор за один токен. Ответ «yes / no» даёт непрерывную вероятность, а не дискретный вердикт. На ней держится вся логика порогов и серой зоны.
- Размер. Модель занимает около 12 ГиБ VRAM вместе с KV-кэшем и встаёт рядом с уже работающими моделями.
- Сервинг. Она поддержана в SGLang и vLLM, а SGLang уже есть в стеке. Лицензия — Apache-2.0.
По данным авторов [7], Shieldstral достигает F1 88.1 на WildGuardTest и 84.6 на PolyGuard Prompt. Это уровень Qwen3Guard-Gen-8B (88.2 и 84.3) при втрое меньшем размере. Для сравнения, у Llama Guard 4 — 74.3 и 62.1.
Вендорские F1 — ориентир, а не доказательство
Это цифры авторов модели. Сравнение кандидатов на собственных русскоязычных данных мы не проводили и оценивали только итоговую связку.
Особенности реализации
Кому особенно полезен раздел:АрхитекторыИнженеры
Главное отличие от типовой схемы «классификатор перед моделью» в том, что вердикт выносит не одна модель, а два независимых фактора, и у второго есть право вето. Остальные решения выросли из дыр, найденных на практике.
Три ступени и правило комбинации
Кому особенно полезен раздел:ИнженерыML и исследователи
- Дешёвый гейт на регулярных выражениях. Он ничего не блокирует, а только решает, нужна ли проверка на массовую выгрузку данных.
- Shieldstral. Оценивает вход по политике одним токеном (
max_tokens=1,temperature=0); вероятность нарушения берётся из логпробов (формула ниже). Если в ответе нет ни «yes», ни «no», это ошибка разбора, и вердикт не додумывается. - Судья с ограниченным декодированием. Это Plumb-4B [15] — decision-модель на базе Qwen3.5-4B, которая возвращает вероятность каждого варианта ответа за один прямой проход, без генерации токенов. Вопрос у неё один, с выбором: «safe», одна из категорий или «массовая выгрузка». Судья вызывается, только когда p ≥ 0.30 или когда его запросил гейт. Объединение трёх прежних вопросов в один сократило его время со 110 до 65 мс.
Здесь ℓ — логпробы токенов «yes» и «no» в первой позиции ответа.
Зачем нужен второй фактор, видно из замера. Запросы с единичными персональными данными получали от Shieldstral p = 0.75–0.92, а настоящая косвенная инъекция — 0.73–0.78. Такие диапазоны не разделить никаким порогом. Судья разделяет их уверенно: 0.04–0.14 для персональных данных против 0.53 для атаки. Отсюда правило: в диапазоне 0.70 ≤ p < 0.97 судья с оценкой ниже 0.25 накладывает вето. Выше 0.97 вето уже нет.
| Зона | Диапазон p | Судья | Без судьи | Итог в enforce |
|---|---|---|---|---|
| Безопасно | p < 0.30 | не вызывается | — | пропуск |
| Серая зона | 0.30 ≤ p < 0.70 | решает, порог 0.50 | FLAG | BLOCK, если оценка судьи ≥ 0.50, иначе пропуск |
| Вероятно опасно | 0.70 ≤ p < 0.97 | вето при оценке < 0.25 | FLAG | BLOCK, если вето нет |
| Опасно | p ≥ 0.97 | без права вето | BLOCK | BLOCK |
| Поверх всех зон | любое p | гейт запросил проверку, выгрузка ≥ 0.70 | — | нарушение при любом p |
Если судья недоступен, запросы из серой зоны и зоны «вероятно опасно» только помечаются (FLAG), а не блокируются.
Блокировка без судьи возможна только при p ≥ 0.97. Во всех спорных случаях без второго мнения система только помечает запрос, а не блокирует его.
ML-исследователю
Калиброванная вероятность одного классификатора не спасает, когда классы перекрываются: персональные данные (0.75–0.92) и косвенная инъекция (0.73–0.78) лежат в одной полосе p. Второй фактор с другим вопросом и другой моделью даёт независимое измерение, и в нём классы расходятся (0.04–0.14 против 0.53). Поэтому порог ставится не на один скор, а на их комбинацию.
Всё, что прислал клиент, — недоверенный текст
Кому особенно полезен раздел:АрхитекторыИнженеры
Проверяется не только последняя реплика пользователя. В проверку попадают системный промпт, инструкции, история реплик ассистента и результаты инструментов: всё это клиент может подделать. Дыра была найдена на ревью: классический джейлбрейк в system-промпте плюс «продолжай» от пользователя проходили вообще без вызова модели. Это прямое следствие работ о косвенных инъекциях [12].
Архитектору
Граница доверия проходит по шлюзу, а не по ролям внутри запроса. System-промпт, история и ответы инструментов приходят от клиента, а значит, они такой же недоверенный ввод, как реплика пользователя. Если ваша проверка смотрит только на role: user, её обходит любой клиент, который сам собирает сообщения.
Окна вместо обрезки
Кому особенно полезен раздел:ИнженерыML и исследователи
Длинный вход режется на окна по 3000 символов с перекрытием 300, не больше 10 окон. Они проверяются параллельно, итог — максимум p по окнам. Если окон больше лимита, дешёвый скан ищет паттерны инъекций по всему тексту и ставит фокус-окна вокруг находок. До этого инъекция в середине документа на 20 тысяч символов получала p = 0.000, после — 0.867.
Размер окна подобран замером пяти вариантов как компромисс: маленькие окна лучше ловят локальную инъекцию, но теряют контекст и чаще дают ложные срабатывания.
Политика как данные
Кому особенно полезен раздел:АрхитекторыИнженеры
Текст политики хранится в БД неизменяемыми версиями. Каждая правка создаёт новую версию, её можно проверить на примерах до включения и откатить. Политика двуязычная, из четырёх категорий. В ней есть явный список исключений: художественный текст, единичные персональные данные, свой собственный пароль, учебные материалы по безопасности, заведомо фейковые секреты.
Политика передаётся постоянным префиксом запроса, поэтому radix-кэш SGLang не пересчитывает её на каждом вызове. Кэш на стороне шлюза хранит сырые оценки факторов, а не вердикты. Благодаря этому новые пороги применяются сразу.
Задержка и отказы
Кому особенно полезен раздел:ИнженерыАрхитекторы
- Параллельный запуск. Проверка стартует сразу после выбора маршрута и идёт параллельно с подсчётом токенов и проверкой вложений. Результат нужен только перед вызовом провайдера, так что блокировка срабатывает до первого байта даже на потоковой выдаче.
- Бюджеты времени. 300 мс на окно, 250 мс на судью, общий дедлайн 500 мс. Ожидание слота в очереди считается отдельно от таймаута, и занятость модели не путается с её отказом.
- Fail-open. При недоступности классификатора запрос пропускается, но каждый такой пропуск виден в метрике с алертом. Режим fail-closed под нагрузкой давал ложную блокировку 33% запросов при 3 одновременных и 75% при 8, поэтому его сознательно не поддерживаем.
- Три режима.
off,monitor(проверка в фоне, запрос не ждёт) иenforce(нарушение → HTTP 403).
Fail-open — осознанный риск
Пока классификатор недоступен, вход не проверяется. Компенсация — алерт на каждый такой пропуск и отдельный детектор секретов, который закрыт на отказ (см. ниже).
Ничего лишнего наружу
Кому особенно полезен раздел:АрхитекторыИнженеры
Клиент получает только вердикт, категорию и ссылку на запись в журнале. Ни вероятности, ни причины он не видит: иначе атаку можно было бы подобрать под пороги перебором.
Секреты — не задача классификатора
Кому особенно полезен раздел:АрхитекторыИнженеры
Ключи, токены и пароли ищет отдельный детерминированный детектор. Он работает за линейное время, умеет маскировать и в режимах маскирования и блокировки закрыт на отказ (fail-closed). LLM-классификатор плохо находит секреты, а регулярное выражение с проверкой энтропии — хорошо. При 300 КБ входа на него уходит 10 мс по медиане.
Архитектору
Задачи с точным признаком (формат ключа, энтропия строки) решаются детерминированно и закрыты на отказ. Вероятностной модели остаётся то, что без понимания текста не решить: намерение, инъекции, выгрузка. Так отказ классификатора не открывает дорогу утечке секретов.
Проверьте у себя
- Попадают ли в проверку system-промпт, история ассистента и результаты инструментов, или только последняя реплика пользователя?
- Проверяется ли длинный вход целиком (окнами), или модель видит только обрезанное начало?
- Разделены ли ожидание в очереди и таймаут модели? Иначе под нагрузкой «занято» превращается в «отказ».
- Не уходят ли клиенту вероятность или причина вердикта?
- Видна ли в метриках каждая пропущенная из-за недоступности проверка?
Результаты, ограничения и что дальше
Кому особенно полезен раздел:Бизнес и продуктML и исследователиИнженеры
На контрольном наборе из 58 синтетических кейсов в режиме enforce связка правильно отработала на 56. Оставшиеся два промаха известны и задокументированы.
- Пропуск. Инъекция, спрятанная в HTML-комментарий внутри результата инструмента, получила p = 0.12.
- Ложная блокировка. Пользователь вставил свой собственный пароль (p = 0.97), и запрос заблокирован.
Это регрессионный тест, а не оценка полноты
Набор маленький и искусственный. Он ловит поломки при изменениях, но не говорит, какую долю реальных атак система пропускает.
| Запрос | p50, мс | p95, мс |
|---|---|---|
| Короткий | 40.6 | 45.3 |
| Документ на 20 тыс. символов | 49.7 | 55.2 |
| С флагом риска (вызывается судья) | 48–51 | 56–57 |
В режиме monitor добавка практически нулевая. Сам Shieldstral на 2 тыс. токенов отвечает за 49 мс (p50) одиночно, а при 8 одновременных запросах — уже за 268 мс. Именно поэтому очередь и таймаут разделены.
Ревью первой версии на проде дало три урока, и из них выросла текущая архитектура:
- Обрезка прятала атаки. Около 73% вердиктов выносились по обрезанному входу. Ответ — окна с фокусировкой.
- Проверялась только реплика пользователя. Джейлбрейк через system-промпт проходил. Ответ — весь клиентский ввод считается недоверенным.
- Три отдельных вопроса судье не укладывались в бюджет. Вызовы уходили в таймаут. Ответ — один комбинированный вопрос выбора и вызов судьи только из серой зоны.
Что не сделано и стоит проверить дальше:
- Сравнение на своих данных. Нет офлайн-бенча кандидатов на реальном русскоязычном трафике. Вендорские F1 — это ориентир, а не доказательство.
- Модерация ответов и стримов. Сейчас проверяется только вход. Потоковые модели [9] [10] ждут поддержки в сервинге.
- Скрытые инъекции в разметке. Нужен препроцессинг, который извлекает HTML-комментарии и невидимый текст из результатов инструментов.
- Осознанная детекция, а не отказ. По выводу [8] монитор ценен тем, что ловит сверх отказов базовой модели. Именно эту долю стоит измерить на нашем трафике.
Литература
Кому особенно полезен раздел:ML и исследователи
- Inan H. et al. Llama Guard: LLM-based Input-Output Safeguard for Human-AI Conversations. arXiv:2312.06674.
- Zeng W. et al. ShieldGemma: Generative AI Content Moderation Based on Gemma. arXiv:2407.21772.
- Han S. et al. WildGuard: Open One-Stop Moderation Tools for Safety Risks, Jailbreaks, and Refusals of LLMs. arXiv:2406.18495.
- Padhi I. et al. Granite Guardian. arXiv:2412.07724.
- Zhao H. et al. Qwen3Guard Technical Report. arXiv:2510.14276.
- Kumar P. et al. PolyGuard: A Multilingual Safety Moderation Tool for 17 Languages. arXiv:2504.04377.
- Calvi A. et al. Shieldstral. arXiv:2607.25857. Карточка модели: mistralai/Shieldstral-1.0-3B.
- Karne S. Safety Monitors Mostly Catch What the Model Already Refuses. arXiv:2609.05797.
- Kavumba P. et al. Predict, Don’t React: Value-Based Safety Forecasting for LLM Streaming. arXiv:2604.03962.
- Wang J. et al. FreoStream: Enhancing Stream Guardrails via Future-Aware Reasoning and Safety-Aligned Optimization. arXiv:2606.13737.
- Chen S. et al. StruQ: Defending Against Prompt Injection with Structured Queries. arXiv:2402.06363.
- Greshake K. et al. Not what you’ve signed up for: Compromising Real-World LLM-Integrated Applications with Indirect Prompt Injection. arXiv:2302.12173.
- Tan L. et al. LionGuard 2: Building Lightweight, Data-Efficient & Localised Multilingual Content Moderators. arXiv:2507.15339.
- Krasnodębska A. et al. PL-Guard: Benchmarking Language Model Safety for Polish. arXiv:2506.16322.
- crh225/plumb-4b — карточка модели: дообучение Qwen3.5-4B (через JevK5 v0.2), оценка вариантов ответа за один прямой проход, Apache-2.0.
Названия и первые авторы сверены с arXiv API 25 октября 2026.