на главную Dmitrii Lu
Case Study · 03 / 2026

AI-верификатор фото — защита от фейковых жалоб

Telegram-бот + Mini App для ресторанов, доставки и фудтеха. Сотрудник загружает фото из жалобы клиента — система за секунды проверяет, была ли картинка сгенерирована нейросетью, отредактирована в фотошопе и когда реально снята. На выходе — визуальная ELA-карта манипуляций, PDF-отчёт для разбора спора и защита маржи от ложных компенсаций. Собран в связке с Claude Code.

Telegram-чат с Verificator_eat_bot — Mini App «Проверка фото» открыта внутри клиента
Mini App открывается прямо в Telegram — сотруднику не нужно ставить отдельное приложение
ELA-карта модификаций на сфотографированной тарелке — тёплые пятна выдают область редактирования
реальный ELA-хитмэп · тёплые зоны = высокий уровень пересжатия = след редактирования
Продукт
Verificator_eat · @Verificator_eat_bot · Telegram Mini App
Сегмент
Общепит, доставка, фудтех — защита от ложных компенсаций по фото
Роль
Full-Stack AI Developer — архитектура, ML-пайплайн, Mini App, PDF-отчёты, ролевая модель
Разработка
2026 · в связке с Claude Code
Стек
Python 3.12 · aiogram 3 · aiohttp · SQLAlchemy · Alembic · Pillow · NumPy · Vue 3 · Vite · Pinia · AI or Not API · ReportLab · Docker · Fly.io
  1. 15 000 ₽ предотвращённых убытков всего — в реальной тестовой точке за первые недели работы
  2. 10 подделок выявлено — AI-фото, пересжатия, отсутствие EXIF
  3. ~58% доля «модифицировано» среди загруженных фото в пилотном режиме
  4. 1500 ₽ средний чек ресторана — в настройках задаётся для автоподсчёта сохранённой маржи
  1. 4 независимых слоя анализа — AI-детектор, ELA-хитмэп, EXIF, давность съёмки
  2. 2 роли в системе — оператор (проверка) и администратор (управление)
  3. PDF отчёт по каждому спору — для разбора с клиентом или агрегатором
  4. 20 МБ потолок файла · JPEG · PNG · WebP — принимает любой формат доставки

* цифры предотвращённых убытков взяты из реального дашборда статистики тестовой точки · средний чек настраивается

1

Задача

В общепите, доставке и на агрегаторах еды появился новый класс мошенничества: клиент заказывает, получает блюдо, а потом присылает фото — «в моём блюде волос / плесень / посторонний предмет» — и требует компенсацию, возврат или бесплатный повторный заказ. Проблема в том, что фото всё чаще не настоящие: их либо генерирует Midjourney / DALL·E, либо собирают из чужих снимков в фотошопе, либо просто берут из гугла двухлетней давности. Ресторану проще отдать 1 500 ₽, чем спорить — и эти «проще» суммируются в ощутимый минус по маржинальности.

  • AI-генерация дешевеет. Любой может за 30 секунд сгенерировать «реалистичное» фото испорченного блюда — и приложить к претензии.
  • У менеджера нет инструмента. На глаз AI-фото сегодня почти не отличить от настоящего — особенно в торопливом чате поддержки.
  • Старые фото. Часть претензий — это чужое фото из интернета или снимок двухнедельной давности, который выдают за «сейчас из ресторана».
  • Нужны доказательства. Спор с клиентом или агрегатором требует не «мнения менеджера», а документа с фактами — PDF, который можно переслать.
2

Архитектура — один бот, четыре анализа

Система — Telegram-бот на aiogram, который монтирует внутри себя Mini App на Vue 3. Сотрудник загружает фото прямо в окне Telegram, aiohttp-бэкенд прогоняет его через четыре независимых слоя анализа (AI-детектор, ELA, EXIF, timestamp), взвешивает результаты в едином вердикте и сохраняет запись в Postgres. По итогу — визуальный вердикт в Mini App, тепловая карта манипуляций и PDF-отчёт для разбирательства.

  • aiogram 3 + aiohttp — в одном процессе: и webhook для Telegram, и REST API для Mini App.
  • Vue 3 + Vite + Pinia — Mini App со всеми экранами: проверка, история, статистика, сотрудники, настройки.
  • SQLAlchemy async + Alembic — модели Verification / Employee / AppSettings, миграции схемы под версии.
  • Pillow + NumPy — ELA-хитмэп и EXIF-разбор делаются локально, без внешних API.
  • AI or Not — единственный внешний ML-провайдер, отвечает за вердикт «сгенерировано нейросетью».
  • ReportLab — серверная сборка PDF-отчёта с русскими шрифтами и встроенным хитмэпом.
  • Ролевая модель — оператор видит «Проверка» + «История»; админ — плюс «Статистика», «Сотрудники», «Настройки».
  • Docker · Fly.io — один контейнер, ноль ручной инфраструктуры.
                     ┌─────────────────────────────────────┐
                     │        Telegram Bot API             │
                     └────────────────┬────────────────────┘
                                      │ webhook · Mini App launch
                                      ▼
