Обнаружение PII с Privacy Filter от OpenAI


OpenAI представил Privacy Filter на Hub — это открытый детектор персональных данных (PII), который эффективно размечает текст по восьми категориям, обрабатывая до 128k токенов за один проход. Мы провели время, чтобы протестировать его функционал и разработали три приложения, каждое из которых демонстрирует разные возможности инструмента: работу с документами, изображениями и текстовыми фрагментами.

Document Privacy Explorer — загрузите PDF или DOCX, читайте документ с подсветкой каждого фрагмента PII прямо на месте.

Image Anonymizer — загрузите изображение и получите его обратно с чёрными полосами поверх имён, адресов электронной почты и номеров счетов. Изображение также доступно для редактирования на холсте, чтобы вы могли добавить собственные аннотации перед скачиванием.

SmartRedact Paste — вставьте конфиденциальный текст, поделитесь публичным URL, который отдаёт редактированную версию, и сохраните для себя приватную ссылку для просмотра оригинала.

Все три приложения построены на gradio.Server, который позволяет сочетать пользовательские HTML/JS-фронтенды с очередью Gradio, распределением ZeroGPU и SDK gradio_client. Во всех этих приложениях gradio.Server играет одну и ту же роль бэкенда — именно эта согласованность делает его по-настоящему мощным инструментом.

Я уже разбирал, как Hugging Face влияет на экосистему открытого ИИ и его инструменты в контексте Privacy Filter. Ссылка на статью.

Важно понимать архитектурные паттерны надёжных AI-систем, так как это непосредственно связано с работой инструментов, таких как Privacy Filter. Читать дальше.

Создание качественного контента с использованием AI может значительно улучшить эффективность работы с PII, что делает это обсуждение особенно актуальным. Узнайте больше

Модель

Privacy Filter — это модель с 1,5 млрд параметров и 50 млн активных параметров, распространяемая по разрешительной лицензии Apache 2.0. Категории PII: private_person, private_address, private_email, private_phone, private_url, private_date, account_number, secret. Контекст составляет 128 000 токенов.

Модель достигает передового уровня производительности на бенчмарке PII-Masking-300k; полные цифры и методология приведены в официальном блоге о выпуске.

Document Privacy Explorer

Попробуйте по адресу ysharma/OPF-Document-PII-Explorer.

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

Что здесь делает Privacy Filter. Файл обрабатывается единовременно с использованием контекста в 128k токенов, что исключает необходимость в разбивке на части или сшивании. Смещения фрагментов точно соответствуют отображаемому тексту, обеспечивая четкие границы даже в сложных ситуациях.

Что здесь делает gr.Server. Существует возможность реализовать этот функционал в Blocks с gr.HighlightedText, но это усложняет программу. Нам нужен был опыт чтения с шрифтами с засечками и фильтрами по категориям, работающими на стороне клиента без необходимости перезапуска модели, а также сводная панель, которая минует принудительное обновление страницы. gr.Server позволяет создать единый HTML-документ и обслуживать модель через один эндпоинт.

import gradio as gr
from fastapi.responses import HTMLResponse
from gradio.data_classes import FileData
server = gr.Server()
@server.get("/", response_class=HTMLResponse)
async def homepage(): return FRONTEND_HTML # reader view; see app.py
@server.api(name="analyze_document")
def analyze_document(file: FileData) -> dict: text = extract_text(file["path"]) # PyMuPDF / python-docx source_text, spans = run_privacy_filter(text) # single 128k pass return { "text": source_text, "spans": spans, # [{start, end, label}, ...] "stats": compute_stats(source_text, spans), }

Обратите внимание на декоратор: @server.api(name="analyze_document"), а не обычный @server.post. Именно эта часть подключает обработчик к очереди Gradio, так что параллельные загрузки сериализуются, @spaces.GPU корректно компонуется на ZeroGPU, и один и тот же эндпоинт доступен как из браузера, так и через gradio_client без дублирования кода. Браузер вызывает его с помощью JS-клиента Gradio.

