Гибридные пайплайны: CV+LLM, DIFF+LLM и ETL+ML

Задача страницы. Инженерный гид по проектированию и эксплуатации смешанных пайплайнов на GPU: — CV+LLM (детекция/сегментация/ОCR → рассуждение/инструкции), — DIFF+LLM (идеация/контроль генерации/оценка качества), — ETL+ML (GPU‑ETL → обучение/инференс). Разберём архитектуры, очереди и backpressure, микробатчинг, профилирование, экономику и устойчивость. Сосредоточимся на GPU‑эффективности, наблюдаемости и чётких SLA.

TL;DR

  • Архитектура как граф задач: декомпозируйте на независимые стадии (CV/LLM/DIFF/ETL/Rank), связывайте через очереди с HWM/LWM и явными таймаутами/ретраями.
  • Латентность vs throughput: для интерактива держите U≈0.6–0.75, маленькие батчи (≤ 4) и микрошаги 20–40 мс; для батчей — укрупняйте батчи и используйте Interruptible. См. https://cloudcompute.ru/solutions/throughput-vs-latency/ и https://cloudcompute.ru/solutions/interruptible-patterns/
  • GPU‑упаковка: лёгкие микросервисы (эмбеддинги, OCR, детекторы) выгодно сажать на MIG; тяжёлые LLM/диффузию — на цельные GPU. См. https://cloudcompute.ru/solutions/mig/
  • Кэш и артефакты: веса/токенайзеры/тайлы — на NVMe с прогревом; фичи/эмбеддинги — в локальный кэш. См. https://cloudcompute.ru/solutions/storage-data/
  • Наблюдаемость: E2E p95, stage_*_latency, queue_depth, drop/timeout, gpu_util/HBM, дешборды для деградаций/фоллбэков. См. https://cloudcompute.ru/solutions/llm-inference/observability/
  • Экономика: Cost_request = Σ (c_stage × t_stage / U_stage). Узкое место определяет throughput; оптимизация — балансировка и фьюзинг препроцесса.
  • Безопасность: PII/маскирование, guardrails перед LLM‑вызовами, версионирование промптов/моделей. См. https://cloudcompute.ru/solutions/security/ и https://cloudcompute.ru/solutions/llm-inference/observability/

Сценарии (когда это нужно)

  • CV+LLM: визуальный поиск и описания, чек‑листы качества, извлечение структур из документов (det→OCR→LLM), VQA, анализ производственных дефектов.
  • DIFF+LLM: генерация изображений по брифу с итеративным «критиком» (LLM), автокоррекция промптов, ControlNet/последующий апскейл.
  • ETL+ML: RAPIDS/Spark RAPIDS‑подготовка фичей → обучение (cuML/torch) → сервинг (Triton), RAG‑обогащение метаданными.
  • Композиты: видео‑аналитика + субтитры + LLM‑резюмирование; ASR→LLM→TTS для «голосовых ассистентов». См. https://cloudcompute.ru/solutions/realtime-streaming/

Архитектуры и пайплайны A) CV + LLM (Perception → Reasoning → Action)

Ingress (HTTP/WS) 
 └─> Preprocess (resize/normalize, NVJPEG/NVDEC)
 └─> CV Stage(s): Detector/Segmenter/OCR (GPU)
 └─> Feature Join (embeddings/text, NVMe cache)
 └─> LLM Reasoner (prompt+context, stream partials)
 └─> Guardrails/Policies
 └─> Response (JSON/SSE)

Особенности: для OCR/детектора используйте микробатч ≤ 4, для LLM — стриминг частичных токенов. Фичи и вырезки храните на NVMe.

B) DIFF + LLM (Ideation → Generation → Review)

Brief/Prompt ─> LLM Prompt Crafter ─> Diffusion (SD/Control) ─> LLM Critic (score/tags)
 └─> If score < τ → Re-prompt (N iters)
 └─> If ok → Upscale/Refine → Deliver

Особенности: вынесите LLM‑критика на отдельный GPU/MIG, лимитируйте число итераций и общий бюджет времени.

C) ETL + ML (Features → Train/Score)

Object/NVMe ─> RAPIDS/Spark RAPIDS (read→join→agg→encode)
 └─> Feature Store (Parquet/partitions)
 ├─> Train (cuML/torch) → Checkpoints
 └─> Triton Serving (GPU) → Online scoring/embeddings

