
В прошлом году я уже рассказывал об AVI (Aligned/Agreement Validation Interface) — концепции внешнего, гибкого и независимого от модели фильтра, который работает как умный файрвол для LLM: отбивает промпт-атаки на входе, проверяет ответы модели на токсичность, этичность и нарушение закона — на выходе. Недавно мы доработали свою концепцию с точки зрения архитектуры, реализовали и выложили на GitHub рабочий сервис на Python и FastAPI: входной и выходной фильтры, RAG-модуль, докер-сборку с мониторингом (Prometheus, Grafana, Jaeger), а также инструментарий для воспроизведения экспериментов на FinanceBench.
Под катом расскажу, к какой архитектуре системы мы пришли, как сделали так, чтобы новые правила для фильтрации можно было добавлять одной фразой на естественном языке, как AVI показал себя в тестах и помогает экономить на обучении ИИ-моделей.
А по-научному и подробно все описано в журнале MDPI.Electronics (на английском).
Бизнес-проблема: дообучать модель ради одного правила дорого и долго
Когда мы продаем большие языковые модели в банки, страховые, медицину, заказчики всегда выдают нам длинный список того, что модель НЕ должна:
-
давать советов по криптовалюте;
-
называть финансовые показатели до выхода квартального отчета;
-
общаться на политически острые темы;
-
раскрывать персональные данные;
-
делать что-либо из длинного списка того, что запрещено законом и здравым смыслом.
Классический способ — дообучить модель на датасетах алайнмента с инструкциями и заглушками. И тут начинается боль для ИИ-тренеров и финансовых директоров. Один полный цикл дообучения модели для одного правила — это около 2 тыс. долларов и 10 дней на прогон. За это время правила обычно успевают поменяться. То есть, к моменту выхода в прод модель уже успеет устареть.
Тут вы скажете, что мир же уже изобрел LlamaGuard и NeMo Guardrails – и будете правы. Первый — это классификатор-детектор. Он смотрит на вход пользователя и ответ модели и помечает, нарушает ли контент заданные правила безопасности (например, насилие, мошенничество, нецензурная лексика). Работает как «фильтр на входе/выходе».Второй — это фреймворк для программируемых ограничений. Он позволяет задавать сценарии (rails), которые ограничивают темы, блокируют действия, перенаправляют диалог или меняют тональность.
Однако и LlamaGuard, и NeMo Guardrails работают с фиксированным набором запретов и плохо донастраиваются под конкретную компанию. Получается, что с ними может работать только команда квалифицированных ML-инженеров, которые разбираются в архитектуре нейросетей. Нам же очень хотелось освободить дорогих и вечно занятых ML-специалистов от этих задач и сделать так, чтобы новые правила для моделей мог задавать любой юрист, комплаенс-менеджер и кто-угодно, кому больше надо, без погружения внутрь нейросети.
Как работает AVI
AVI (Agreement Validation Interface) работает как программа-посредник между человеком и моделью: проверяет, что человек написал в запросе и что модель собирается ответить. Если в запросе или в ответе всплывает что-то, нарушающее правила, AVI это блокирует.
Как это работает
1. Пользователь пишет запрос модели.
2. Фильтр на входе сверяет запрос с базой правил.
3. Если запрос проходит, он идет в модель.
4. Ответ модели проверяет фильтр на выходе.
5. Если все чисто — пользователь получает ответ.
Архитектура AVI вдохновлена LlamaGuard, и NeMo Guardrails, но есть нюансы. Это смещение точки контроля со скриптовой логики (как в NeMo) или статического классификатора (как в LlamaGuard) к динамическому поиску по базе векторно-закодированных правил. Эта база может быстро обновляться и дополняться людьми без ML-экспертизы, модель может извлекать из нее правила и подмешивать в контекст через RAG.
Это можно записать так:
где
и
— Input/Output Governors,
— векторный индекс политик,
— извлечённые правила, которые подмешиваются в контекст модели.
Главное – сами правила лежат не внутри модели, а в отдельной базе, которую можно легко дополнить. Хочешь запретить обсуждать криптовалюту — пишешь обычной фразой на русском: «не обсуждай криптовалюту, не давай советов по инвестициям в нее, не приводи примеры курсов». Загружаешь в базу — и через пару секунд правило начинает работать в проде.
Суммирую ключевые фичи:
-
Governance вынесен наружу. Никакого RLHF и новых весов под каждое правило — только индекс в векторной базе.
-
Двусторонний фильтр: правила применяются и до того, как модель что-то сгенерировала, и после.
-
Time-to-Compliance — меньше пяти секунд: новое правило начинает работать в проде сразу после индексации.
-
Корпус политик можно «прицепить» к разным LLM, нужна только разовая калибровка порогов.
Про архитектуру
Фильтр AVI реализован в виде микросервиса на Python 3.11 с использованием шлюза FastAPI. Ядро механизма управления составляет конвейер поиска, который включает три ключевых компонента:
-
модель эмбеддинга,
-
векторную базу данных,
-
стратегию индексации.
Для преобразования текстовых политик и запросов в векторы используется современная модель-трансформер ‘deepvk/USER-bge-m3’ с размерностью 1024 измерения.
В качестве векторного хранилища применяется Qdrant, выбранный за эффективную реализацию алгоритма HNSW для ANN-поиска. Для обработки длинных документов (более 100 страниц) мы используем рекурсивную стратегию чанкинга: документы разбиваются на семантические единицы с контекстным окном до 8192 токенов, что позволяет извлечь точные фрагменты политик и повысить точность следующей генерации.
Фильтр на входе
Когда приходит запрос, система не буферизирует весь пользовательский ввод, а работает по принципу скользящего окна:
-
Входной поток токенов разбивается на небольшие окна — подпоследовательности.
-
Для каждого окна вычисляется векторное представление.
-
Если сходство (косинусное расстояние) этого вектора с любым правилом из индексной базы превышает заданный порог τ — фиксируется нарушение.
Ключевое преимущество нашего подхода — раннее прерывание инференса (Early Breaking). Система может остановить инференс модели сразу при обнаружении нарушения в любом окне. Это позволяет:
-
Предотвратить генерацию запрещенного контента.
-
Сэкономить вычислительные ресурсы.
-
Обеспечить структурную защиту от промпт-инъекций.
Еще мы добавили в AVI возможность настраивать чувствительность фильтра для каждого правила или категории правил. Это делает наш фильтр эффективнее статических классификаторов.
Если поставить общий порог чувствительности на все категории правил одновременно, будет почти невозможно подобрать значение. Если поставить τ низким, жесткие правила будут работать отлично, но мягкие начнут цепляться к безобидным вопросам. Если τ будет высоким, наоборот, мягкие правила будут работать хорошо, а жесткие начнут пропускать опасные сообщения.
В итоге мы сделали свой регулятор чувствительности для каждой категории правил. Жесткие правила настроены так, чтобы лишний раз перестраховаться. Мягкие – не дергаются на каждую запятую. Настройки проводит человек со стороны бизнеса – тот, кто знает, что именно компания не хочет видеть в ответах.
Задержку удалось снизить, но это только половина истории — не менее важно правильно откалибровать сам порог срабатывания фильтра τ. Слишком низкий порог ловит всё подряд вместе с безобидными запросами, слишком высокий — начинает пропускать опасные. Вот как разные значения τ влияют на баланс между полнотой обнаружения и точностью:
Лирическое отступление — про грабли
Когда мы только сделали фильтр, все работало процентов на семьдесят. Модель распознавала, что запрос опасный, и начинала ответ с «не могу назвать точную цифру…». А в следующем предложении эту цифру все равно давала — просто потому, что помнит ее из обучения. Фильтр срабатывал, но правило все равно нарушалось.
Чтобы это вылечить, нужно прикладывать модели отдельную четкую инструкцию: не раскрывать значение, не вычислять, не приводить аналогию, не давать «примерную оценку». Фильтр видит опасные запросы, а инструкция жестко запрещает обходные пути. Без отдельной инструкции модель все равно найдет способ ответить.
Фильтр на выходе
Второй фильтр мы поставили на выходе. Ответ модели еще раз сверяется с базой правил. Это страховка для случаев, когда запрос выглядел невинно, а модель в процессе все-таки выдала лишнее. Поверх всего этого — кэш на похожие запросы. Если кто-то уже задавал примерно такой же вопрос, ответ выдается тут же, минуя и фильтры, и саму модель.
Что получилось на тестах
Мы тестировали AVI на двух разных аппаратных конфигурациях, чтобы оценить эффективность использования ресурсов и возможность развертывания.
Первая — на GPU (NVIDIA A100 с 80 ГБ VRAM), где под инференс и эмбеддинг выделено 8 ГБ памяти. Вторая — на CPU (Apple M1 Pro) с 16 ГБ унифицированной памяти. Так мы эмулировали сценарий локального или edge-развертывания, когда специализированное GPU-оборудование недоступно.
Прирост в 19,5 п.п. на FinanceBench — усреднённая цифра по всему бенчмарку. Интереснее посмотреть, как фильтр справляется с разными типами небезопасного контента по отдельности — для этого мы прогнали AVI на закрытом русскоязычном датасете провокационных запросов MWS AI и разбили результаты по категориям:
Качество AVI проверяли на двух бенчмарках: публичном финансовом FinanceBench — 150 запросов, 3 прогона, итого 450 наблюдений — и закрытом русскоязычном датасете провокативного контента от MWS AI — 201 запрос и инструкции из 1000 русскоязычных правил модерации. В качестве модели, которую проверяли в связке с AVI, мы взяли MWS AI Cotype Pro 2.5, а для бейзлайна — GPT-4o с обычным RAG без AVI.
Метрики считали автоматически (LLM-as-a-Judge — GPT-4o-mini при temperature=0.0) по трем осям: Compliance 0.6, Helpfulness 0.3, Naturalness 0.1. «Compliant» — это ≥ 7/10 по компоненте Compliance.
Результаты тестов в цифрах:
Compliance Rate на FinanceBench:
-
83.2% (95% CI 79.4–87.1%) против 63.7% (CI 62.1–65.3%) у бейзлайн-модели.
-
Δ = +19.5 п.п., t = 4.02, p = 0.002 — статистически значимо.
Детекция входным фильтром на FinanceBench: Precision = Recall = F1 = 1.000.
Helpfulness: 0.812 (CI 0.798–0.826), то есть полезность не схлопнулась.
Кросс-домен (русскоязычный провокационный контент):
-
Recall = 0.985 (134 из 136 запросов заблокировано);
-
комплаенс на сработавших правилах = 0.977.
По категориям в русскоязычном датасете F1:
-
Hate Speech — 0.957,
-
Illegal Requests — 0.965,
-
Self-Harm — 0.983,
-
Extremism — 0.972,
-
Privacy Violation — 0.800,
-
Misinformation — 0.950.
Латентность на A100:
-
−72.5% по сравнению с беизлайном за счет Early Breaking;
-
на CPU (Apple M1 Pro в Docker) — 25 секунд cold-start governed.
Time-to-Compliance:
-
индексация одного правила — менее 5 секунд;
-
полный цикл «правило → прод» с участием человека — порядка 10 минут против 10–24 часов на файнтьюне.
Интересный факт: на русскоязычном датасете overall Precision просел до 0.684 при FPR = 0.954. Это не сломанная архитектура, а калибровочный артефакт: 1 000 правил создают такое плотное «облако» в эмбеддинг-пространстве, что почти любой запрос задевает хоть одно из них. Повышение порога θ с 0.40 до 0.55 опускает FPR до ~0.31 при сохранении Recall ≥ 0.95. То есть проблема решается через настройку τ.
Отдельно мы вручную разобрали 84 случая «non-compliant» и собрали таксономию ошибок: 45.2% — Numeric Leak (модель назвала запретную цифру), 36.9% — Exact Leak (точная утечка формулировки), 11.9% — Context Leak (правило ушло через контекст), 6.0% — Derivative (производная утечка через аналогию). Между двумя ручными аннотаторами Cohen’s κ = 0.82 — то есть таксономия не «на глаз», а согласованная.
Что это меняет для бизнеса
Для нас важно, что мы снимаем с разработчиков моделей часть ответственности за соблюдение правил и передаем ее самой компании, которая лучше знает свои регламенты.
В банке появляется человек, который без ML-инженера, добавляет правило фразой на русском, проверяет, что оно работает, и катит в прод. То же самое в страховой, в медцентре, в юридической фирме. Соблюдение требований перестает быть квартальным проектом и превращается в обычный рабочий процесс.
Что дальше
Мы выложили на GitHub полный код сервиса — input/output-фильтры, RAG-модуль, docker-compose со стеком мониторинга и Gradio-интерфейсом для тестирования, а также инструментарий, который воспроизводит эксперимент на FinanceBench — от скачивания датасета до генерации графиков из статьи. Правила модерации в репозитории — это шаблон CSV с несколькими примерами; собственно корпус из тысячи правил и датасет для кросс-доменного теста на русском остаются внутренними и не публикуются.
Что собираемся делать дальше:
-
Создать отдельные наборы правил под медицину и юриспруденцию, где регуляторика самая плотная.
-
Продумать защиту от атак, когда опасный запрос разбит на несколько безобидных сообщений в разных репликах.
-
Разработать готовые шаблонные отказы вместо тех, что генерирует сама модель, — это ускорит ответ еще больше.
-
Добавить калибровку порогов чувствительности в полуавтоматическом режиме, чтобы при переносе правил на другую модель не приходилось все крутить руками.
Автор: Lhody