Image Anonymizer: анонимизация изображений с AI

Проблема пользователя. Вы хотите поделиться изображением или скриншотом — переписка в Slack, чек, панель управления Stripe — с чёрными полосами поверх персональных данных. Вы хотите включать и выключать полосы, перетаскивать их для изменения положения или нарисовать вручную для всего, что модель пропустила, а затем экспортировать результат.

Что здесь делает Privacy Filter. Tesseract выполняет OCR (оптическое распознавание символов) и возвращает ограничивающие рамки для каждого слова. Бэкенд восстанавливает полный текст с картой смещений символов к рамкам, затем один раз запускает Privacy Filter по всему тексту. Обнаруженные символьные фрагменты сопоставляются с картой слов и объединяются в пиксельные прямоугольники для каждой строки.

Что здесь делает gr.Server. gr.ImageEditor поддерживает многослойные аннотации и является разумной отправной точкой для редактирования изображений. Рабочий процесс, который нам был нужен — метаданные категории для каждой полосы, переключение всех полос в категории одновременно, экспорт PNG на стороне клиента в исходном разрешении без обращения к серверу, — было чище реализовать на пользовательском фронтенде с <canvas>. gr.Server возвращает пиксельные прямоугольники из одного поставленного в очередь эндпоинта и позволяет холсту управлять всем остальным:

@server.api(name="anonymize_screenshot")
def anonymize_screenshot(image: FileData) -> dict: img = Image.open(image["path"]).convert("RGB") full_text, char_to_box = ocr_image(img) # per-word boxes + char map spans = run_privacy_filter(full_text) boxes = spans_to_pixel_boxes(spans, char_to_box) return { "image_data_url": pil_to_base64(img), "width": img.width, "height": img.height, "boxes": boxes, # [{x, y, w, h, label, text}, ...] }

Фронтенд вызывает его с помощью client.predict("/anonymize_screenshot", { image: handle_file(file) }) — тот же паттерн, что и выше. Переключения, перетаскивания, рисование новых полос и экспорт PNG происходят в браузере; правки никогда не отправляются обратно на сервер.

SmartRedact Paste

Проблема пользователя. Вам нужен pastebin (сервис для публикации текстовых фрагментов), который редактирует данные перед публикацией. Вы вставляете строку журнала, письмо, тикет поддержки. В ответ вы получаете два URL. Публичный отдаёт редактированную версию с заполнителями <PRIVATE_PERSON>, <PRIVATE_EMAIL>, <ACCOUNT_NUMBER>, следуя соглашению о редактировании из официальных примеров блога.

Приватный защищён токеном, который вы сохраняете, и показывает оригинал с подсвеченными фрагментами.

Что здесь делает Privacy Filter. Каждый обнаруженный фрагмент заменяется заполнителем <CATEGORY> в сохранённой вставке — это и есть весь шаг редактирования. Многоязычный текст (испанский, французский, китайский, хинди и другие языки из примеров карточки модели) проходит через тот же вызов без каких-либо изменений.

Что здесь делает gr.Server. Этому приложению нужны два разных GET-маршрута для одного и того же идентификатора вставки — один публичный и один защищённый токеном, — и форма URL важна, потому что ссылка для просмотра оригинала — это то, что вы сохраняете. gr.Server работает здесь, потому что под ним находится приложение FastAPI — именно поэтому @server.api и обычный @server.get могут соседствовать в одном процессе. Примечание: это также можно реализовать с помощью gr.Blocks(), монтируя пользовательские маршруты через FastAPI:

