Автоматическое удаление PII из изображений Amazon Nova | Гайд 2026 | AiManual
AiManual Logo Ai / Manual.
06 Июл 2026 Гайд

Автоматическое удаление PII из изображений с Amazon Nova: как не попасть на GDPR-штраф

Пошаговый гайд: как с помощью Amazon Nova Vision автоматически находить и размывать персональные данные на картинках. Код, архитектура, подводные камни.

Скриншот с паспортом в корпоративном чате — это 20 млн евро штрафа

Представьте: сотрудник загружает скриншот с паспортными данными в трекер задач. Через минуту изображение улетает в логи, потом в аналитику. GDPR — до 4% от глобального оборота. PCI DSS — до 100 тыс. долларов за инцидент. И это не гипотетика: в 2025 году Meta оштрафовали на €1,2 млрд за DPA violations.

Проблема классическая: PII бывает не только в тексте, но и в картинках. Лица на фото, номера кредиток на чеках, паспорта в сканах. Старые методы (OCR + regex) работают только с текстом, а детекция лиц — отдельная боль. Традиционные пайплайны дробятся: одна модель для OCR, вторая для лиц, третья для номеров. Дорого, сложно, негибко.

Но с середины 2025 года Amazon выкатила Nova Vision — мультимодальную модель, способную одновременно распознавать текст, объекты и лица. И задавать ей можно практически любые правила. Давайте соберём production-ready пайплайн для автоматической PII-маскировки в изображениях. Без костылей, на чистом AWS.

💡 Кстати: если вы хотите разобраться, как Amazon Nova справляется с галлюцинациями в критических сценариях, почитайте статью про детерминированные LLM от Artificial Genius. Там показано, как использовать Nova для финансов и медицины без риска.

Почему Amazon Nova, а не куча отдельных моделей?

Звучит логично: взять Rekognition для лиц, Textract для документов, а потом всё сшить. Но у этого подхода три проблемы:

  • Стоимость. Каждый сервис — отдельный биллинг. Для одного изображения вы платите три раза.
  • Задержка. Последовательные вызовы — время, которое в real-time недопустимо.
  • Контекст. Модели не видят полной картины. Номер карты, напечатанный на футболке, может быть не распознан как PII.

Amazon Nova Vision (на июль 2026 — актуальны версии Nova Lite 2.0 и Nova Pro 2.0) решает всё одной моделью. Вы просто даёте промпт: “Найди все персональные данные: лица, номера паспортов, кредитных карт, телефоны, email-адреса. Для каждого найденного объекта верни bounding box в формате [x1,y1,x2,y2].” И модель возвращает структурированный JSON с координатами.

🔑
Важно: Nova Vision — это не детектор объектов в классическом понимании. Это мультимодальная LLM, которая умеет понимать изображение и отвечать в нужном формате. Если вы попросите её описать всё текстом — она опишет. Если дать чёткую схему JSON — она вернёт координаты. Научитесь правильно составлять промпты — и модель будет работать как часы.

Кстати, о мультимодальности. В статье Кроссмодальный поиск на практике я показывал, как Nova Multimodal Embeddings позволяют искать по контенту без текстовых меток. Тот же принцип используется и здесь — модель видит изображение целиком.

Архитектура: три сервиса, один пайплайн

Нам понадобится минимум AWS-компонентов:

  • S3 buckets: один для исходных изображений (input), второй для очищенных (output).
  • Lambda function на Python, которая срабатывает по S3-триггеру.
  • Amazon Bedrock с включённой моделью Amazon Nova Pro (или Lite — зависит от требований по точности).

Схема простая: загрузка файла в input-bucket → триггер запускает Lambda → функция читает изображение, отправляет его в Bedrock, получает bounding boxes → размывает/закрашивает области → сохраняет результат в output-bucket.

⚠️ Подводный камень: размер изображения влияет на стоимость и latency. Статья Snapcompact подсказывает, как можно сжимать изображения, сохраняя ключевые детали — это прямо применимо к нашему пайплайну. Рекомендую уменьшать изображения до 1024x1024 перед отправкой, если позволяет качество.

Шаг 1. Готовим инфраструктуру

Создаём два S3-бакета (имена уникальные, можно с префиксом pii-input-* и pii-output-*). Включаем версионирование на всякий случай.