┌──────────────────────────────────────────────────────────────────┐
│  aiogram 3  ·  aiohttp server  (один процесс, один контейнер)  │
│                                                                  │
│   ┌──────────────┐   ┌──────────────┐   ┌──────────────────┐     │
│   │ bot router   │   │ REST /api   │   │  miniapp (Vue)   │     │
│   │ /start       │   │ /verify      │   │  Pinia · router  │     │
│   │ /history     │   │ /history     │   │  5 экранов       │     │
│   │ /stats       │   │ /stats       │   └──────────────────┘     │
│   │ /admin       │   │ /employees   │                            │
│   └──────────────┘   │ /settings    │                            │
│                      │ /heatmap     │                            │
│                      │ /pdf         │                            │
│                      └──────┬───────┘                            │
│                             │                                    │
│     ┌──── analysis pipeline ┴─────────────────────────────┐      │
│     │                                                    │      │
│     ▼                                                    ▼      │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ AI detector  │ │     ELA      │ │    EXIF     │ │Timestamp│ │
│ │ AI or Not    │ │ Pillow+NumPy │ │ Pillow/TAGS  │ │ datetime │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └────┬─────┘ │
│        └────────────────┴──────┬─────────┴──────────────┘       │
│                                ▼                                │
│                      ┌───────────────────┐                      │
│                      │ build_verdict()  │ ──► confidence %     │
│                      └─────────┬─────────┘                      │
│                                ▼                                │
│                   ┌────────────────────────┐                    │
│                   │ Postgres · SQLAlchemy │ ──► audit            │
│                   └─────────────┬──────────┘                    │
│                                 ▼                               │
│                      ┌───────────────────┐                      │
│                      │ ReportLab · PDF  │ ──► /tmp cache       │
│                      └───────────────────┘                      │
└──────────────────────────────────────────────────────────────────┘

4 слоя анализа · единый вердикт · ролевая модель · Mini App и бот в одном процессе

· вход

Telegram Mini App

Кнопка «Открыть панель» запускает Vue 3 SPA внутри Telegram. Сотрудник тапает по области drag-n-drop, выбирает фото — multipart летит в /api/verify.

· ML-пайплайн

4 независимых слоя

AI or Not (вердикт «сгенерировано нейросетью»), ELA-хитмэп на Pillow+NumPy, разбор EXIF-тегов, проверка давности снимка через DateTimeOriginal.

· вердикт

Взвешенная логика

Функция build_verdict() комбинирует результаты в три класса: ORIGINAL / MODIFIED / AI_GENERATED — и возвращает confidence %.

· выход

PDF + история

Каждая проверка пишется в Postgres, ELA кэшируется в /tmp, ReportLab собирает PDF с русским шрифтом — сотрудник может скачать и переслать.

3

Mini App в Telegram

Сотрудник общепита не ставит приложение, не заводит аккаунт, не помнит пароль. Он открывает Telegram — Verificator_eat_bot уже добавлен в корпоративный чат, нажимает «Открыть панель» — и попадает в полноценный SPA с пятью экранами прямо в клиенте.

  • /start → приветствие бота, подсказка отправить фото как документ для максимальной точности анализа
  • Mini App → drag-n-drop зона «Нажмите для загрузки», JPEG / PNG / WebP до 20 МБ
  • Bottom nav → 2 пункта для оператора, 5 для администратора
  • Auth → через initData Telegram, без отдельных логинов
Команда /start в боте — подсказка отправить фото для верификации
/start · подсказка отправить фото как документ — так сохраняются метаданные
4

Две роли — оператор и админ

