Microservice: ИИ-сервисы, локальные модели в бизнес-процессах
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
Начало
Создадим 4 отдельных, полностью рабочих микросервиса на Python (FastAPI), каждый в своей папке, как в проекте. Они будут общаться с Ollama и крутиться на выделенных портах Ubuntu. В каждом сервисе мы используем единый стиль логирования, анкеты Pydantic и DTO-заглушки (fallback), чтобы при перегрузке CPU или таймауте система не падала, а возвращала предсказуемый результат.
Сервис 1: ai-receipt-gateway
- Порт: 11435
- Модель: llama3.2-vision:11b (Мультимодальная)
- Задача: Принять фото чека в Base64, распознать его и выдать сырой структурированный JSON продуктов.
- github
Этот сервис принимает Base64-картинку от Go, оборачивает её в строгий системный промпт, заставляет Ollama вытащить продукты и возвращает результат в Go.
Сервис 2: ai-voice-gateway
- Порт: 11436
- Модель: whisper-base (Распознавание речи)
- Задача: Принять аудиофайл в Base64, перевести его в сырой текст и вернуть текстовую строку.
- github
Этот сервис принимает Base64-аудио от Go, отправляет его в Whisper для перевода речи в текст и возвращает чистую текстовую строку.
Сервис 3: ai-voice-parser
- Порт: 11437
- Модель: qwen2.5:3b (Текстовая)
- Задача: Принять сырой текст из Whisper, вытащить продукты и провести валидацию параметров. Если порций или веса нет — выставить статус invalid и отправить на модерацию.
- github
Этот сервис занимается только одной задачей: берет распознанный текст из Whisper, проверяет наличие названия, веса и порций. Если чего-то не хватает — бракует строку и выставляет статус invalid для модерации.
Сервис 4: ai-profanity-filter
- Порт: 11438
- Модель: qwen2.5:3b (Текстовая)
- Задача: Финальный этап для чеков и валидного голоса. Заменяет мат на звездочки * и удаляет спам-позиции из массива.
- github
Этот сервис вызывается Воркером 2 (как для чеков, так и для валидного голоса). Он проверяет финальный JSON продуктов, заменяет нецензурную лексику на звездочки * и выкидывает мусорные спам-позиции из массива.
Разница между ними в том, в каком виде данные выходят из первой фазы:
- Чеки (ai-receipt-gateway): На вход этого сервиса подаётся картинка, но внутри работает мультимодальная модель llama3.2-vision:11b. Она одновременно работает и как OCR (читает текст с фото), и как парсер. На выходе из этого сервиса сразу получается готовый структурированный JSON продуктов, а не сырой текст. Модели со зрением умеют делать это за один шаг. Поэтому чекам сервис ai-voice-parser не нужен. Они сразу летят на фильтрацию мата и спама (ai-profanity-filter).
- Голос (ai-voice-gateway): На вход подаётся аудио. Модель whisper умеет делать только одну вещь — переводить звук в текст. На выходе мы получаем сырую текстовую строку (например: “я купил две пачки молока по двести грамм”). И вот этот сырой текст мы не можем сразу отправить на фильтр мата, потому что это ещё не JSON. Нам нужно сначала превратить его в структурированные продукты. Именно для этого и нужен ai-voice-parser (на базе текстовой qwen2.5:3b). Он берёт сырую строку текста от Whisper, извлекает сущности, проверяет наличие веса/порций и собирает такой же JSON продуктов, какой чековый сервис собрал из картинки. Итоговые цепочки (пайплайны) в Кафке:
• Пайплайн ЧЕКОВ: Картинка чека ──► [ai-receipt-gateway] ──► Сырой JSON продуктов ──► [ai-profanity-filter] ──► Чистый JSON ──► [БД] • Пайплайн ГОЛОСА: Звуковой файл ──► [ai-voice-gateway] ──► Сырой текст речи ──► [ai-voice-parser] ──► Сырой JSON продуктов ──► [ai-profanity-filter] ──► Чистый JSON ──► [БД]
На этапе перед фильтром мата оба потока объединяются, потому что из ai-receipt-gateway и из ai-voice-parser выходят абсолютно одинаковые по структуре JSON-файлы.
Сценарий 1: Загрузка чека (Фотографии) и Аудио (VTT) с мобильного приложения
Эта диаграмма показывает синхронную фазу (gRPC-стриминг от мобильного приложения) и то, как Go-сервис мгновенно освобождает клиента, отправляя данные в асинхронный пайплайн.
📱 Мобилка 🟢 Go Сервис S3 MinIO 🪪 Auth-Service 🦫 Брокер Kafka
│ │ │ │ │
│─── 1. gRPC Stream ─> │ │ │
│ UploadReceipt() │ │ │ │
│ [Metadata: token] │ │ │ │
│ │─── 2. gRPC Call ────────────────────────>│ │
│ │ ValidateToken(token) │ │ │
│ │<── 3. gRPC Return ───────────────────────│ │
│ │ [IsValid: true, GroupID] │ │
│ │ │ │ │
│─── 4. gRPC Stream ─> │ │ │
│ [Send Chunks...] │ │ │ │
│─── 5. End Stream ──> │ │ │
│ │── 6. PutObject() ──>│ │ │
│ │ [Save raw file] │ │ │
│ │<─ 7. Return Path ───│ │ │
│ │ │ │ │
│ │── 8. PublishEvent() ───────────────────────────────────────────>│
│ │ [receipt_id, s3_link, group_id] │ │ To Topic:
│ │ │ receipt-images-topic
│<─ 9. gRPC Response │ │ (или receipt-audio-topic)
│ [Status: processing, receipt_id] │
Сценарий 2: Асинхронный пайплайн обработки (Очередь Kafka & ИИ-модели)
Эта диаграмма описывает фоновую фазу, когда вы поочередно запускаете ИИ-модели на Ubuntu-машине. Обратите внимание, как аудиосообщение (VTT) проверяется на полноту данных и, в случае брака, улетает в топик модерации.
🦫 Брокер Kafka 🤖 Воркер 1/3 (Go) S3 MinIO 🧠 ИИ (Ubuntu) 🤖 Воркер 2 (Go) 🗄 Core tracker-app
│ │ │ │ │ │
│── 1. PollFetches() ──>│ │ │ │ │
│ [New S3 Event] │ │ │ │ │
│ │── 2. Download ───>│ │ │ │
│ │ FileBytes() │ │ │ │
│ │<─ 3. Return Bytes │ │ │ │
│ │ │ │ │ │
│ │── 4. HTTP POST (Base64/Text) ───────>│ │ │
│ │ ExtractEntities() / Recognize() │ │ │
│ │<── 5. HTTP Return (JSON Text) ───────│ │ │
│ │ │ │ │
│ │ [ЕСЛИ ЭТО ГОЛОС: ХВАТАЕТ ВЕСА/ПОРЦИЙ?] │ │
│ │───[НЕТ]───► Публикация в receipt-moderation-topic ────────> (В таблицу модерации) │
│ │ │ │ │
│ │───[ДА]───► 6. PublishEvent() ─────────────────────────────>│ │
│ To: receipt-raw-products-topic │ │
│ │── 7. PollFetches ─>│
│ │ [Raw JSON] │
│ │ │
│ │── 8. HTTP POST ───>│
│ │ FilterProfanity()│
│ │<─ 9. HTTP Return ──│
│ │ [Clean JSON] │
│ │ │
│ │── 10. Publish ────>│
│ To Topic:
│ receipt-clean-products-topic
│ │
│ 11. Read & Commit ──>│
│ │── 12. SQL Write ──> [PostgreSQL]
Сценарий 3: B2B Интеграция с магазинами (Паттерн Request-Reply / Webhook)
Эта диаграмма детально описывает интеграцию сторонних магазинов, проверку их токенов по нашей новой receipt_processor_db, отправку чека напрямую в базу трекера и асинхронный обратный вызов (вебхук) через StoreCallbackWorker.
🏢 Магазин API 🟢 Go Сервис 🗄 Локальная БД 🦫 Брокер Kafka 🗄 Core tracker-app
│ │ │ │ │
│─ 1. gRPC Request ─> │ │ │
│ RegisterStoreReceipt(store_token) │ │ │
│ │── 2. SQL Query ─>│ │ │
│ │ GetPartnerByToken() │ │
│ │<─ 3. SQL Return ─│ │ │
│ │ [Partner Valid, WebhookURL] │ │
│ │ │ │ │
│ │── 4. SQL Write ─>│ │ │
│ │ CreateStoreTransaction(status: 'accepted') │
│ │ │ │ │
│ │── 5. ProduceSync() (Прямой пуш, минуя ИИ) ──────────────────>│
│ │ Headers: reply_to='store-callbacks-topic' │ To Topic:
│ │ Headers: correlation_id='TX-STORE-123' │ receipt-clean-products-topic
│ │ │ │
│<─ 6. gRPC Response │ │ │
│ [Status: accepted, correlation_id] │ │
│ │ │── 7. Read Record ─>│
│ │ │ [Commit to DB] │
│ │ │ │
│ │<─ 8. Push Reply ───│
│ │ To Topic: │
│ │ store-callbacks-topic
│ │ │
│ ┌─────────────────────────────────────────┘ │
│ │ 9. PollFetches() (StoreCallbackWorker) │
│ ▼ │
│ 🟢 Go Сервис │
│ │ │
│ │── 10. SQL Query ─>│ │
│ │ GetWebhookURLByCorrelationID() │
│ │<─ 11. SQL Return ─│ │
│ │ [WebhookURL, StoreReceiptNo] │
│ │ │ │
│─ 12. HTTP POST ────│ │ │
│ (Webhook Callback)│ │ │
│ [Chit-Status] │ │ │
│<─ 13. HTTP 200 OK ─│ │ │
│ │ │ │
│ │── 14. SQL Update ──────────────────────>│ │
│ UpdateTransactionStatus(status: 'processed') │