Метод GET /api/products/card?

Документация API: Асинхронное зачисление и ИИ-генерация карточки элемента «Периодической системы продуктов» через событийно-ориентированный контур Kafka

Published

July 3, 2026

WarningОграничение публичной документации

В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.

  • Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).

Функциональное назначение

Метод является входной точкой для получения карточки продукта. Он обрабатывает текстовые запросы от мобильного приложения и возвращает карточку продукта содеращаю данные о продукте его составе.

Метод решает три задачи:

  1. Быстрый неблокирующий прием (Async Acknowledge): Шлюз фиксирует факт запроса в базе данных со статусом PENDING, избавляя пользователя от необходимости ожидать завершения работы ИИ-генератора.
  2. Событийное квотирование нагрузки (Kafka Queueing): Задача инкапсулируется в сообщение и отправляется в брокер сообщений Kafka (Redpanda). Это защищает ИИ-воркеры от пиковых нагрузок и упорядочивает транзакции.
  3. Автоматическое ИИ-обогащение Master Data: Изолированный Python-контур (Consumer) перехватывает задачу, обращается к LLM по технологии Structured Outputs и сохраняет детальный физико-химический паспорт продукта в гибком поле JSONB базы данных PostgreSQL.

Протокол взаимодействия (HTTP Контракт)

  • Метод: POST
  • Маршрут: /api/products/card?
  • Формат данных: application/json

Спецификация заголовков (HTTP Headers)

Заголовок Обязательный Описание Пример значения
Content-Type Да Указывает на передачу строго типизированного JSON-пакета application/json
X-Request-ID Да Сквозной ID для трассировки логов между FastAPI и ИИ-воркером через Kafka req-atomic-egg-77bb

Спецификация тела запроса (Request Body)

Поле Тип Обязательный Описание Пример значения
name String Да Сырая текстовая строка (наименование продукта или CV-тег) "Яйцо куриное"

Пример сырого JSON-запроса (Payload):

{
  "name": "Яйцо куриное С1"
}

Схема обработки запроса пользователя (Mermaid)

sequenceDiagram
    autonumber
    actor User as Пользователь (Экран добавления)
    participant APP as Мобильное приложение (Flutter)
    participant API as Бэкенд-шлюз (FastAPI)
    participant DB as Реляционная СУБД (PostgreSQL)
    participant KAFKA as Брокер событий (Kafka/Redpanda)
    participant WK as ИИ-Воркер (Python Consumer)
    participant AI as Сервис ИИ (OpenAI API gpt-4o)

    User->>APP: Вводит текст ("Яйцо"), нажимает "Добавить"
    APP->>API: HTTP POST /api/products (JSON с name)
    activate API
    
    note over API: Шаг 3: Первичная Pydantic-валидация и нормализация строки
    API->>DB: SELECT status FROM food_elements WHERE input_name = 'яйцо'
    activate DB
    DB-->>API: Элемент отсутствует (null)
    deactivate DB
    
    Note over API, DB: Старт атомарной SQL-транзакции
    API->>DB: INSERT INTO food_elements (input_name, status) VALUES ('яйцо', 'PENDING')
    activate DB
    DB-->>API: Успешная фиксация PENDING-записи
    deactivate DB
    Note over API, DB: Коммит атомарной транзакции (COMMIT)
    
    API->>KAFKA: Отправка сообщения в топик "product-generation"
    API-->>APP: HTTP 202 Accepted (Задача принята к исполнению)
    deactivate API
    note over APP: Пользователь видит продукт со статусом "Синтез карточки элемента..."
    
    %% Асинхронный контур
    activate WK
    KAFKA->>WK: Извлечение сообщения {"input_name": "яйцо"}
    note over WK: Шаг 11: Формирование строгого JSON-промпта с Pydantic-схемой
    WK->>AI: Запрос Structured Outputs (gpt-4o)
    activate AI
    AI-->>WK: Валидный JSON (Паспорт элемента Eg: БЖУ, валентность, фазы)
    deactivate AI
    
    WK->>DB: UPDATE food_elements SET chemical_card = JSONB, status = 'READY' WHERE input_name = 'яйцо'
    activate DB
    DB-->>WK: Успешное сохранение мастер-данных
    deactivate DB
    deactivate WK
    
    note over APP: При следующем пуллинге/обновлении экрана продукт переходит в статус READY с полной БЖУ-карточкой