Особенности: тяжёлые шифлы и обучение — в Interruptible, онлайн‑скоринг — в On‑Demand. См. https://cloudcompute.ru/solutions/rapids/, https://cloudcompute.ru/solutions/spark-rapids/, https://cloudcompute.ru/solutions/triton-inference-server/

Профили GPU и ориентиры

Инженерные диапазоны для онлайн пайплайнов при U≈0.7. Реальные цифры зависят от моделей/разрешений/промптов и I/O.

**Профиль GPU** **Память** **CV+LLM (запросы/с)\*** **DIFF+LLM (изобр/мин)\*\*** **ETL+ML (онлайн RPS)\*\*\*** **Комментарии**
24 ГБ (Compact) 24 ГБ 10–30 2–6 100–300 Лёгкие детекторы/OCR/эмбеддинги; LLM — малый/квантованный.
48 ГБ (Balanced) 48 ГБ 30–70 6–12 300–700 Баланс качества/латентности; LLM средний; DIFF с малым шагом.
80 ГБ (HQ) 80 ГБ 70–150 12–25 700–1500 Тяжёлые промпты/больше токенов; DIFF с Control/апскейлом.

* CV детект + OCR + LLM‑ответ p95 ≤ 1–2 с. ** Один проход генерации (≤ 30–60 шагов) + оценка «критиком». *** Ранкер/скора, без тяжёлых фичей. Для батч‑ETL см. страницы RAPIDS/Spark RAPIDS.

Конфиги и скелеты

Docker Compose: оркестратор + три воркера (CV / LLM / DIFF)

version: "3.9"
x-env: &env
 CACHE_DIR: /var/cache/hybrid
 PRECISION: "fp16"
 MAX_MICROBATCH: "4"
 HWM: "128" # High-watermark очереди
 LWM: "64"
services:
 orchestrator:
 image: cloudcompute/hybrid-orchestrator:latest
 environment: *env
 ports: ["8088:8088"] # HTTP/SSE API
 volumes:
 - /nvme/hybrid:/var/cache/hybrid
 depends_on: [cv-worker, llm-worker, diff-worker]
 command: ["python","serve.py","--host=0.0.0.0","--port=8088"]
 cv-worker:
 image: cloudcompute/cv-serving:latest
 environment: { PRECISION: "fp16", MAX_MICROBATCH: "4" }
 deploy: { resources: { reservations: { devices: [{ capabilities: ["gpu"] }] } } }
 volumes: ["/nvme/models:/models", "/nvme/hybrid:/var/cache/hybrid"]
 llm-worker:
 image: cloudcompute/llm-serving:latest
 environment: { PRECISION: "fp16", MAX_TOKENS: "256", STREAM: "true" }
 deploy: { resources: { reservations: { devices: [{ capabilities: ["gpu"] }] } } }
 volumes: ["/nvme/models:/models", "/nvme/hybrid:/var/cache/hybrid"]
 diff-worker:
 image: cloudcompute/diffusion-serving:latest
 environment: { STEPS: "30", UPSCALE: "true", PRECISION: "fp16" }
 deploy: { resources: { reservations: { devices: [{ capabilities: ["gpu"] }] } } }
 volumes: ["/nvme/models:/models", "/nvme/hybrid:/var/cache/hybrid"]

K8s: разные пулы под стадии (онлайн SLA)

apiVersion: apps/v1
kind: Deployment
metadata: { name: llm-worker }
spec:
 replicas: 3
 selector: { matchLabels: { app: llm-worker } }
 template:
 metadata: { labels: { app: llm-worker } }
 spec:
 containers:
 - name: llm
 image: cloudcompute/llm-serving:latest
 ports: [{ containerPort: 9090 }]
 env:
 - { name: PRECISION, value: "fp16" }
 - { name: MAX_TOKENS, value: "256" }
 resources:
 limits: { nvidia.com/gpu: 1, cpu: "4", memory: "32Gi" }
 nodeSelector: { pool: on-demand }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: diff-worker }
spec:
 replicas: 2
 selector: { matchLabels: { app: diff-worker } }
 template:
 metadata: { labels: { app: diff-worker } }
 spec:
 containers:
 - name: diff
 image: cloudcompute/diffusion-serving:latest
 resources:
 limits: { nvidia.com/gpu: 1, cpu: "4", memory: "32Gi" }
 nodeSelector: { pool: interruptible } # офлайн/полуонлайн