Нижняя навигация Mini App динамически перестраивается под роль. Оператор (линейный сотрудник зала или колл-центра) видит только проверку и свою историю — ничего лишнего. Администратор — плюс сводную статистику по точке, список сотрудников с ролями и настройки среднего чека для расчёта сохранённой маржи.

  • Оператор → Проверка · История (2 таба)
  • Админ → Проверка · История · Статистика · Сотрудники · Настройки (5 табов)
  • Назначение ролей — одной кнопкой из админского экрана, без SQL
  • Деактивация — увольнение сотрудника закрывает ему Mini App
Mini App глазами оператора — два таба в нижней навигации: Проверка и История
2 таба — только проверка и личная история
Mini App глазами администратора — пять табов
5 табов — плюс статистика, сотрудники, настройки
5

Ядро проверки — 4 слоя анализа

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

01 · AI-детектор · AI or Not
  • Verdict — ai / human / unknown
  • Confidence — вероятность AI-генерации 0..1
  • Generators — детектируется источник: Midjourney, SDXL, DALL·E, Flux
  • Graceful degrade — при падении API вердикт по остальным 3 слоям
02 · ELA-хитмэп · локально
  • Пересжатие изображения в JPEG q=90
  • Попиксельная разность с оригиналом × 20
  • JET-colormap без matplotlib — чистый NumPy
  • Тёплые зоны = область, которая перекомпрессовалась дважды — типичный признак редактирования
03 · EXIF-анализ · локально
  • Камера — Make / Model (iPhone 15, Canon EOS и т.д.)
  • Software — сверяется с списком из 18 редакторов (Photoshop, Lightroom, Snapseed, Facetune…)
  • GPS — присутствует / нет
  • Флаги — NO_EXIF · HAS_CAMERA · HAS_DATE · HAS_GPS · EDITING_SOFTWARE
04 · Давность · локально
  • Парс даты из DateTimeOriginal
  • Вердикт — recent / suspicious / old / no_data
  • Пороги — WARN (по умолчанию 30 мин.) и MAX (24 ч)
  • Защита — дата в будущем → suspicious
6

ELA — тепловая карта манипуляций

Error Level Analysis — классический forensic-алгоритм, который превращает невидимые глазом следы редактирования в яркую тепловую карту. Система пересжимает фото в JPEG с тем же качеством, вычитает из оригинала — и зоны, где разность велика, подсвечиваются тёплыми цветами. Если на фото блюда «инородный предмет» — он почти всегда вставлен отдельным слоем и на ELA подсвечивается ярче фона.

Экран результатов с ELA — вердикт «Возможно модифицировано», уверенность 57%, тепловая карта фото тарелки
вердикт сверху · ELA-хитмэп ниже · тёплые зоны = область пересжатия
Детали анализа под ELA — уровень модификации 77%, JPEG-качество 71, EXIF отсутствует, дата съёмки не найдена
детали: JPEG-качество · EXIF · давность · «анализ для рассмотрения жалобы»
7

История и статистика

Каждая проверка сохраняется — и сотрудник, и администратор могут вернуться к ней, скачать PDF, переслать клиенту. Админ видит сводку по точке: сколько всего проверок, сколько сегодня / за неделю, какая доля — «модифицировано» vs «оригинал», и сколько рублей маржи уже спасено (подсчитывается автоматически из среднего чека в настройках).

Список истории проверок с цветовыми маркерами — зелёные «Оригинал», оранжевые «Модифицировано», PDF-ссылка на каждую
история проверок · цветовые полосы слева · PDF в одном тапе
Статистика — всего 17 проверок, выявлено 10 подделок, предотвращено убытков 15 000 ₽
дашборд админа · пончик распределения · спасённая маржа автоподсчётом
8

Управление — сотрудники и настройки

Админ добавляет сотрудников по Telegram ID, назначает роль — оператор или администратор — и в любой момент может повысить, понизить или деактивировать аккаунт. Средний чек в настройках — единственный экономический параметр, от которого зависит расчёт «предотвращённых убытков» на дашборде.

9

Deep dive — данные, ELA, вердикт

Три технических куска, ради которых случаи вроде этого стоит собирать по-инженерному, а не склеивать no-code. Ниже — схема данных под аудит, ядро ELA-алгоритма и формула взвешенного вердикта.

· audit

Полный след проверки

В таблице verifications хранится не только итоговый вердикт, но и каждый промежуточный сигнал: вердикт AI-детектора отдельно, JSON-словарь детектированных генераторов, все EXIF-флаги, camera_info, software, timestamp-вердикт. При споре можно поднять одну запись и разложить логику на составляющие.