Далее — IAM-роль для Lambda. Политики:

  • s3:GetObject на input-bucket.
  • s3:PutObject на output-bucket.
  • bedrock:InvokeModel (можно ограничить конкретной моделью).
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::pii-input-2026/*"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject"],
      "Resource": "arn:aws:s3:::pii-output-2026/*"
    },
    {
      "Effect": "Allow",
      "Action": "bedrock:InvokeModel",
      "Resource": "arn:aws:bedrock:us-east-1::foundation-model/amazon.nova-pro-v1:0"
    }
  ]
}

На момент 06.07.2026 модель Nova Pro — самая мощная. В регионах us-east-1 и eu-west-1 она доступна по умолчанию.

Шаг 2. Пишем Lambda-функцию

Код на Python 3.12. Используем библиотеки boto3, Pillow, json.

import boto3
import json
from PIL import Image, ImageFilter
import io
import os

bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
s3 = boto3.client("s3")

def lambda_handler(event, context):
    # Получаем информацию о загруженном файле
    bucket = event["Records"][0]["s3"]["bucket"]["name"]
    key = event["Records"][0]["s3"]["object"]["key"]
    
    # Читаем изображение из S3
    response = s3.get_object(Bucket=bucket, Key=key)
    image_bytes = response["Body"].read()
    
    # Вызываем Bedrock с изображением
    pii_regions = detect_pii(image_bytes)
    if not pii_regions:
        print("PII не найдено, просто копируем")
        s3.put_object(Bucket=os.environ["OUTPUT_BUCKET"], Key=key, Body=image_bytes)
        return {"statusCode": 200, "body": "No PII"}
    
    # Размываем PII-области
    redacted_image = blur_regions(image_bytes, pii_regions)
    
    # Сохраняем результат
    s3.put_object(
        Bucket=os.environ["OUTPUT_BUCKET"],
        Key=key,
        Body=redacted_image,
        ContentType=response["ContentType"]
    )
    
    return {"statusCode": 200, "body": f"Redacted {len(pii_regions)} regions"}

Функция detect_pii — ключевая. Отправляем изображение в Nova с промптом, который требует вернуть bounding boxes.

def detect_pii(image_bytes: bytes):
    # Конвертируем bytes в base64
    import base64
    image_b64 = base64.b64encode(image_bytes).decode("utf-8")
    # Определяем mime-type (можно вытащить из заголовка S3, упрощаем)
    mime = "image/jpeg"
    
    prompt = """
    Analyze the image carefully. Find all personally identifiable information (PII):
    - Faces (any human face)
    - Passport numbers, ID numbers
    - Credit card numbers (16 digits)
    - Phone numbers
    - Email addresses
    - Full names (if clearly visible)
    
    For each PII element, return a JSON object with:
    - "type": one of "face", "passport_number", "credit_card", "phone", "email", "name"
    - "bbox": [x1, y1, x2, y2] where coordinates are in pixels relative to image width/height (0-1)
    - "confidence": 0.0 to 1.0
    
    Return ONLY a JSON array, no other text. Example:
    [
      {"type": "face", "bbox": [0.1, 0.2, 0.3, 0.4], "confidence": 0.95},
      {"type": "credit_card", "bbox": [0.4, 0.5, 0.8, 0.6], "confidence": 0.99}
    ]
    If no PII, return empty array []
    """
    
    body = {
        "anthropic_version": "bedrock-2023-05-31",
        "messages": [
            {
                "role": "user",
                "content": [
                    {"type": "image", "source": {"type": "base64", "media_type": mime, "data": image_b64}},
                    {"type": "text", "text": prompt}
                ]
            }
        ],
        "max_tokens": 2000,
        "temperature": 0  # Детерминированность важна для PII
    }
    
    try:
        response = bedrock.invoke_model(
            modelId="amazon.nova-pro-v1:0",
            contentType="application/json",
            accept="application/json",
            body=json.dumps(body)
        )
        result = json.loads(response["body"].read())
        # Извлекаем ответ ассистента
        content = result["content"][0]["text"]
        # Парсим JSON
        pii_list = json.loads(content)
        return pii_list
    except Exception as e:
        print(f"Error invoking Nova: {e}")
        return []

💡 Почему temperature=0? Если вы читали статью Детерминированные LLM от Artificial Genius, то знаете: для чувствительных данных галлюцинации недопустимы. Temperature=0 даёт воспроизводимый результат.

Теперь функция размытия:

def blur_regions(image_bytes: bytes, regions: list) -> bytes:
    img = Image.open(io.BytesIO(image_bytes))
    width, height = img.size
    
    for region in regions:
        bbox = region["bbox"]
        # Конвертируем относительные координаты в абсолютные
        x1 = int(bbox[0] * width)
        y1 = int(bbox[1] * height)
        x2 = int(bbox[2] * width)
        y2 = int(bbox[3] * height)
        
        # Вырезаем область
        crop = img.crop((x1, y1, x2, y2))
        # Размываем
        blurred = crop.filter(ImageFilter.GaussianBlur(radius=30))
        # Вставляем обратно
        img.paste(blurred, (x1, y1))
    
    buf = io.BytesIO()
    img.save(buf, format="JPEG", quality=85)
    return buf.getvalue()

Готово. Загружаете тестовую картинку — и через секунду получаете чистый вариант в output-бакете.

Шаг 3. Тестирование и подводные камни

Первым делом проверьте, что модель действительно возвращает корректные bounding boxes. Частая ошибка — модель начинает описывать PII словами, а не координатами. Я советую сначала запустить промпт вручную через Bedrock Playground, убедиться, что ответ парсится как JSON.

Вторая проблема — точность. Nova не идеальна. Она может пропустить мелкий текст или лицо в тени. В таких случаях комбинируйте с другими инструментами. Например, статья Локальный OCR с PII-маскировкой показывает, как Qwen 3 VL не справляется один — и как собрать гибридный пайплайн. Здесь та же логика: Nova — голова, но для страховки можно добавить детекцию лиц от Rekognition или Tesseract.

⚠️ Грабли с координатами: Nova может вернуть bbox в формате [left, top, right, bottom] в пикселях, а не в относительных величинах. В моём примере я использую относительные, потому что так проще для разных разрешений. Если модель возвращает пиксели — нормируйте их на размер изображения.

Третье — лимиты Lambda. При обработке больших изображений ( > 10 MB) может упасть timeout (максимум 15 минут, но лучше держать в пределах 30 секунд). Решение: либо уменьшать изображение перед отправкой в Bedrock, либо использовать AWS Step Functions для асинхронного пайплайна.

Четвёртое — стоимость. Один вызов Nova Pro стоит ~$0.003 за изображение (цены на июль 2026). Плюс Lambda и S3. Для тысяч изображений в день — копейки, но для миллионов может выйти ощутимо. Оптимизируйте промпт, используйте Nova Lite (дешевле, но точнее) или функцию max_tokens по минимуму.

Когда это не работает (и что делать)

Nova Vision, как и любая LLM, иногда галлюцинирует — видит кредитку на картинке с котиком. Поэтому:

  • Добавьте в промпт фразу "Only return PII if you are at least 80% confident".
  • Используйте confidence threshold при размытии: если confidence < 0.7 — пропускаем.
  • Для надежности можно сделать двухэтапную проверку: сначала Nova, потом дополнительный сервис (например, Amazon Rekognition для лиц).

Кстати, интересный кейс — когда PII находится не в тексте, а в метаданных изображения (EXIF). Тут Vision не поможет. Нужно чистить EXIF отдельно. Я упоминал об этом в статье Автоматическая чистка персональных данных — советую почитать для комплексного подхода.

Ещё одна ловушка — изображения с низким разрешением или поворотом. Nova может не распознать текст. В таком случае предварительно делайте препроцессинг: поворот, увеличение резкости. OpenCV в помощь.

Масштабирование: от фоточек до миллионов документов

Lambda + S3 — отличное решение для небольшого потока. Но если вам нужно обрабатывать 10 000 изображений в час, Lambda не потянет (concurrency limits). Выход — использовать SQS + Lambda с партионной обработкой, или AWS Batch для пакетной загрузки.

Пример из жизни: Huntington Bank обработал 400 миллионов документов на AWS за пару месяцев. Они использовали комбинацию Textract и Lambda с очередями. Наш пайплайн с Nova можно встроить в ту же архитектуру.

Краткий чек-лист перед продакшеном

  • Тесты на разных типах PII: лица, паспорта, кредитки, email в разных шрифтах.
  • A/B тестирование: сравнивайте результат Nova с ручной разметкой.
  • Мониторинг: CloudWatch метрики на количество обработанных изображений, ошибки, среднюю задержку.
  • Fallback: если Nova не уверена — отправляйте изображение на ручную проверку.

И да, не забудьте включить логирование запросов к Bedrock. Без логов сложно расследовать инциденты.

Пара слов о сравнении с альтернативами

Мы привыкли, что PII-фильтрация — это удел NLP моделей. Но с Vision LLM открывается новый уровень. Если вы хотите увидеть больше примеров, как PII чистят в тексте — статья Как собрать PII-фильтр на коленке покажет простой способ с OpenAI. У нас подход схож, но на стороне AWS.

И напоследок: не доверяйте модели на 100%. Всегда настраивайте fallback — отправляйте подозрительные изображения на ручную проверку. Автоматика — это щит, но не меч. Через год подобные пайплайны станут стандартом де-факто для compliance. Amazon Nova — лишь первая ласточка, но уже сейчас можно строить production-решения, которые спасут от миллионных штрафов.

Подписаться на канал