Конфиг пайплайна (YAML): граф, SLA, фоллбэки

dag:
 nodes:
 - id: preprocess ; type: cv_pre
 - id: detector ; type: cv_model ; model: "detector_x"
 - id: ocr ; type: cv_ocr ; model: "ocr_small"
 - id: llm_reason ; type: llm ; model: "llm_medium" ; stream: true
 - id: critic ; type: llm ; model: "llm_small"
 - id: diffusion ; type: diff ; steps: 30 ; upscale: true
 edges:
 - [preprocess, detector]
 - [detector, ocr]
 - [ocr, llm_reason]
 - [llm_reason, diffusion, { optional: true, when: "request.mode == 'generate'" }]
 - [diffusion, critic]
sla:
 e2e_ms: 1500
 stage:
 detector_ms: 150
 ocr_ms: 120
 llm_reason_ms: 800
 diffusion_ms: 600
queue:
 hwm: 128
 lwm: 64
 drop_policy: "oldest" # для интерактива
fallbacks:
 - when: "llm_reason_timeout" ; action: "short_answer"
 - when: "diffusion_timeout" ; action: "skip_upscale"

FastAPI (скелет): оркестратор с очередями и таймаутами

from fastapi import FastAPI, Body
from sse_starlette.sse import EventSourceResponse
import asyncio, time, json, uuid
app = FastAPI()
Q = { "cv": asyncio.Queue(maxsize=128),
 "llm": asyncio.Queue(maxsize=128),
 "diff": asyncio.Queue(maxsize=64) }
async def call_worker(kind, payload, timeout_ms):
 q = Q[kind]; req_id = str(uuid.uuid4())
 fut = asyncio.get_running_loop().create_future()
 await q.put((req_id, payload, fut))
 try:
 return await asyncio.wait_for(fut, timeout=timeout_ms/1000)
 except asyncio.TimeoutError:
 return {"timeout": True}
@app.post("/cv-llm")
async def cv_llm(payload: dict = Body(...)):
 t0 = time.time()
 r1 = await call_worker("cv", {"op":"detector+ocr", "img":payload["img"]}, 300)
 if r1.get("timeout"): return {"ok": False, "error":"cv_timeout"}
 r2 = await call_worker("llm", {"op":"reason", "text":r1["text"]}, 900)
 if r2.get("timeout"): r2 = {"text":"(краткий ответ без контекста)"}
 return {"ok": True, "t_ms": int((time.time()-t0)*1000), "answer": r2["text"]}

Привязку к реальным моделям/бэкендам (Triton/vLLM/TGI/ComfyUI) делайте через адаптеры; для UI/демо — см. https://cloudcompute.ru/solutions/gradio-fastapi/ ## Наблюдаемость, метрики, алерты

E2E и стадии:

  • hyb_e2e_seconds (p50/p95), hyb_stage_latency_seconds{stage=cv|ocr|llm|diff}, hyb_tokens_per_s, hyb_images_per_min.
  • hyb_queue_depth{stage=...}, hyb_drop_total, hyb_timeout_total.

GPU/IO:

  • gpu_utilization{stage=...}, gpu_mem_peak_bytes, gpu_copy_util, nvme_{read,write}_mb_s, model_cache_hit.

Качество:

  • CV: map@mAP, OCR: cer/wer, DIFF: critic_score, LLM: halluc_rate (проксими), финальные accept_rate.

Алерты (примеры):

  • hyb_e2e_p95 > SLA — сократить токены/шаги DIFF, включить деградацию, расширить GPU/профиль.
  • gpu_copy_util≈100% при низком SM — упор в копировщики/PCIe → пиннинг, фьюзинг препроцесса, уменьшить параллельность.
  • hyb_queue_depth↑ и drop_total↑ — узкое место стадии; добавить воркеры/увеличить профиль/перестроить DAG.
  • gpu_mem_peak/HBM > 0.9 — уменьшить batch/размеры картинок/токенов, FP16/BF16, выгрузка неисп. тензоров.

Детальнее: https://cloudcompute.ru/solutions/monitoring-logging/https://cloudcompute.ru/solutions/llm-inference/observability/

Экономика и формулы

