1. Проблема стримингового контентного фильтра llm
Guardrail стадии output проверяет ответ модели. На нестриминговом запросе это просто: у шлюза есть полное завершение до того, как вернётся хоть один байт, так что он может block, mask или пропустить его чисто. Стриминг это инвертирует. Ответ приходит как последовательность SSE-дельт, каждая пересылается вашему клиенту, как только приходит, так что фильтр, ждущий конца, не фильтрует ничего. Ответ OrcaRouter — это сканер потока: по мере того как дельты вывода текут, сканер прогоняет ваши правила стадии output по накапливающемуся тексту и действует в тот миг, когда правило срабатывает — не после того, как поток завершится. Действие, которое вы создаёте, решает, что значит «действует»:block режет поток, а flag пропускает его. mask
действительно редактирует на нестриминговом выводе, но переписывание
потока in-band в дорожной карте — на потоке сегодня сканер вычисляет
маску, но действует только на решении block, так что правило mask пока
не редактирует стримированный ответ.
Эта оговорка важна только для правил стадии output на
стриминговых запросах. Правила стадии input проверяют запрос до
запуска модели, так что они полностью живы, включая маскирование — и
любое правило output на нестриминговом запросе видит весь ответ и ведёт
себя нормально, включая
mask.2. Что stream-safe сегодня
block — stream-safe (режет поток на лету)
block — stream-safe (режет поток на лету)
Правило
block применяется на стриминговом и нестриминговом
выводе. На потоке сканер наблюдает за дельтами; когда правило block
срабатывает, оно режет поток — запечатывает сканер, выдаёт
короткое уведомление-замену ([response truncated by guardrail: … policy violation]) как финальную дельту и закрывает SSE-канал прежде,
чем дальнейший заблокированный контент дойдёт до клиента. Поскольку
HTTP-статус ответа уже зафиксирован на 200 к моменту сброса первой
дельты, блокировка посреди потока не может переиздать статус — она
грациозно завершает открытый поток. Тело HTTP 400 guardrail_blocked
— это форма блокировки output на нестриминге.Байты, уже сброшенные клиенту, нельзя отозвать, так что блокировка на
стриминге работает по мере возможностей над тем, что уже
отстримилось, но надёжно останавливает всё после совпадения. Для
жёсткой гарантии, что ни один нарушающий байт никогда не отправляется
— и для тела 400 guardrail_blocked — отправляйте запрос
нестриминговым.mask — только нестриминговый вывод (переписывание потока in-band в дорожной карте)
mask — только нестриминговый вывод (переписывание потока in-band в дорожной карте)
Правило
mask переписывает совпадение — например, email в ответе
становится [EMAIL] — на нестриминговом выводе, где шлюз держит
всё завершение и пересылает отредактированную форму вашему клиенту.На стриминговом выводе сегодня сканер вычисляет маску, но не
пересылает замаскированный текст — он действует только на решении
block — так что правило mask не редактирует стримированный
ответ. Переписывание стримингового вывода in-band в дорожной карте.
Пока оно не зашипится, если вам нужно, чтобы стримированный ответ
никогда не раскрывал совпавший текст, создайте правило как block
(оно завершает ответ на попадании) или отправьте запрос
нестриминговым, чтобы маска переписала весь ответ.flag — только наблюдение, никогда не меняет трафик
flag — только наблюдение, никогда не меняет трафик
Правило
flag никогда не меняет трафик — оно пропускает байты. На
нестриминговом выводе оно записывает совпадение в ленте
Matches, так что вы можете измерить частоту срабатываний правила,
прежде чем продвинуть его в block. На стриминговом ответе оно
остаётся только наблюдением и пропускает дельты нетронутыми;
структурированная запись совпадения пишется на пути нестримингового
вывода. В любом случае оно никогда не блокирует и не переписывает, так
что его всегда безопасно оставить включённым.Действие на output | Нестриминг | Стриминг |
|---|---|---|
block | отклоняет ответ | режет поток |
mask | редактирует ответ | пока нет — block вместо (дорожная карта) |
flag | записывает совпадение | пропускает (только наблюдение) |
3. Один конкретный пример — stream-safe фильтр секретов
Скажем, ваша модель может вытащить учётные данные из RAG-контекста, и ваше приложение стримит. Вы хотите, чтобы шлюз убил поток в тот миг, когда появляется совпадение в форме секрета, а не маскировал его — утёкший секрет должен завершить ответ, а не быть частично отредактированным. Создайте это в консоли — редактирование политики — действие управления на вашей сессии, шлюзованное до Developer+; relay-ключ только отправляет трафик/v1/*:
- Откройте
/console/guardrails, New guardrail, назовите егоstream-safe-out. - Добавьте одно правило:
- Тип:
regex(или правилоpiiс сущностями секретов вродеaws_access_key/api_key_openai/jwt) - Стадия:
output - Действие:
block← завершает ответ на попадании секрета;maskвместо этого отредактировал бы его и дал бы остальному ответу продолжиться
- Тип:
- Сохраните, затем привяжите его на
/console/tokenчерез выпадающий список Guardrail ключа.
stream: true, ровно как раньше:
4. PII Shield на потоке
Пресет PII Shield — это единственное правилоpii, действие mask,
стадия both. На стадии input оно полностью живое — оно переписывает
запрос до того, как модель его увидит, со стримингом или без. На стадии
output маскирование редактирует на нестриминговых ответах, где
шлюз держит всё завершение до возврата.
На стриминговом выводе маска пока не редактирует — сканер
вычисляет маску, но действует только на решении block, так что
стримированный ответ пропускается, а не переписывается. Переписывание
стримингового вывода in-band в дорожной карте. Так что если ваша цель —
чтобы PII никогда не была наблюдаема в стримированном ответе, либо:
- создайте правило output как block, приняв, что попадание завершает ответ, а не редактирует его, либо
- отправьте запрос нестриминговым, чтобы маска переписала весь ответ с целым завершением в руках.
5. Докажите это перед шипом
Не угадывайте, какая комбинация стадии/действия держится — проверьте её.Вкладка Test
У каждого редактора guardrail есть вкладка Test: вставьте образец,
выберите стадию
output и прогоните текущую политику без вышестоящего
вызова и без квоты. Увидьте вердикт и, для правил mask,
отрендеренный текст. Запуск песочницы — действие Developer+ (она
может запускать платные правила judge / external).Вкладка Eval
Вкладка Eval оценивает guardrail против поставляемых или
пользовательских JSONL-корпусов — полезно, чтобы подтвердить, что
правило block ловит известную утечку по корпусу, прежде чем привязать
ключ.
6. Что стоит блокировка на стриминге
Блокировка на стриминге несёт тот же учёт, что и любая блокировка output — вышестоящая модель уже отработала, так что шлюз ведёт возврат за вас:- Поток завершается грациозной дельтой усечения (статус уже 200);
блокировка output на нестриминге возвращает тело HTTP 400
guardrail_blocked, называющее guardrail и сработавшее правило. - Квота не списывается. Когда блокировка output отклоняет ответ, шлюз возвращает предварительно списанную квоту, так что заблокированный вызов для вас бесплатен, даже если модель произвела токены.
- Запрос помечается skip-retry — повторный прогон того же промпта просто снова заблокировался бы, так что шлюз не будет сжигать повтор на другом канале.
GET /api/guardrail/match, открыта любому Member); совпавшая
подстрока захватывается только когда у guardrail включён переключатель
Log raw content (по умолчанию выключен). Полная деталь живёт в
ошибке guardrail_blocked
и ленте matches.
7. Куда двигаться дальше
Стадия output
Полная стадия output — проверка ответа модели, block против mask и
grounding.
Покрытие стриминга
Полная матрица того, что применяется на стриминге против нестриминга
по каждой стадии и действию.
Действия
block, mask и flag в деталях — когда каждое правильный выбор.
Стадия input
Зеркальное отражение — маскирование здесь полностью живое, включая на
стриминге.
Связанные концепции
Связанные концепции
Угрозы, которые это адресует
Угрозы, которые это адресует
Полный справочник движка
Полный справочник движка
Guardrails — каждый тип правила, поле и
маршрут, включая grounding и LLM judge.
