Метод gRPC /analytics.v1.AnalyticsService/CheckProduct

Внутренний контракт: ИИ-модерация текста, проверка обсценной лексики и валидация по справочнику Master Data

Published

July 1, 2026

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

Метод CheckProduct предназначен для глубокого анализа, цензурирования и бизнес-валидации сырого текстового ввода (raw_text_input), полученного после OCR-распознавания чека или ручного исправления пользователем.

Метод решает три задачи в рамках единого вызова:

  1. NLP-модерация: Проверка строки на наличие ненормативной лексики, спама или оскорблений с помощью ИИ.
  2. MDM-валидация: Сверка очищенного текста со справочником мастер-данных продуктов питания в PostgreSQL для отсечения нецелевых категорий (например, «носки», «бытовая химия»).
  3. Канонизация: Автоматический маппинг пользовательских синонимов и уменьшительно-ласкательных форм к официальным товарным наименованиям (например, «апельсинки» → «АПЕЛЬСИНЫ») с привязкой категории.

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

  • Протокол: gRPC поверх HTTP/2
  • Тип вызова: Unary RPC (Один запрос — Один ответ)
  • Пакет (Package): analytics.v1
  • Сервис (Service): AnalyticsService
  • Метод: CheckProduct

2.1 Спецификация заголовков (gRPC Metadata)

Поскольку gRPC использует HTTP/2, метаданные передаются в виде бинарных или текстовых пар ключ-значение в кадрах HEADERS.

Ключ Метаданных Обязательный Описание Пример значения
x-request-id Да Сквозной ID исходного HTTP-запроса для распределенного логирования req-5f9c-2b1a-88ef
content-type Да Системный заголовок HTTP/2 application/grpc
user-agent Нет Идентификатор вызывающей библиотеки/клиента grpc-python/1.60.0 FastAPI-Worker

2.2 Спецификация тела запроса (Protocol Buffers Message)

Контракт описывается в файле analytics.proto. Все строковые поля используют кодировку UTF-8.

syntax = "proto3";

package analytics.v1;

message ProductCheckRequest {
  string raw_text_input = 1; // Сырой текст, введенный пользователем или распознанный OCR
  string user_id = 2;        // Уникальный идентификатор пользователя (UUID)
}

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

Диаграмма описывает внутреннее поведение gRPC-сервиса, включая вилки исключений при обнаружении ненормативной лексики и отсутствии товара в справочнике мастер-данных.

sequenceDiagram
    autonumber
    participant API as Бэкенд-шлюз (FastAPI)
    participant GRPC as ИИ-сервис (PyTorch / gRPC)
    participant DB as Мастер-Данные (PostgreSQL)
    participant KAFKA as Брокер событий (Kafka)

    API->>GRPC: gRPC CheckProduct(raw_text_input, user_id)
    activate GRPC
    
    note over GRPC: Шаг 2: Токенизация и NLP-фильтрация текста
    alt Обнаружен мат / спам / оскорбления
        GRPC-->>API: gRPC error (StatusCode.INVALID_ARGUMENT, "REJECTED_CENSOR")
    else Текст успешно прошел цензуру
        GRPC->>DB: SELECT FROM product_master_dictionary WHERE search_vector @@ ...
        activate DB
        DB-->>GRPC: Результат поиска (id, canonical_name, category_id)
        deactivate DB
        
        alt Совпадений в словаре не найдено (Не продукт питания)
            GRPC-->>API: gRPC error (StatusCode.NOT_FOUND, "REJECTED_NOT_FOOD")
        else Товар верифицирован в MDM
            note over GRPC: Шаг 5: Маппинг синонима в каноническое имя
            GRPC-->>API: gRPC ProductCheckResponse(status='APPROVED', canonical_name='АПЕЛЬСИНЫ')
            GRPC->>KAFKA: send_to_kafka_async("analytics.mdm.verified")
        end
    end
    deactivate GRPC