Расшифровка шагов работы метода

Шаг Действие Параметры / Запросы Ошибки (Исключения / Статусы)
Шаг 1 (User -> APP) Пользователь вручную вводит текстовое наименование продукта и инициирует его добавление. Ввод строки (например, “Яйцо”), нажатие кнопки «Добавить» EmptyInputException (пустая строка или пробелы)

Спецификация ответов сервера (Response Body) и ошибок

Успешные ответы (Success Responses)

HTTP 202 Accepted (Ответ на Шаге 7)

Возвращается мобильному приложению Flutter мгновенно, подтверждая успешный запуск асинхронной транзакции и публикацию задачи в Kafka.

  • Заголовки ответа (Response Headers):
    • Content-Type: application/json
  • Тело ответа (Response Body):
{
  "status": "PENDING",
  "message": "Product added to processing queue."
}

HTTP 200 OK (Прямой кэш-ответ на Шаге 4)

Возвращается, если продукт уже присутствует в глобальном справочнике. Поле chemical_card извлекается из JSONB-хранилища PostgreSQL.

{
  "status": "READY",
  "card": {
    "symbol": "Eg",
    "official_name": "Яйцо",
    "group_name": "Протеины",
    "period": 3,
    "calories_per_100g": 157.0,
    "proteins": 12.7,
    "fats": 11.5,
    "carbs": 0.7,
    "cooking_valence": 2,
    "chemical_props": {
      "phase_transitions": {
        "62C-65C": "Начало денатурации белка, потеря прозрачности",
        "65C-70C": "Загустевание желтка, сохранение пластичности",
        "above_80C": "Полное затвердевание. Риск выделения сероводорода"
      },
      "activators": ["Кислота (H+ для пашот-эффекта)"],
      "inhibitors": ["Жир (блокирует аэрацию белков)"]
    },
    "common_ocr_synonyms": ["яйцо", "яйца куриные", "egg", "яйцо кур с1"]
  }
}

Спецификация интеграционного gRPC-контракта Стриминга (Шаг 10)

Описание внутренней внутренней структуры Protocol Buffers (ai_generation.proto) для обмена данными между ИИ-воркером и LLM-шлюзом в структурированном JSON-режиме.

syntax = "proto3";

package masterdata.periodic.v1;

service FoodSynthesisService {
  // Получение строго типизированной карты химических свойств продукта
  rpc SynthesizeFoodCard (FoodSynthesisRequest) returns (FoodSynthesisResponse);
}

message FoodSynthesisRequest {
  string product_name = 1;
}

message FoodSynthesisResponse {
  string json_structured_output = 1; // Сериализованная Pydantic-модель MasterFoodCard
}

Вилки исключений и обработка ошибок

Ошибка валидации структуры входных данных (HTTP 422 Unprocessable Entity — Шаг 4)

Выбрасывается бэкенд-шлюзом FastAPI, если входящее имя продукта передано пустым или нарушает строковый тип данных.

{
  "error_code": "ERR-VALIDATION-FAILED",
  "message": "Переданный JSON-пакет содержит пустое или некорректное имя продукта.",
  "details": [
    {
      "loc": ["body", "name"],
      "msg": "Поле наименования элемента не может быть пустой строкой",
      "type": "value_error.str.min_length"
    }
  ]
}

Ошибка краха ИИ-синтеза воркера (Фоновая фиксация — Шаг 12)

Если на Шаге 10 провайдер ИИ выдал ошибку (Rate Limit / Timeout) или Pydantic-валидатор воркера зафиксировал сбой структуры ответа, транзакция ИИ-коммита отменяется, а статус в БД переводится в аварийный режим.

{
  "error_code": "ERR-ATOMIC-SYNTHESIS-FAILED",
  "message": "Асинхронный синтез элемента прерван: ошибка генерации карточки ИИ-провайдером.",
  "details": {
    "input_name": "яйцо куриное с1",
    "status": "FAILED",
    "action": "Task put back in Dead Letter Queue for reprocessing or manual admin auditing."
  }
}