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 с полной БЖУ-карточкой
Метод GET /api/products/card?
Документация API: Асинхронное зачисление и ИИ-генерация карточки элемента «Периодической системы продуктов» через событийно-ориентированный контур Kafka
- MDM-016 Ready for Development — создать метод.
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
Функциональное назначение
Метод является входной точкой для получения карточки продукта. Он обрабатывает текстовые запросы от мобильного приложения и возвращает карточку продукта содеращаю данные о продукте его составе.
Метод решает три задачи:
- Быстрый неблокирующий прием (Async Acknowledge): Шлюз фиксирует факт запроса в базе данных со статусом
PENDING, избавляя пользователя от необходимости ожидать завершения работы ИИ-генератора. - Событийное квотирование нагрузки (Kafka Queueing): Задача инкапсулируется в сообщение и отправляется в брокер сообщений Kafka (Redpanda). Это защищает ИИ-воркеры от пиковых нагрузок и упорядочивает транзакции.
- Автоматическое ИИ-обогащение 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)
Расшифровка шагов работы метода
| Шаг | Действие | Параметры / Запросы | Ошибки (Исключения / Статусы) |
|---|---|---|---|
Шаг 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."
}
}