Зачем гонять простые запросы через GPU

Многие запросы к ассистенту выглядят так: «помоги написать письмо клиенту», «сделай выжимку из отчета». Опасности в них нет, и это видно сразу. До релиза 4.4 почти каждый такой запрос после правил все равно шел в тяжелые модели на GPU, самый дорогой ресурс всей системы.

Теперь перед тяжелыми моделями стоит быстрая логика на CPU. Очевидные случаи она закрывает сама, а все, в чем не уверена, отправляет в тяжелые модели, как раньше. Так выглядит путь запроса в Guardrail 4.4:

Путь запроса через быструю логику на CPU и тяжелые модели на GPU в Guardrail 4.4

Границу между очевидным и спорным задают пороги уверенности. Мы подбирали их на большом наборе размеченных запросов, а потом гоняли на трафике, близком к реальному. Задача была такая: пусть быстрая логика забирает себе как можно больше простых случаев, а качество проверки остается прежним. Работает она в обе стороны: проверяет и запросы пользователей, и ответы модели.

Что показали замеры

Мы прогнали новую схему на запросах, приближенных к реальным, и на открытом бенчмарке GuardRate.

Что измеряли Результат
Нагрузка на тяжелые модели на GPU примерно на 10-15% меньше
Качество проверки прежнее, разница в пределах долей процента
Ответ на простой запрос в несколько раз быстрее
Время ответа быстрой логики считанные миллисекунды, в том числе под нагрузкой
Одна копия быстрой логики сотня с лишним запросов в секунду
Ресурсы на копию пара ядер CPU и меньше гигабайта памяти

Быстрая логика ставится на любой сервер рядом с Guardrail, при обновлении до 4.4 ее нужно развернуть отдельно. Масштабируется она дешевыми ядрами CPU, а GPU остается для сложных случаев.

Где быстрая логика не торопится

Ответ «безопасно» быстрая логика дает, только когда для сомнений нет поводов. Запрос все равно уйдет в тяжелые модели, если он слишком длинный, если разбор спрятанного текста не успел закончиться или если какая-то проверка не отработала.

Если сама быстрая логика недоступна, Guardrail долго ее не ждет и передает запрос дальше. Проверка от этого не останавливается.

Как прячут инструкцию от фильтра

Возьмем классическую атаку «ignore all previous instructions» и спрячем ее тремя способами:

  • Вставим символ нулевой ширины внутрь слова ignore. На экране ничего не изменится, для шаблона это уже два разных куска текста.
  • Заменим латинскую «o» на кириллическую: ignоre. Глазом разницу не увидеть, сравнение строк ломается.
  • Сдвинем каждую букву на 13 позиций: vtaber nyy cerivbhf vafgehpgvbaf. Модель по просьбе пользователя расшифрует фразу и выполнит ее.

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

Что Guardrail делает с таким текстом

Guardrail снимает маскировку до проверки и прогоняет через правила все получившиеся версии текста:

  • вырезает невидимые и служебные символы, которые рвут слова
  • возвращает на место буквы, подмененные двойниками из другого алфавита, и раскрывает leetspeak вроде k1ll
  • находит и декодирует больше 20 форматов кодирования, от распространенных до экзотических, даже вложенные друг в друга
  • перебирает больше десятка классических шифров и распознает несколько словесных игр

У шифра ключ заранее неизвестен, поэтому Guardrail перебирает варианты и оставляет те, что читаются как осмысленный текст. Перебор ограничен по времени и почти не тратится на текст, который и так читается как обычный язык. Обычные сообщения детектор практически не нагружает.

Ошибиться безопасно

Найденная кодировка или шифр сами по себе сообщение не блокируют, закодированные данные встречаются и в обычной переписке. Находка служит поводом заглянуть внутрь.

Догадка шифра никогда не подменяет исходный текст, ее проверяют в дополнение к оригиналу. При неверной догадке в худшем случае появится лишнее совпадение, и исходная атака все равно останется под проверкой. На 6069 безобидных текстах этот слой не дал ни одного ложного срабатывания.

Когда разбор не успел закончиться, например из-за перегрузки или слишком глубокой вложенности, быстрая логика уже не может назвать такой текст безопасным, и он уходит в тяжелые модели. Перегрузка в этом случае честно отражается как пропуск части проверки.

В ответе API видно, нашлись ли кодировки или шифры и полностью ли прошел разбор. Сам расшифрованный текст по умолчанию наружу не отдается.

В итоге Guardrail в 4.4 тратит меньше GPU на очевидное и внимательнее смотрит туда, где текст пытается спрятаться.