# Model call → queued endpoint. Hit from the browser via
# client.predict("/create_paste", { text, ttl }).
@server.api(name="create_paste")
def create_paste(text: str, ttl: str = "never") -> dict: source_text, spans = run_privacy_filter(text) redacted = redact(source_text, spans) # <CATEGORY> placeholders pid, reveal_token = secrets.token_urlsafe(6), secrets.token_urlsafe(22) PASTES[pid] = Paste(pid, reveal_token, source_text, redacted, spans, expires_at=_ttl(ttl)) # see app.py return { "view_path": f"/view/{pid}", "reveal_path": f"/view/{pid}?token={reveal_token}", }
# View page → plain FastAPI GET.
# No model, no queue needed, and we
# actually want the bespoke
URL shape `/view/{pid}?token=...` that a
# queued endpoint couldn't give us.
@server.get("/view/{pid}", response_class=HTMLResponse)
async def view_paste(pid: str, token: str | None = None): p = _store_get(pid) # see app.py for store if p is None: return HTMLResponse(_not_found(), status_code=404) revealed = bool(token) and secrets.compare_digest(token, p.reveal_token) return HTMLResponse(_render_view(p, revealed))

Фоновый поток вытесняет истёкшие вставки каждые 30 секунд. Весь сервис, включая хранилище, занимает около 200 строк кода приложения, потому что всё находится в одном процессе.

Что предоставляет gradio.Server

Разделение во всех трёх приложениях одинаково — всё, что касается модели, проходит через @server.api, всё остальное остаётся на обычных маршрутах FastAPI.

@server.api предоставляет очередь Gradio: сериализованные запросы, корректная компоновка @spaces.GPU на ZeroGPU, события прогресса. Именно через него браузер обращается через @gradio/client. Тот же эндпоинт также используется пользователями gradio_client из Python — одна функция, два SDK, без дублирования кода.

Обычные @server.get / @server.post зарезервированы для статических поверхностей: HTML-страниц, поиска файлов, дешёвых чтений словарей. Это практическое правило из вводного поста о gradio.Server, и именно оно делает три приложения согласованными, несмотря на то что их интерфейсы очень разные.

На мой взгляд, ключевое преимущество этой архитектуры — предсказуемость: когда знаешь, что любой вызов модели идёт через @server.api, отлаживать производительность и масштабировать нагрузку становится значительно проще.

Типичные ошибки при работе с Privacy Filter OpenAI

Несколько наблюдений, которые стоит учесть до того, как вы начнёте строить собственное приложение.

Не разбивайте текст на части без необходимости. Контекст в 128k токенов покрывает большинство реальных документов целиком. Разбивка на чанки (chunks) нарушает границы фрагментов и приводит к ложным срабатываниям на стыках.

Не игнорируйте карту смещений при работе с изображениями. В Image Anonymizer мы строим явную карту символ → пиксельная рамка через Tesseract. Без неё сопоставление фрагментов с координатами на холсте становится ненадёжным.

Не смешивайте @server.api и @server.post для одного и того же эндпоинта. Только @server.api подключается к очереди Gradio и корректно компонуется с ZeroGPU. Использование @server.post для вызовов модели лишает вас сериализации и событий прогресса.

Не забывайте про TTL для хранилища вставок. В SmartRedact Paste фоновый поток вытесняет истёкшие записи каждые 30 секунд. Без этого хранилище в памяти растёт неограниченно при любой нагрузке

Ответы на эти вопросы могут быть для вас полезными

Можно ли использовать Privacy Filter для текстов на языках, отличных от английского?

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

Почему в примерах используется @server.api, а не стандартный @server.post?

Только @server.api подключает обработчик к очереди Gradio, что обеспечивает сериализацию параллельных запросов, корректную компоновку с @spaces.GPU на ZeroGPU и доступность эндпоинта через gradio_client из Python без дублирования кода.

Как Privacy Filter справляется с длинными документами?

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

Какие категории PII умеет распознавать модель?

Восемь категорий: private_person, private_address, private_email, private_phone, private_url, private_date, account_number, secret. Полная таксономия с примерами приведена в карточке модели на Hugging Face.

Можно ли развернуть эти приложения вне Hugging Face Spaces?

Да. gradio.Server построен поверх FastAPI, поэтому приложение запускается в любом окружении, где доступен Python. ZeroGPU и @spaces.GPU специфичны для Hugging Face Spaces, но логику очереди и маршрутизации можно адаптировать под собственную инфраструктуру.

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x