Пусть для этапа k: цена c_k (за GPU‑час), целевая загрузка U_k, среднее время обработки t_k.

  • **Стоимость запроса: Cost_request ≈ Σ_k ( c_k × t_k / U_k ).
  • **Throughput (ограничение узким местом): TPS ≈ min_k ( 1 / t_k_effective ), где t_k_effective учитывает очередь и микробатчинг.
  • **Стадия DIFF с N итерациями: t_diff ≈ N × t_step + t_upscale, ограничивайте N и шаги апскейла по SLA.
  • **Кэш‑экономия: Вероятность хита p_hit даёт: Δt ≈ p_hit × (t_load - t_cache) и ΔCost ≈ Σ (c_k × Δt / U_k).
  • **On‑Demand vs Interruptible: Для смешанных пайплайнов: CV/LLM — On‑Demand, DIFF/обучение/ETL — Interruptible. Итоговая стоимость = сумма по пулам. См. https://cloudcompute.ru/solutions/cost-planner/ и https://cloudcompute.ru/solutions/interruptible-patterns/

Безопасность и политики

  • PII/контент: маскирование идентификаторов, фильтры изображений/текста, безопасное логирование (без сырья). См. https://cloudcompute.ru/solutions/security/
  • Guardrails LLM: валидация промптов/ответов, whitelists/blacklists, лимиты на токены и цепочки.
  • Секреты и ключи: только Secret‑хранилища/ENV, ротация.
  • Ретеншн: TTL на временные артефакты/рендеры/эмбеддинги; манифесты версий моделей/промптов.
  • Изоляция: раздельные пулы (On‑Demand/Interruptible), MIG‑профили для мелких сервисов. См. https://cloudcompute.ru/solutions/mig/

Траблшутинг

**Симптом** **Возможная причина** **Решение**
E2E p95 вышел за SLA Узкое место (LLM/DIFF) или очереди Урезать токены/шаги, включить деградации, добавить воркеры/профили, повысить U осторожно
Пики VRAM/CUDA OOM Размеры изображений/батчи/активации FP16/BF16, лимит разрешений, микробатч ≤ 4, выгрузка лишних тензоров
Падение качества OCR/детекта Слишком агрессивный resize/сжатие Балансировать препроцесс, повысить качество, адаптивные пороги
«Галлюцинации» LLM Недостаточный контекст/guardrails Добавить RAG/кастомные промпты, валидацию выходов, пост‑правила
Диффузия «залипает» Вытянутые промпты/слишком много итераций Ограничить N, LLM‑редактор промптов, ранний останов по «critic\_score»
Очереди растут волнообразно Несогласованный микробатчинг стадий Синхронизировать MAX\_MICROBATCH, задать HWM/LWM, включить backpressure
GPU простаивает Узкое место в I/O/CPU Пиннинг/zero‑copy, NVMe‑кэш, фьюзинг препроцесса, выделенные CPU лимиты
Нестабильный прод Канарейки/версии конфликтуют Версионирование моделей/промптов, canary/rollback, контракт схем

Как запустить в cloudcompute.ru

  1. Откройте Шаблоны запусков: https://cloudcompute.ru/solutions/templates/ — выберите Hybrid Orchestrator и профильные темплейты (CV Serving / LLM Serving / Diffusion Serving / RAPIDS).
  2. Разведите пулы: On‑Demand (CV/LLM/онлайн‑ранкинг) и Interruptible (DIFF/обучение/ETL).
  3. Смонтируйте NVMe: /nvme/models, /nvme/hybrid (кэш/артефакты).
  4. Заполните dag.yaml (стадии, таймауты, деградации) и переменные (микробатч, HWM/LWM).
  5. Поднимиe наблюдаемость: дешборды E2E/стадий, алерты p95/queue/HBM, трассировка запросов.
  6. Канареечный деплой и нагрузочный прогон ≥ 30 мин под целевым трафиком.

Чек‑лист перед продом

  • Заданы SLA: E2E и по стадиям; реализованы деградации/фоллбэки.
  • Настроены очереди HWM/LWM, микробатчинг и backpressure.
  • Прогреты модели/артефакты на NVMe; кэш‑хитрейт измерен.
  • Дашборды и алерты: hyb_e2e_p95, stage_*_latency, queue_depth, HBM, copy_util.
  • Политики PII/guardrails/ретеншн включены; секреты — через Secret‑хранилище.
  • Пулы On‑Demand/Interruptible и/или MIG‑раскладка согласованы.
  • Резервные сценарии (rollbacks/канарейки) протестированы.

Навигация

Готовы запустить?

Запустить GPU-сервер