4 Расшифровка шагов

  • Шаг 1 (API -> GRPC): Фоновый воркер или синхронный роут бэкенд-шлюза FastAPI упаковывает текстовые данные в структуру ProductCheckRequest и отправляет удаленный вызов на gRPC-сервер аналитики. Передается сквозной x-request-id для трейсинга.
    • Стратегия Fail-Safe: Если gRPC-сервер находится в состоянии offline, FastAPI перехватывает ошибку сети, пишет предупреждение [Moderation Warning] в системный лог и пропускает запрос по сценарию ограниченного доверия, чтобы не блокировать действия человека.
  • Шаг 2 (GRPC -> GRPC): Внутри gRPC-сервиса запускается ИИ-контур: NLP-модель выполняет токенизацию строки и проверяет её на наличие мата, спама или явного бреда.
    • Вилка исключений (Мат/Спам): Если модель обнаруживает обсценную лексику, метод прерывает выполнение, транзакция бракуется и возвращается gRPC-ошибка REJECTED_CENSOR со статус-кодом INVALID_ARGUMENT. Бэкенд-шлюз мгновенно маппит это в HTTP-ошибку ERR-BUPAR-CENSOR (HTTP 400).
  • Шаг 3 (GRPC -> DB): Если текст чист, сервис обращается к реляционной СУБД PostgreSQL к таблице Мастер-данных (Master Data Management): SELECT id, category_id, canonical_name FROM product_master_dictionary WHERE search_vector @@ to_tsquery($1). Используется полнотекстовый поиск для сопоставления словоформ.
  • Шаг 4 (DB -> GRPC): База данных возвращает результат поиска на gRPC-сервер.
    • Вилка исключений (Не продукт): Если в словаре не найдено совпадений (пользователь ввел нецелевой объект, например, «кирпич» или «носки»), система возвращает gRPC-ошибка REJECTED_NOT_FOOD со статус-кодом NOT_FOUND. Бэкенд прерывает операцию на HTTP-контуре с ошибкой ERR-NOT-A-PRODUCT (HTTP 422).
  • Шаг 5 (GRPC -> GRPC): В случае успешного нахождения товара в словаре, ИИ-сервис производит автоматический маппинг синонима к каноническому имени (например, ввод «апельсинки» переводится в официальное "АПЕЛЬСИНЫ").
  • Шаг 6 (GRPC -> API): gRPC-сервер возвращает шлюзу FastAPI успешный строго типизированный ответ ProductCheckResponse.
  • Шаг 7 (GRPC -> KAFKA): Лог успешной валидации продукта параллельно отправляется gRPC-сервером в топик analytics.mdm.verified для обогащения дата-лейка аналитики и дообучения NLP-моделей.

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

5.1 Успешный ответ (Protobuf Message)

При успешном прохождении цензуры и нахождении продукта в справочнике возвращается структура ProductCheckResponse.

message ProductCheckResponse {
  string status = 1;         // Фиксированный статус одобрения: "APPROVED"
  string canonical_name = 2; // Каноническое название из словаря (например, "АПЕЛЬСИНЫ")
  int32 category_id = 3;     // ID продуктовой категории для дерева каталога
  float confidence_score = 4;// Метрика уверенности NLP-модели в маппинге синонима
}

5.1.1 Пример успешного ответа в JSON-эквиваленте:

{
  "status": "APPROVED",
  "canonical_name": "АПЕЛЬСИНЫ",
  "category_id": 12,
  "confidence_score": 0.985
}

5.2 Спецификация ошибок и системных кодов (gRPC Error Statuses)

Вместо HTTP-статусов gRPC возвращает канонические коды ошибок (gRPC Rich Error Model) совместно со строковым сообщением.

5.2.1 Ошибка 1: Обнаружение ненормативной лексики (Цензура)

  • gRPC Status Code: 3 (INVALID_ARGUMENT)
  • Сообщение (Message): REJECTED_CENSOR
  • Конвертация на FastAPI-шлюзе: Преобразуется в HTTP 400 Bad Request с бизнес-кодом ошибки ERR-BUPAR-CENSOR.

5.2.2 Ошибка 2: Объект отсутствует в продуктовой матрице (Не еда)

  • gRPC Status Code: 5 (NOT_FOUND)
  • Сообщение (Message): REJECTED_NOT_FOOD
  • Конвертация на FastAPI-шлюзе: Преобразуется в HTTP 422 Unprocessable Entity с бизнес-кодом ошибки ERR-NOT-A-PRODUCT.

5.2.3 Ошибка 3: Системный сбой базы данных справочников

  • gRPC Status Code: 14 (UNAVAILABLE)
  • Сообщение (Message): MDM_DATABASE_TIMEOUT
  • Конвертация на FastAPI-шлюзе: Преобразуется в HTTP 503 Service Unavailable с кодом ERR-DATABASE-OFFLINE. Поведение воркера переключается на стратегию Fail-Safe.