sequenceDiagram
autonumber
actor App as APP (📱 Client)
participant GW as GATEWAY (FastAPI)
participant S3 as MinIO (S3 Storage)
participant K as Broker: Kafka
participant Vision as product-vision (YOLO)
participant Censor as censorship-worker
%% PART A: UPLOAD AND QUEUE PUSH
App->>GW: POST /upload-product-photo (Multipart, lang)
activate GW
GW->>S3: PutObject: Save image file
activate S3
S3-->>GW: Return image_file_url
deactivate S3
note over GW: trace_id Generation & Payload Assembly
GW->>K: Push to topic: bpds.inventory.in.product.image
GW-->>App: HTTP 202 Accepted (Gateway released)
deactivate GW
%% PART B: YOLO DETECTION
K->>Vision: Handler: ProcessProductImage()
activate Vision
Vision->>S3: GetObject: Download via URL
activate S3
S3-->>Vision: Binary graphic stream
deactivate S3
note over Vision: YOLO Inference:<br/>Contour localization and class detection
Vision->>K: Push to topic: bpds.inventory.in.receipt.upload
deactivate Vision
Метод POST /api/v1/gateway/upload-product-photo
Документация API: Добавление продуктов через готовый снимок с автоматической gRPC ИИ-модерацией
- IAD-MIGRATION-116 Backlog — Краткое Описание задачи 1.
- GW-2 Ready for Development — Подключение эндпоинта в шлюзе.
- AID-012 Ready for Development — создать метож ProcessVoiceStream.
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
Функциональное назначение
This method is designed for the asynchronous processing and object detection of product images (or receipts) using computer vision (YOLO).
Within the updated architecture, this method acts as a Vision Context Provider:
- Binary Traffic Isolation: The
FastAPIgateway does not hold the image in RAM during model inference. Instead, it instantly streams the file to the distributed object storageMinIO (S3), freeing upUvicornnetwork worker threads. - Asynchronous Detection (YOLO): Heavy convolutional neural network (CNN) inference is offloaded from the API tier to an isolated
product-vision-processorworker, which translates graphical pixels into a canonical text class representing the item. - Censorship Perimeter Reuse: Once detection is complete, the extracted text string is automatically routed to the existing
censorship-control-worker. This guarantees that unified edge security policies are enforced (Fail-Close via Redis).
Interaction Protocol (HTTP Contract)
- Method:
POST - Route:
/api/v1/purchase/upload-product-photo - Data Format:
multipart/form-data
Headers Specification (HTTP Headers)
| Header | Required | Description | Example Value |
|---|---|---|---|
Content-Type |
Yes | Indicates the transmission of composite form data (multipart). | multipart/form-data; boundary=----WebKitFormBoundary... |
Authorization |
Yes | Access token used to extract the user_id and the multi-tenancy home_group_id stamp. |
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... |
X-Request-ID |
Yes | End-to-end request ID to trace the session lifecycle (FastAPI \(\rightarrow\) MinIO \(\rightarrow\) Kafka \(\rightarrow\) Workers). | req-5f9c-2b1a-88ef |
Accept |
No | Expected response format from the backend gateway. | application/json |
Query Parameters Specification
| Parameter | Type | Required | Description | Example Value |
|---|---|---|---|---|
app_lang |
String | Yes | Target application language used to adapt the system prompt at the downstream censorship phase. | ru |
Request Body Specification (Request Body — Multipart FormData)
| Field | Type | Required | Description | Example Value |
|---|---|---|---|---|
file |
Binary (File) | Yes | Raw binary data of the product photo (image/jpeg, image/png). Constraint: up to 10 MB. |
snapshot.jpg |
crop_type |
String | No | Matrix cropping and preprocessing mode for the AI worker (default, square, raw). |
"square" |
Raw HTTP Request Example (Payload):
POST /api/v1/purchase/upload-product-photo?app_lang=ru HTTP/1.1
Host: foodlifecycle.com
Authorization: Bearer eyJhbGciOiJIUzI1Ni...
X-Request-ID: req-5f9c-2b1a-88ef
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="snapshot.jpg"
Content-Type: image/jpeg
[BINARY_IMAGE_DATA]
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="crop_type"
square
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Метод предназначен для асинхронной обработки и распознавания изображений продуктов (или чеков) с использованием компьютерного зрения (YOLO).
В рамках новой архитектуры этот метод выполняет роль поставщика медиа-контекста (Vision Context Provider):
- Изоляция бинарного трафика: Шлюз
FastAPIне держит изображение в оперативной памяти во время инференса, а мгновенно сбрасывает его в распределенное объектное хранилищеMinIO (S3), освобождая сетевые потокиUvicorn. - Асинхронная детекция (YOLO): Тяжелый инференс сверточных нейросетей вынесен из API-слоя в изолированный воркер
product-vision-processor, который транслирует графические пиксели в текстовый канонический класс предмета. - Переиспользование контура защиты: После детекции текстовая строка автоматически направляется в уже существующий воркер цензуры (
censorship-control-worker), что гарантирует соблюдение единых политик безопасности периметра (Fail-Close через Redis).
Протокол взаимодействия (HTTP Контракт)
- Метод:
POST - Маршрут:
/api/v1/purchase/upload-product-photo - Формат данных:
multipart/form-data
Спецификация заголовков (HTTP Headers)
| Заголовок | Обязательный | Описание | Пример значения |
|---|---|---|---|
Content-Type |
Да | Указывает на передачу составных данных формы (мультипарт) | multipart/form-data; boundary=----WebKitFormBoundary... |
Authorization |
Да | Токен авторизации для извлечения user_id и Multi-Tenancy клейма home_group_id |
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... |
X-Request-ID |
Да | Сквозной ID запроса для трассировки сессии (FastAPI \(\rightarrow\) MinIO \(\rightarrow\) Kafka \(\rightarrow\) Workers) | req-5f9c-2b1a-88ef |
Accept |
Нет | Ожидаемый формат ответа от бэкенд-шлюза | application/json |
Спецификация параметров запроса (Query Parameters)
| Параметр | Тип | Обязательный | Описание | Пример значения |
|---|---|---|---|---|
app_lang |
String | Да | Целевой язык приложения для адаптации системного промпта на этапе цензуры | ru |
Спецификация тела запроса (Request Body — Multipart FormData)
| Поле | Тип | Обязательный | Описание | Пример значения |
|---|---|---|---|---|
file |
Binary (File) | Да | Бинарный файл фотографии продукта (image/jpeg, image/png). Ограничение: до 10 МБ. |
snapshot.jpg |
crop_type |
String | Нет | Режим кадрирования и предобработки матрицы для ИИ-воркера (default, square, raw) |
"square" |
Пример сырого HTTP-запроса (Payload):
POST /api/v1/purchase/upload-product-photo?app_lang=ru HTTP/1.1
Host: foodlifecycle.com
Authorization: Bearer eyJhbGciOiJIUzI1Ni...
X-Request-ID: req-5f9c-2b1a-88ef
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="snapshot.jpg"
Content-Type: image/jpeg
[БИНАРНЫЕ ДАННЫЕ ИЗОБРАЖЕНИЯ]
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="crop_type"
square
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Диаграмма последовательности (Mermaid)
sequenceDiagram
autonumber
actor App as APP (📱 Клиент)
participant GW as GATEWAY (FastAPI)
participant S3 as MinIO (S3 Storage)
participant K as Брокер: Kafka
participant Vision as product-vision (YOLO)
participant Censor as censorship-worker
%% ЧАСТЬ А: ЗАГРУЗКА И ПУШ В ОЧЕРЕДЬ
App->>GW: POST /upload-product-photo (Multipart, lang)
activate GW
GW->>S3: PutObject: Сохранение файла изображения
activate S3
S3-->>GW: Возврат image_file_url
deactivate S3
note over GW: trace_id Generation & Payload Assembly
GW->>K: Пуш в топик: bpds.inventory.in.product.image
GW-->>App: HTTP 202 Accepted (Шлюз свободен)
deactivate GW
%% ЧАСТЬ Б: YOLO ДЕТЕКЦИЯ
K->>Vision: Handler: ProcessProductImage()
activate Vision
Vision->>S3: GetObject: Скачивание по URL
activate S3
S3-->>Vision: Бинарный графический поток
deactivate S3
note over Vision: YOLO Inference:<br/>Локализация контуров и детекция класса
Vision->>K: Пуш в топик: bpds.inventory.in.receipt.upload
deactivate Vision
Расшифровка шагов
This documentation section is currently under development and may contain incomplete data. Some technical descriptions, parameters, and system operation scenarios for the digital business process simulator are subject to change.
- Stable documentation version: Will be published upon final completion and validation of the method code.
| Step | Action | Parameters / Requests / DTO | Errors (Exceptions / Statuses) |
|---|---|---|---|
1 (Gateway -> MinIO) |
The API Gateway captures the raw binary product photo (.jpg or .png) from the user’s mobile client, validates its size and media signature, and streams it to the S3 bucket. |
S3 API PUT Object Request: Bucket: "product-images", Key: "uploads/2026/07/product_photo_202.jpg"Headers: Content-Type: image/jpeg, Content-Length: 3145728 |
IAD-VISION-422: Unsupported mime-type or invalid file signature format.IAD-VISION-413: File size exceeds the allowed 10 MB limit. |
2 (MinIO -> Gateway) |
MinIO flushes the incoming image stream to disk arrays and returns an internal URL reference of the stored graphic object to the API Gateway. | S3 API PUT Object Response: HTTP Status: 200 OKETag: "4a28c319ba27d3322d8d8a7c5cb9c402", URL: https://minio.internal |
No business errors |
3 (Gateway -> T_Photo) |
The gateway constructs the initial computer vision task DTO, embeds application language metadata with the end-to-end trace ID, and publishes the message to the Kafka broker. | Kafka Message (Topic: bpds.inventory.in.product.image):Payload: { "image_file_url": "https://minio.internal", "app_lang": "ru-RU", "x_request_id": "trace-cv-censor-uuid" } |
IAD-VAL-400: Mandatory payload metadata properties or structural parameters are missing. |
4 (T_Photo -> ProductAI) |
The product-vision-processor microservice, subscribed to the product image topic, polls the next task event from the queue to run object analysis. |
Kafka Consumer Poll Request:Group_ID: "product-cv-processors", Payload from Step 3 received.Partition: 2, Offset: 99412 |
No business errors |
5 (ProductAI -> MinIO) |
The computer vision service calls the S3 object store endpoint to fetch the image matrix binary stream into the temporary GPU/CPU memory allocation buffer. | HTTP GET /product-images/uploads/2026/07/product_photo_202.jpg: Headers: Internal Auth Tokens. Output: raw binary graphics byte stream. |
IAD-VISION-404: Target source image asset was not found or deleted from storage before processing. |
6 (ProductAI -> T_Results) |
The local YOLO model delineates object boundaries and maps them to a string representation of the item class. The outcome is pushed to the unified input topic along with the trace ID. | Kafka Message (Topic: bpds.inventory.in.receipt.upload):Payload: { "raw_text_input": "Груша Конференция", "app_lang": "ru-RU", "x_request_id": "trace-cv-censor-uuid" } |
IAD-YOLO-422: Detection confidence score dropped below safety threshold or model classification failed. |
| Шаг | Действие | Параметры / Запросы / DTO | Ошибки (Исключения / Статусы) |
|---|---|---|---|
Шаг 1 (Gateway -> MinIO) |
API-шлюз принимает бинарный файл фотографии продукта (.jpg или .png) со смартфона пользователя, выполняет валидацию размера и сигнатуры медиафайла, после чего загружает его в S3-бакет. |
S3 API PUT Object Request: Bucket: "product-images", Key: "uploads/2026/07/product_photo_202.jpg"Headers: Content-Type: image/jpeg, Content-Length: 3145728 |
MinIOException: BucketNotFoundMinIOException: AccessDenied (неверные или просроченные учетные данные API Gateway)StorageFullException |
Шаг 2 (MinIO -> Gateway) |
MinIO сохраняет изображение на диски и возвращает API-шлюзу внутреннюю URL-ссылку на загруженный графический объект. | S3 API PUT Object Response: HTTP Статус: 200 OKETag: "4a28c319ba27d3322d8d8a7c5cb9c402", URL: https://minio.internal |
MinIOException: ConnectionTimeoutDiskWriteError (критическая ошибка ввода-вывода или размонтирование RAID-массива) |
Шаг 3 (Gateway -> T_Photo) |
Шлюз формирует стартовое DTO задачи компьютерного зрения, внедряет метаданные языка локали приложения, сквозной trace-id и отправляет сообщение в брокер Kafka. | Kafka Message (Topic: bpds.inventory.in.product.image):Payload: { "image_file_url": "https://minio.internal", "app_lang": "ru-RU", "x_request_id": "trace-cv-censor-uuid" } |
FastAPI.ValidationError (передан некорректный URL или отсутствуют обязательные поля)KafkaException: QueueFullExceptionMessageTimedOut |
Шаг 4 (T_Photo -> ProductAI) |
Микросервис product-vision-processor, подписанный на топик изображений продуктов, вычитывает очередную задачу для проведения объектного анализа. |
Kafka Consumer Poll Request:Group_ID: "product-cv-processors", Получен payload шага 3.Partition: 2, Offset: 99412 |
KafkaException: CommitFailedException (зависание потока детекции, консьюмер выпал из группы по таймауту)SerializationException |
Шаг 5 (ProductAI -> MinIO) |
Сервис компьютерного зрения обращается к объектному хранилищу S3 для скачивания бинарной матрицы картинки во временный буфер памяти GPU/CPU. | HTTP GET /product-images/uploads/2026/07/product_photo_202.jpg: Headers: Internal Auth Tokens. На выходе: бинарный поток байт графического файла. |
HTTP 404 Not Found (файл удален из бакета до начала обработки воркером)HTTP 403 ForbiddenConnectTimeout |
Шаг 6 (ProductAI -> T_Results) |
Локальная нейросеть YOLO определяет границы объекта и транслирует его в строковое имя класса (например, ‘Груша’). Результат вместе с trace-id пушится в общий топик. | Kafka Message (Topic: bpds.inventory.in.receipt.upload):Payload: { "raw_text_input": "Груша Конференция", "app_lang": "ru-RU", "x_request_id": "trace-cv-censor-uuid" } |
YOLOInferenceError (низкая уверенность модели или сбой CUDA ядра)KafkaException: DeliveryTimeoutKafkaException: RecordTooLargeException |
Спецификация ответов сервера (Response Body)
This documentation section is currently under development and may contain incomplete data. Some technical descriptions, parameters, and system operation scenarios for the digital business process simulator are subject to change.
- Stable documentation version: Will be published upon final completion and validation of the method code.
1. Успешные ответы (Success Responses)
HTTP 202 Accepted (Успешный асинхронный ответ — Шаг 6)
Возвращается мобильному приложению шлюзом FastAPI Gateway мгновенно после успешного сохранения бинарного multipart-потока в MinIO S3 и публикации задачи в топик брокера сообщений Kafka.
- Заголовки ответа (Response Headers):
Content-Type: application/json
- Тело ответа (Response Body):
{
"status": "PHOTO_UPLOAD_ACCEPTED",
"data": {
"trace_id": "req-5f9c-2b1a-88ef",
"message": "Фотография успешно загружена в S3-хранилище и принята в пайплайн ИИ-детекции YOLO.",
"processed_at": "2026-07-20T23:21:00Z"
}
}HTTP 201 Created (Асинхронный Исход 10а / Финальное авто-подтверждение)
Генерируется на финальном этапе обработки чека или фото после успешного прохождения цензуры, NER-распознавания и параллельной фиксации (Fan-Out) транзакций в инвентарных базах данных.
- Заголовки ответа (Response Headers):
Content-Type: application/json
- Тело ответа (Response Body):
{
"status": "CONFIRMED",
"product_name": "ГРУША",
"applied_quantity": 1.0,
"unit": "шт",
"timestamp": "2026-07-20T23:21:00Z"
}2. Спецификация ошибок и исключений (Error Responses)
Все ошибки бэкенда возвращаются в едином стандартизированном формате RFC 7807 (Problem Details) или стандартном JSON-формате FastAPI HTTPException. Это позволяет Flutter-клиенту (Dio) однозначно парсить код ошибки и выводить корректный локализованный текст на основе динамического справочника.
Исключение: Низкое качество изображения / Сбой распознавания (Асинхронный Исход 10б)
Формируется ИИ-воркером, если модель YOLO вернула score уверенности ниже порогового значения 0.85. Пайплайн инвентаризации приостанавливается, система генерирует черновик и отправляет пуш-контекст на UI через WebSocket.
{
"error_code": "ERR-LOW-VISION-CONFIDENCE",
"message": "Не удалось однозначно распознать продукт на фотографии. Требуется ручное подтверждение.",
"details": {
"yolo_score": 0.54,
"image_snapshot_url": "s3://raw-images/uuid-99.jpg",
"action": "Render interactive draft card on UI with user text-input field fallback."
}
}Ошибка загрузки и персистентности файла в бакет (HTTP 500 Internal Server Error — Шаг 2)
Выбрасывается шлюзом FastAPI, если внутренний кластер MinIO S3 недоступен, пул соединений переполнен или хранилище выдало отказ на прием бинарного потока put_object().
{
"error_code": "ERR-BUCKET",
"message": "Не удалось сохранить или верифицировать медиафайл во внутреннем объектном хранилище.",
"details": {
"reason": "MinIO S3 storage cluster rejected input stream or partition disk is full."
}
}Ошибка ИИ-цензурирования и детекции (Асинхронный Исход 10в — Шаг 14в)
Формируется воркером цензуры, если в процессе распознавания или анализа текстового класса модели YOLO локальная нейросеть Ollama через gRPC зафиксировала попытку инъекции кода в метаданные, мат, спам или деструктивный контент (is_profane == true).
{
"error_code": "ERR-CENSOR",
"message": "Изображение или распознанный текст класса не прошли автоматическую проверку политик безопасности.",
"details": {
"reason": "Spam, explicit content, or prompt injection pattern detected by Ollama Guardrails."
}
}Ошибка валидации структуры контракта (HTTP 422 Unprocessable Entity — Шаг 1.1)
Выбрасывается шлюзом FastAPI, если размер переданного файла превышает лимит в 10 МБ, либо нарушена multipart-структура тела запроса формы.
{
"error_code": "IAD-VAL-422",
"message": "Переданные данные формы или файл не соответствуют ожидаемой схеме валидации Pydantic.",
"details": [
{
"loc": ["body", "file"],
"msg": "Размер загружаемой фотографии продукта не должен превышать 10 МБ.",
"type": "value_error.file.size_limit"
}
]
}