- Дата публикации
PII Shield от Microsoft: как не сливать персональные данные в каждый запрос к LLM
Что нового
Microsoft представила PII Shield — прослойку между вашим приложением и любым LLM, которая автоматически анонимизирует персональные данные в каждом запросе и восстанавливает их в ответе.
Ключевые новшества:
-
«Сэндвич»-паттерн для любого LLM-запроса
Запрос проходит через/anonymize, все PII заменяются плейсхолдерами вида{{PERSON_1}}, LLM видит только их. После ответа приложение отправляет текст на/deanonymize, и PII Shield подставляет реальные значения обратно. -
REST API и библиотека в одном пакете
- REST-эндпоинты:
/anonymize,/anonymize_unique,/deanonymize,/apps,/apps/{id}/config. - Режим библиотеки:
pip install pii_shieldи вызов движка напрямую из Python для батчевых задач.
- REST-эндпоинты:
-
Глубокая поддержка индийских идентификаторов плюс 100+ стандартных типов PII
Помимо Presidio по умолчанию, есть кастомные детекторы для:- Aadhaar (с проверкой контрольной цифры по Verhoeff),
- PAN,
- водительских удостоверений всех 36 штатов Индии,
- PIN-кода,
- UPI ID,
- индийских телефонов,
- банковских счетов, IFSC, CKYC, PRAN, APAAR, геокоординат, естественных дат и др.
-
Выбор стратегии по каждому типу сущности
Для каждого типа PII можно задать отдельное действие:replace— плейсхолдеры{{PERSON_1}},{{EMAIL_ADDRESS_2}}(полностью обратимо),hash— SHA-256 (необратимо, подходит для аналитики),encrypt— шифрование с ML-KEM-768 + AES-256-GCM (постквантовый KEM + симметричное шифрование),fake— генерация реалистичных, но вымышленных значений через Faker (необратимо, удобно для демо и тестов).
-
Постквантовая криптография по умолчанию
Для шифрования PII используется ML-KEM-768 (NIST-стандартизованный постквантовый KEM) + AES-256-GCM. Есть обратная совместимость с Fernet. -
Мультиарендность на уровне конфигурации
Приложения регистрируются черезPOST /apps, маршрутизация по заголовкуX-App-Id. Для каждого приложения — свои стратегии по сущностям, свои ключи шифрования, свои allow-листы. -
Наблюдаемость «из коробки»
OpenTelemetry-трейсы, метрики и логи для каждого запроса. Поддержка OTLP-выгрузки сразу в два бэкенда: локальный стек Grafana LGTM и Azure Monitor. В комплекте — готовые Grafana-дэшборды: p95/p99 задержки, счётчики сущностей, ошибки по приложениям. -
Готовые UI
Две Streamlit-панели:- Playground — визуальное тестирование: вставили текст, выбрали NLP-бэкенд, сразу видите, что нашлось и как заанонимизировалось.
- Admin UI — настройка приложений, стратегий по сущностям, allow-листов и просмотр живой статистики.
-
Гибкая NLP-подложка
PII Shield использует Microsoft Presidio с подключаемыми NLP-бэкендами:- spaCy — самый быстрый вариант на CPU,
- ONNX — ускоренные квантованные модели,
- Stanza — повышенная полнота обнаружения,
- Hugging Face Transformers — state-of-the-art модели, включая IndicNER для индийских данных.
-
Батч-обработка файлов
В режиме библиотеки доступен BatchProcessor для CSV и DataFrame с потоковой и процессной параллелизацией — для офлайн-пайплайнов и разовых прогонов.
PII Shield можно развернуть локально или в любом облаке. В примере для Azure используются Container Apps, Azure Cache for Redis, Application Insights, Log Analytics и Azure Managed Grafana.
Как это работает
PII Shield строится вокруг трёх вещей: сущностей, распознающих модулей (recognizers) и «сэндвич»-паттерна.
Сущности и распознаватели
Сущность — это единый фрагмент PII в тексте:
PERSON, EMAIL_ADDRESS, PHONE_NUMBER, CREDIT_CARD, IBAN_CODE, LOCATION, IN_AADHAAR, IN_PAN, IN_DRIVING_LICENSE, IN_UPI_ID и т.д.
Каждая сущность содержит:
- тип (например,
PERSON), от которого зависят формат плейсхолдера и стратегия анонимизации; - позицию в исходном тексте — смещения начала и конца, чтобы заменить ровно нужный фрагмент;
- confidence-оценку 0.0–1.0, чтобы отсеивать шум и выбирать лучший из пересекающихся вариантов;
- стабильный идентификатор внутри запроса: все вхождения одного и того же значения («Rahul Sharma») сводятся к одному плейсхолдеру
{{PERSON_1}}, а не{{PERSON_1}}и{{PERSON_2}}. Это сохраняет кореференцию при проходе через LLM.
Распознаватель — компонент, который находит сущности в тексте. PII Shield использует три типа распознавателей, которые работают совместно:
-
NLP-распознаватели
Опираются на языковую модель Presidio Analyzer (spaCy / ONNX / Stanza / Transformers). Нужны для сущностей без фиксированного формата:PERSON,LOCATION,ORGANIZATION,NRP. Пример: строка «Rahul встретился с Priya в Bengaluru» не ловится регулярками, модель должна понять, что это два человека и место. -
Pattern-распознаватели
Небольшие Python-классы, расширяющиеPatternRecognizer, которые объединяют:- один или несколько regex-паттернов (формат 12-значного Aadhaar, структура PAN
AAAAA9999A, номера прав с префиксом штата и т.п.); - список контекстных ключевых слов (
aadhaar,uidai,licence,dl,pan,card,dob), которые повышают уверенность, когда встречаются рядом; - базовую confidence-оценку и опциональный валидатор для идентификаторов с контрольной суммой (Verhoeff для Aadhaar, mod-97 для IBAN и др.).
Логика простая:
- regex говорит «это может быть Aadhaar»,
- контекст «рядом есть слово
aadhaar— уверенность растёт», - валидатор «контрольная сумма сошлась — принимаем».
Такая многоступенчатость снижает ложные срабатывания на «шумных» данных: CRM-заметки, переписки, логи.
- один или несколько regex-паттернов (формат 12-значного Aadhaar, структура PAN
-
Гибридные / deny-list распознаватели
Работают поверх остальных. Подходят для внутренних списков кодовых имён проектов, форматов внутренних клиентских ID и других бизнес-специфичных сущностей.
Analyzer Presidio запускает все распознаватели, каждый оценивает свои кандидаты. Пересекающиеся сущности объединяются: выигрывает наибольшая уверенность, более длинные спаны поглощают короткие. На выходе — список кортежей (entity_type, start, end, score), который получает анонимизатор.
Новые распознаватели добавляются через YAML-конфигурацию.
«Сэндвич»-паттерн
PII Shield оборачивает каждый вызов LLM двумя тонкими слоями:
-
Верхний слой — анонимизация
Приложение отправляет исходный текст в/anonymizeили/anonymize_unique. PII Shield находит все PII и заменяет их на стабильные, непрозрачные плейсхолдеры ({{PERSON_1}},{{EMAIL_ADDRESS_2}}и т.д.) ещё до выхода за границы доверенной инфраструктуры. -
Средний слой — LLM
LLM видит только плейсхолдеры. Для него{{PERSON_1}}и{{IN_AADHAAR_1}}— просто имена собственные. Он рассуждает над ними, не зная исходных значений. -
Нижний слой — деанонимизация
После ответа LLM приложение отправляет текст и session ID в/deanonymize. PII Shield подставляет реальные значения обратно.
Единственный компонент, который знает исходные PII, — это краткоживущая мапа «плейсхолдер → оригинал» в Redis. Кореференция сохраняется, потому что {{PERSON_1}} остаётся одним и тем же человеком во всех местах запроса и, как правило, ответа.
Зашифрованные сущности обрабатываются отдельно: по умолчанию используется ML-KEM-768 + AES-256-GCM.
Высокоуровневая архитектура
1. Пользователь / клиентское приложение
Пользователь пишет в чат-бот или агент. Он не знает о слое редактирования: на экране всегда полные, восстановленные данные.
2. AI-приложение (агент / RAG / чат)
Это ваш GenAI-сервис — бот, агентный сценарий, RAG-пайплайн. Логика принадлежит ему, но он никогда не шлёт сырой текст в LLM. Вместо этого он всегда идёт через PII Shield и пересылает дальше только анонимизированный текст.
3. PII Shield (FastAPI)
Центральный stateless-сервис, через который проходят все запросы. Это естественная точка для:
- применения политики,
- rate limiting,
- аудита,
- инструментирования.
Внутри несколько слоёв:
-
REST API
POST /anonymize_unique— детект + редакт за один вызов, возвращает session ID,POST /deanonymize— восстановление по session ID,/appsи/apps/{id}/config— регистрация приложений и настройка стратегий,- плюс health-check, метрики и OpenAPI-спека.
-
Presidio Engine
Сердце детекта и редактирования. Работает в два этапа:- Analyze: запуск выбранного NLP-бэкенда (spaCy / ONNX / Stanza / Transformers) и кастомных распознавателей (
IN_AADHAAR,IN_PAN,IN_IFSC,IN_UPI_ID,IN_BANK_ACCOUNT,IN_PHONE,IN_PIN_CODE,CKYC,PRAN,APAAR,GeoCoordinate,NaturalDateи др.). Каждый спан получает score и усиливается контекстными словами. - Anonymizer: применение операторов по сущностям:
replace,hash,encrypt,fake.
- Analyze: запуск выбранного NLP-бэкенда (spaCy / ONNX / Stanza / Transformers) и кастомных распознавателей (
-
State Stores (Redis)
Два логических хранилища, оба на Redis, но с разной семантикой:- Session Mapping Store — краткоживущие записи
UUID → entity-mapдля «сэндвича» (анонимизировать → LLM → деанонимизировать). TTL по умолчанию — секунды или минуты, чтобы plaintext PII не задерживались. - App Registry — долговременная конфигурация приложений: стратегии по сущностям, списки разрешённых сущностей, ссылки на ключи шифрования, allow-листы вымышленных брендов. Это обеспечивает мультиарендность.
- Session Mapping Store — краткоживущие записи
-
Telemetry
OpenTelemetry SDK оборачивает каждый этап пайплайна:- спан на запрос,
- метрики по количеству сущностей, задержкам анонимизации, попаданиям в кэш,
- структурированные логи с trace-id.
Поток OTLP можно параллельно отправлять в Azure Monitor и в самодельный стек с Grafana.
4. LLM (Azure OpenAI / OSS)
Любая модель: Azure OpenAI (например, GPT-4o), self-hosted OSS, Foundry-развёртывание. Контракт PII Shield гарантирует, что модель видит только анонимизированный текст. Сырая PII не уходит в тенант поставщика LLM.
5. Наблюдаемость (Azure Monitor / OTLP → Grafana)
Сюда стекаются OpenTelemetry-данные. Операторы видят:
- объём запросов по типам сущностей,
- p95/p99 задержки по этапам,
- использование по приложениям,
- разбивку ошибок.
6. Playground и Admin UI (Streamlit)
Обе панели работают поверх того же REST API, что и прод-приложения. Всё, что делает UI, можно повторить из скрипта или CI-пайплайна.
Пример потока запроса
- Пользователь пишет в банковский чат-бот: номер счёта, Aadhaar, телефон.
- Приложение отправляет сырой текст в PII Shield на
/anonymize_unique. - PII Shield:
- находит все PII,
- заменяет их на плейсхолдеры,
- сохраняет mapping в Redis с коротким TTL,
- отдаёт приложению анонимизированный текст + session ID.
- Приложение вызывает LLM с этим текстом. Модель никогда не видит реальные Aadhaar, счёт или телефон.
- После ответа LLM приложение отправляет ответ + session ID на
/deanonymize. - PII Shield подставляет реальные значения и возвращает результат приложению.
- Пользователь видит естественный диалог с собственными данными. Mapping в Redis автоматически удаляется по истечении TTL.
- Параллельно все этапы шлют трейсы, метрики и логи в стек наблюдаемости.
Что это значит для вас
Для чего использовать
PII Shield полезен везде, где LLM неизбежно сталкиваются с персональными и чувствительными данными:
-
Банковские и финтех-приложения
Чат-боты поддержки, ассистенты для операторов, RAG по CRM-документам, в которых встречаются номера счетов, карты, IBAN, Aadhaar, PAN и т.д. -
Медицина и страхование
Сценарии, подпадающие под HIPAA и аналогичные требования: истории обращений, результаты анализов, обращения пациентов. -
Госуслуги и госкомпании
Работа с Aadhaar, UPI, паспортами, водительскими правами и другими национальными идентификаторами. -
Внутренние ассистенты в корпорациях
Поиск по почте, CRM, тикетам поддержки, документам HR, где много имён, адресов, телефонов и внутренних ID. -
Аналитика и дата-сайенс
Когда нужно прогнать через LLM большой массив данных, но требования GDPR, DPDP или локальные нормы запрещают отдавать сырую PII стороннему провайдеру.
В чём практическая польза
-
Снижение регуляторных рисков по умолчанию
EU AI Act, индийский DPDP Act, CCPA, HIPAA, PCI-DSS и отраслевые регуляции всё чаще отдельно оговаривают AI-пайплайны. PII Shield строит границу: сырая PII не выходит за пределы вашей инфраструктуры, а в tenancy провайдера LLM попадает только анонимизированный текст. -
Один слой вместо десятков «заплаток»
Вместо набора регулярных выражений в каждом сервисе вы получаете единый, хорошо протестированный слой, через который проходят все AI-запросы. Политику меняете один раз — она применяется ко всем приложениям. -
Сохранение качества ответов LLM
Плейсхолдеры стабильны и консистентны ({{PERSON_1}}везде означает одного и того же человека). Кореференция и логика в ответах не рушатся, LLM нормально рассуждает о сущностях, даже не зная их реальных значений. -
Прозрачная интеграция
Приложение продолжает использовать свои промпты и тот же API LLM. Меняется только маршрут: перед LLM —/anonymize, после —/deanonymize. -
Управляемая обратимость
Вы сами решаете, какие сущности должны быть полностью обратимыми (replace/encrypt), а какие нужно навсегда обезличить (hash/fake). Это удобно, когда, например, имена нужны для ответа пользователю, а номера карт нет. -
Наблюдаемость и отладка
Благодаря OpenTelemetry и Grafana вы видите, что именно детектируется, сколько времени занимают этапы, где узкие места и где распознаватель даёт лишние срабатывания.
Где не стоит применять
-
Приложения без PII
Если вы строите ассистента по технической документации, открытым кодовым базам или публичным новостям, где персональных данных нет, дополнительный hops через PII Shield может быть лишним. -
Сценарии, где LLM должен генерировать PII из внешних источников
PII Shield защищает то, что уже есть в тексте запроса или документах RAG. Он не фильтрует, например, публичные базы, которые вы сами подключили к LLM как инструмент. -
Жёсткие требования к сверхнизкой задержке
PII Shield добавляет свой оверхед: запуск NLP, работу распознавателей, сохранение в Redis. Для большинства бизнесовых сценариев это приемлемо, но для realtime-инференса с миллисекундными SLA это может быть критично.
Доступность и инфраструктура
PII Shield — это Python-сервис на FastAPI плюс Redis и стэк наблюдаемости. Его можно развернуть:
- локально (on-prem),
- в Azure (пример архитектуры: Container Apps, Azure Cache for Redis, Application Insights, Log Analytics, Azure Managed Grafana),
- в других облаках, если заменить компоненты на аналоги.
Для использования нужен доступ к соответствующей инфраструктуре и, если вы вызываете облачные LLM, — к их API. Если провайдер LLM заблокирован в России или требует VPN, PII Shield сам по себе это не решит: он не прокси для обхода ограничений, а слой приватности.
Место на рынке
PII Shield решает задачу, с которой многие команды сейчас справляются «на коленке»: набором регулярных выражений, ручных фильтров и разрозненных скриптов вокруг каждого LLM-вызова.
В отличие от таких самописных решений PII Shield даёт:
- централизованный REST-сервис,
- поддержку нескольких NLP-бэкендов (spaCy, ONNX, Stanza, Transformers),
- десятки готовых распознавателей Presidio плюс кастомные для индийских идентификаторов,
- стратегии по сущностям (replace/hash/encrypt/fake),
- мультиарендность с конфигурацией через
/apps, - постквантовое шифрование ML-KEM-768 + AES-256-GCM,
- встроенную наблюдаемость через OpenTelemetry и готовые дэшборды.
Другие игроки в этой нише — это:
- отдельные решения для DLP и токенизации, чаще всего заточенные под базы данных и файловые хранилища, а не под LLM-промпты;
- ручные интеграции Presidio в конкретные сервисы без общего контура управления и мультиарендности.
Числовых сравнений по скорости, стоимости или качеству детекта с альтернативами Microsoft не приводит. Основной акцент — на архитектурном подходе: единый, наблюдаемый слой между всеми AI-приложениями и всеми LLM.
Установка
PII Shield можно использовать как отдельный сервис или как библиотеку внутри Python-приложения.
Режим библиотеки
Пример использования, приведённый авторами:
from pii_shield import PiiShieldEngine
engine = PiiShieldEngine() # load NLP model once, reuse
result = engine.anonymize("Rahul's Aadhaar is 2345 6789 0123")
# "<PERSON_1>'s Aadhaar is <IN_AADHAAR_1>"
restored = engine.deanonymize(result.anonymized_text, result.entity_mapping)
Далее можно использовать BatchProcessor для CSV и DataFrame с потоковой/процессной параллелизацией, если нужно прогонять большие массивы данных офлайн.
Режим сервиса
Сервисная часть построена на FastAPI и предоставляет:
POST /anonymizeиPOST /anonymize_unique— анонимизация текста, выдача session ID и маппинга;POST /deanonymize— восстановление исходных значений по session ID;POST /appsи/apps/{id}/config— регистрация приложений и управление стратегиями;- health-check, метрики и OpenAPI-документацию.
Для прод-развёртывания потребуется:
- Python-окружение,
- Redis для session store и app registry,
- система наблюдаемости с поддержкой OpenTelemetry (например, Grafana LGTM + OTLP или Azure Monitor),
- опционально — Azure Container Apps и связанные сервисы, если вы повторяете референсную схему Microsoft.
Конкретные скрипты развёртывания и код сервиса Microsoft публикует в репозитории pii-shield (GitHub).
Как запустить: пример потока «анонимизировать → LLM → деанонимизировать»
Ниже — логика, которую вам нужно реализовать в своём приложении вокруг вызова LLM.
1. Анонимизация
Приложение отправляет запрос на /anonymize с текстом, например:
"Call Rahul Sharma at rahul@example.com about Aadhaar 2345 6789 0123."
PII Shield выполняет пять шагов:
-
Разбор конфигурации
Если есть заголовокX-App-Id, PII Shield загружает стратегии по сущностям для этого приложения из Redis (с коротким in-process кэшем). Если нет — применяются глобальные настройки. -
Детект PII
Analyzer Presidio запускает выбранный NLP-бэкенд (spaCy / ONNX / Transformers) и все встроенные и кастомные распознаватели. На выходе — список спановentity_type, start, end, score, text. -
Постобработка
- соседние локации и PIN-коды объединяются в один
ADDRESS, - пересекающиеся детекты дедуплицируются (выбирается самый длинный, при равенстве — по максимальному score),
- контекстные ключевые слова повышают confidence,
- сущности ниже порога отбрасываются.
- соседние локации и PIN-коды объединяются в один
-
Назначение плейсхолдеров
Для каждого уникального значения PII создаётся плейсхолдер:{{PERSON_1}},{{PERSON_2}}и т.д. Нумерация — по типу сущности и в пределах запроса. Одно и то же имя в нескольких местах получает один плейсхолдер. -
Применение операторов
В зависимости от стратегии приложения по типу сущности:replace→ плейсхолдер, маппинг сохраняется для обратной замены;hash→ строка вида{ENTITY}_<sha256-prefix>, маппинг не хранится (нечего восстанавливать);encrypt→ токен{{{ENTITY}_ENC_<base64-ciphertext>}}, шифрование ML-KEM-768 + AES-256-GCM, маппинг не нужен, всё есть в шифротексте;fake→ синтетическое значение от Faker, маппинг не хранится.
Реверсивный mapping {placeholder → original} сохраняется в session store (по умолчанию in-memory dict с UUID-ключом, в проде — Redis или БД). Ответ содержит id, anonymized_text и entity_mapping:
{
"id": "a1b2c3d4-...",
"anonymized_text": "Call {{PERSON_1}} at {{EMAIL_ADDRESS_1}} about Aadhaar {{IN_AADHAAR_1}}.",
"entity_mapping": {
"{{PERSON_1}}": "Rahul Sharma",
"{{EMAIL_ADDRESS_1}}": "rahul@example.com",
"{{IN_AADHAAR_1}}": "2345 6789 0123"
}
}
``
### 2. Вызов LLM
Приложение отправляет `anonymized_text` в LLM так же, как раньше отправляло сырой текст. Модель работает с плейсхолдерами как с обычными токенами.
Фраза вида:
> "Tell {{PERSON_1}} that their Aadhaar {{IN_AADHAAR_1}} has been verified"
для модели выглядит естественно, и логика не ломается.
Обычно LLM сохраняет плейсхолдеры как есть, хотя может переписать окружение. Главное — чтобы сами токены `{{PERSON_1}}` и т.п. остались в тексте.
### 3. Деанонимизация
После ответа LLM приложение вызывает `POST /deanonymize` с session `id` и текстом ответа. PII Shield делает три шага:
1. **Загрузка маппинга**
По `id` достаётся словарь плейсхолдеров из session store (одна операция чтения, очень быстро).
2. **Замена плейсхолдеров**
Все вхождения плейсхолдеров в тексте заменяются на исходные значения. Важно, что замена идёт по убыванию длины плейсхолдера, чтобы `{{PERSON_1}}` случайно не изменил часть `{{PERSON_10}}`.
3. **Расшифровка зашифрованных сущностей**
Токены вида `{{ENTITY_ENC_…}}` декодируются из base64 и расшифровываются выбранным бэкендом (по умолчанию постквантовый, для обратной совместимости возможен Fernet).
Текст, отправленный на `/deanonymize`, может сильно отличаться от исходного: LLM мог его перевести, сократить или переформулировать. Важно только, чтобы плейсхолдеры сохранились. Всё остальное проходит через PII Shield без изменений.
После истечения TTL запись в Redis удаляется, и plaintext PII перестаёт существовать в системе.
## Что дальше
PII Shield — это базовый слой. Его сила проявляется особенно заметно, когда вы встраиваете его во все точки входа к LLM, чтобы разработчики физически не могли обойти приватный контур.
Microsoft анонсирует ещё два направления интеграции:
- **PII Shield как middleware в Microsoft Agent Framework**
Агентные системы вызывают инструменты, создают подагентов, кэшируют контекст и обращаются к LLM из неожиданных мест. Middleware позволит автоматически анонимизировать каждый промпт и деанонимизировать каждый ответ, не заставляя авторов агентов думать о PII руками.
- **PII Shield + Azure API Management (APIM)**
Для организаций, которые используют APIM как единый шлюз к LLM-бэкендам. Встраивание PII Shield в политику APIM позволит перехватывать, анонимизировать и деанонимизировать все запросы ко всем LLM, независимо от того, какое приложение или команда их отправила.
Одна политика — приватность для всего AI-ландшафта.
---
## Читайте также
- [Microsoft обновила гайд по управлению AI‑агентами в Microsoft 365: что нового в версии 3.2](/news/new-updates-administering-and-governing-agents-whitepaper-v32-26794)
- [Как Microsoft предлагает обезопасить 1,3 млрд AI-агентов: идентичность, управление и zero trust](/news/securing-ai-agents-at-scale-identity-governance-and-zero-trust-26808)
- [E2a: почта для AI-агентов с проверкой отправителя, WebSocket и HITL-контролем](/news/show-hn-e2a-open-source-email-gateway-for-ai-agents-26835)