· local first

3 из 4 слоёв — локально

ELA, EXIF и timestamp-чекер не ходят в интернет. Это значит, что даже при сбое AI or Not или при отключении интернета — базовая проверка по метаданным и ELA продолжает работать, а сотрудник получает хоть какой-то вердикт.

· UUID

UUID для каждой записи

Первичный ключ — uuid4. В URL-ах PDF и хитмэпов нет угадываемых id-шников. ELA-png кэшируется в /tmp/ela_{uuid}.png и отдаётся только авторизованному сотруднику той же точки.

· Telegram auth

initData для Mini App

Аутентификация — через подпись initData, которую Telegram выдаёт при запуске Mini App. Middleware проверяет HMAC, достаёт telegram_id, матчит его к строке в employees, внутрь хендлера уже приходит объект Employee с ролью.

# ядро ELA — чистый Pillow + NumPy, без matplotlib
orig = Image.open(buf).convert("RGB")
recomp = _save_as_jpeg(orig, quality=ELA_QUALITY)   # 90

diff = np.abs(np.array(orig, int16) - np.array(recomp, int16))
diff_gray = np.clip(diff * ELA_AMPLIFY, 0, 255).max(axis=2)  # ×20

# JET-colormap без matplotlib — синий → зелёный → жёлтый → красный
n = diff_gray / 255.0
r = np.clip(1.5 - np.abs(4 * n - 3), 0, 1)
g = np.clip(1.5 - np.abs(4 * n - 2), 0, 1)
b = np.clip(1.5 - np.abs(4 * n - 1), 0, 1)
heatmap = Image.fromarray((np.stack([r, g, b], -1) * 255).astype(uint8))
-- verifications · одна запись на каждое загруженное фото
CREATE TABLE verifications (
  id                   UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  employee_id          INT  REFERENCES employees(id),

  -- итоговый вердикт
  verdict              verdict_type NOT NULL,     -- ORIGINAL | MODIFIED | AI_GENERATED | UNKNOWN
  confidence           INT  NOT NULL,             -- 0..100 %
  verdict_text         TEXT NOT NULL,

  -- AI-детектор
  ai_verdict           VARCHAR(20),
  ai_confidence        FLOAT,
  ai_generators        JSON,                      -- { midjourney: 0.87, sdxl: 0.12 }
  ai_error             BOOLEAN DEFAULT FALSE,

  -- EXIF
  has_exif             BOOLEAN DEFAULT FALSE,
  camera_info          VARCHAR(255),
  software             VARCHAR(255),
  photo_datetime       VARCHAR(50),
  gps_present          BOOLEAN DEFAULT FALSE,
  editing_detected     BOOLEAN DEFAULT FALSE,
  exif_flags           JSON,                      -- [NO_EXIF, EDITING_SOFTWARE, HAS_GPS]

  -- timestamp
  photo_age_minutes    INT,
  timestamp_verdict    VARCHAR(20),               -- recent | suspicious | old | no_data

  -- артефакты
  ela_heatmap_available BOOLEAN DEFAULT FALSE,
  original_filename    VARCHAR(255),
  complaint_note       TEXT,

  created_at           TIMESTAMPTZ DEFAULT now()
);

схема · каждый промежуточный сигнал сохранён рядом с итоговым вердиктом · UUID для приватности ссылок

10

Результат

  • Ресторан получает доказательство. За секунды — вердикт, тепловая карта и PDF, который можно переслать клиенту или агрегатору. «Ощущение менеджера» превращается в документ.
  • Маржа защищена. В пилотной точке за первые недели — 15 000 ₽ спасённой маржи, 10 выявленных подделок и доля "модифицировано" ~58%.
  • Сотрудник не учится. Вход — через Telegram, который уже у всех в корпоративном чате. Никаких отдельных приложений и паролей.
  • Роли и управление из Mini App. Админ добавляет, назначает и деактивирует сотрудников одной кнопкой.
  • Архитектура с запасом прочности. 3 из 4 слоёв анализа работают локально — базовая защита остаётся даже при падении внешнего ML-провайдера.

Нужен похожий AI-инструмент?

Если в вашем бизнесе фото, документы или скриншоты становятся инструментом мошенничества — напишите. Соберём бота, Mini App или SaaS, который превратит «доверие на слово» в аудируемый процесс.

все работы