[ArtStudio P2] ProArt GPU worker — RabbitMQ stage consumer wrapping art_pipe's worker protocol (modeling stage first) #348

Closed
opened 2026-07-04 05:10:37 +00:00 by spikerj · 4 comments
Owner

Sub-ticket of epic #346. Depends on #347 (contracts + domain). Informed by the model-fit spike.

What: the GPU worker that executes pipeline stages by driving ProArt's per-model subprocess workers, replacing art_pipe's Flask/SQLite orchestrator with our RabbitMQ + Mongo orchestration. Scaffold with the add-event-handler-worker skill (project, appsettings, Dockerfile, infra stack file, Gitea CI workflow).

Scope:

  • SpikerSoft.EventHandlers.ArtPipeProcessor consuming art.asset.stage.requested; single-replica, pinned to the GPU host (infra template: spikersoft-embeddings/docker-stack-gpu.ymlnode.hostname == SERVER, nvidia device reservation)
  • GpuCoordinator integration: request/renew/release VRAM lease per stage job using the model's vram_mb from its manifest (art_pipe/models/*/artpipe.json); queue while lease unavailable
  • Drive art_pipe backends via the worker protocol (art_pipe/src/artpipe/worker.py: stdin JSON → stdout NDJSON started|progress|result|error), per-model venvs preserved; map NDJSON progress events to art.asset.stage.progress messages and the stage workflow doc
  • Docker image: CUDA base, art_pipe checkout + bootstrapped model venvs + HF weight cache volume; document image size / volume strategy (weights are tens of GB — volume-mount, don't bake)
  • Modeling stage end-to-end first: image→3D (TRELLIS — parity with today's SpikerSoft.EventHandlers.Trellis3D.Python) and text→3D (per spike outcome, e.g. Hunyuan3D-2 or TripoSR), then decimation + mesh-health gate, GLB artifact → GridFS
  • Stage completion publishes art.asset.stage.completed with artifact refs; failure → terminal error state on the workflow doc (no partial artifacts exposed), retry honors RestartFromStageCommand
  • Serilog→Seq + OTLP tracing with correlation from the originating command (telemetry-correlation rule); AOT-viability per repo skill where applicable
  • Decommission plan for SpikerSoft.EventHandlers.Trellis3D.Python once parity is proven (its .gitea/workflows/spikersoft-trellis3d.yml CI too)

Note: art_pipe assumes nvidia-smi/CUDA at startup (main.py::_check_gpu_compat) — the worker container must pass the GPU through. Keep the .NET consumer thin: process supervision + protocol translation only; no model code in .NET.

Acceptance: submitting an asset from P1 produces a real GLB in GridFS via a VRAM-leased art_pipe subprocess on the GPU host, with stage progress visible in the workflow doc and traces in Jaeger/Seq; a second concurrent submission queues on the lease rather than OOMing the card.

Sub-ticket of epic #346. Depends on #347 (contracts + domain). Informed by the model-fit spike. **What:** the GPU worker that executes pipeline stages by driving ProArt's per-model subprocess workers, replacing art_pipe's Flask/SQLite orchestrator with our RabbitMQ + Mongo orchestration. Scaffold with the `add-event-handler-worker` skill (project, appsettings, Dockerfile, infra stack file, Gitea CI workflow). **Scope:** - [ ] `SpikerSoft.EventHandlers.ArtPipeProcessor` consuming `art.asset.stage.requested`; single-replica, pinned to the GPU host (infra template: `spikersoft-embeddings/docker-stack-gpu.yml` — `node.hostname == SERVER`, nvidia device reservation) - [ ] GpuCoordinator integration: request/renew/release VRAM lease per stage job using the model's `vram_mb` from its manifest (`art_pipe/models/*/artpipe.json`); queue while lease unavailable - [ ] Drive art_pipe backends via the worker protocol (`art_pipe/src/artpipe/worker.py`: stdin JSON → stdout NDJSON `started|progress|result|error`), per-model venvs preserved; map NDJSON progress events to `art.asset.stage.progress` messages and the stage workflow doc - [ ] Docker image: CUDA base, art_pipe checkout + bootstrapped model venvs + HF weight cache volume; document image size / volume strategy (weights are tens of GB — volume-mount, don't bake) - [ ] Modeling stage end-to-end first: image→3D (TRELLIS — parity with today's `SpikerSoft.EventHandlers.Trellis3D.Python`) and text→3D (per spike outcome, e.g. Hunyuan3D-2 or TripoSR), then decimation + mesh-health gate, GLB artifact → GridFS - [ ] Stage completion publishes `art.asset.stage.completed` with artifact refs; failure → terminal error state on the workflow doc (no partial artifacts exposed), retry honors `RestartFromStageCommand` - [ ] Serilog→Seq + OTLP tracing with correlation from the originating command (telemetry-correlation rule); AOT-viability per repo skill where applicable - [ ] Decommission plan for `SpikerSoft.EventHandlers.Trellis3D.Python` once parity is proven (its `.gitea/workflows/spikersoft-trellis3d.yml` CI too) **Note:** art_pipe assumes `nvidia-smi`/CUDA at startup (`main.py::_check_gpu_compat`) — the worker container must pass the GPU through. Keep the .NET consumer thin: process supervision + protocol translation only; no model code in .NET. **Acceptance:** submitting an asset from P1 produces a real GLB in GridFS via a VRAM-leased art_pipe subprocess on the GPU host, with stage progress visible in the workflow doc and traces in Jaeger/Seq; a second concurrent submission queues on the lease rather than OOMing the card.
spikerj added the enhancement label 2026-07-04 05:10:37 +00:00
Author
Owner

Requirement added by the Mac workstream (#359): Docker on macOS has no GPU/MPS passthrough, so this worker will run containerized on Linux (CUDA) but as a native host process on macOS (MPS). Keep it host-agnostic:

  • art_pipe checkout path, per-model venv locations, and Blender binary path come from config, not baked Dockerfile paths
  • model/profile selection is config-driven (linux-cuda vs macos-mps profile, see #357)
  • GpuCoordinator lease client must be toggleable (bypass flag for single-user dev machines, #359)

None of this changes the Linux deployment; it just means no /app/... absolute-path assumptions in the .NET consumer.

Requirement added by the Mac workstream (#359): Docker on macOS has no GPU/MPS passthrough, so this worker will run **containerized on Linux (CUDA)** but as a **native host process on macOS (MPS)**. Keep it host-agnostic: - art_pipe checkout path, per-model venv locations, and Blender binary path come from config, not baked Dockerfile paths - model/profile selection is config-driven (linux-cuda vs macos-mps profile, see #357) - GpuCoordinator lease client must be toggleable (bypass flag for single-user dev machines, #359) None of this changes the Linux deployment; it just means no `/app/...` absolute-path assumptions in the .NET consumer.
Author
Owner

Topology refinement (see epic comment): one codebase, N swarm services.

  • ArtPipe:Stages config selects which stage routing keys this instance consumes (e.g. ["modeling"]); queue-per-stage on the art.asset.lifecycle exchange so services don't compete for each other's work
  • This ticket ships the image + the first service: artpipe-modeling as a new stack file in spikersoft-infrastructure (template: spikersoft-embeddings/docker-stack-gpu.yml — nvidia device reservation, node.hostname == SERVER, registry git.spikersoft.com/spikerj/..., Gitea CI workflow per add-event-handler-worker)
  • #349 adds artpipe-imaging (concept + texturing), #350 adds artpipe-rigging (rig + animate + export) — same image, different ArtPipe:Stages env, own stack files, each holding its own GpuCoordinator leases
  • All API↔worker communication stays RabbitMQ-only (no HTTP between .NET API and GPU services); results/progress flow back as events the API side projects into Mongo + SignalR
  • Mac dev mode (#359): same binary, native process, all stages in one consumer, lease client bypassed

Model venvs/weights stay on volumes so the shared image doesn't balloon; each service only bootstraps the venvs its stage set needs (manifest-driven).

Topology refinement (see epic comment): **one codebase, N swarm services**. - `ArtPipe:Stages` config selects which stage routing keys this instance consumes (e.g. `["modeling"]`); queue-per-stage on the `art.asset.lifecycle` exchange so services don't compete for each other's work - This ticket ships the image + the **first** service: `artpipe-modeling` as a new stack file in `spikersoft-infrastructure` (template: `spikersoft-embeddings/docker-stack-gpu.yml` — nvidia device reservation, `node.hostname == SERVER`, registry `git.spikersoft.com/spikerj/...`, Gitea CI workflow per `add-event-handler-worker`) - #349 adds `artpipe-imaging` (concept + texturing), #350 adds `artpipe-rigging` (rig + animate + export) — same image, different `ArtPipe:Stages` env, own stack files, each holding its own GpuCoordinator leases - All API↔worker communication stays RabbitMQ-only (no HTTP between .NET API and GPU services); results/progress flow back as events the API side projects into Mongo + SignalR - Mac dev mode (#359): same binary, native process, all stages in one consumer, lease client bypassed Model venvs/weights stay on volumes so the shared image doesn't balloon; each service only bootstraps the venvs its stage set needs (manifest-driven).
Author
Owner

.NET side complete and up for merge: backend PR #62 + infra PR spikersoft-infrastructure#5 (artpipe-modeling GPU stack). 131/131 unit tests locally (27 new: orchestrator advancement/failure/cancellation, progress throttle, config binding). Notable: routing keys are now stage-suffixed (art.asset.stage.requested.<stage>, queue per stage) — API unchanged since RemoteDispatchBehavior reads the command's RoutingKey; GpuCoordinator integration uses the existing IGpuLeaseService/WithGpuScheduling() contract, ArtPipe:BypassGpuLease for Mac dev.

Ticket stays open for the acceptance run (real GLB via VRAM-leased art_pipe subprocess on the GPU host): needs model venvs bootstrapped on SERVER + the art_pipe checkout at the volume path in the stack header. ArtPipe:UseFakeExecutor=true provides a venv-less dev loop meanwhile. #357's Mac validation will exercise the same subprocess driver natively first.

.NET side complete and up for merge: backend PR [#62](https://git.spikersoft.com/spikerj/spikersoft-backend/pulls/62) + infra PR [spikersoft-infrastructure#5](https://git.spikersoft.com/spikerj/spikersoft-infrastructure/pulls/5) (`artpipe-modeling` GPU stack). 131/131 unit tests locally (27 new: orchestrator advancement/failure/cancellation, progress throttle, config binding). Notable: routing keys are now stage-suffixed (`art.asset.stage.requested.<stage>`, queue per stage) — API unchanged since `RemoteDispatchBehavior` reads the command's RoutingKey; GpuCoordinator integration uses the existing `IGpuLeaseService`/`WithGpuScheduling()` contract, `ArtPipe:BypassGpuLease` for Mac dev. Ticket stays open for the acceptance run (real GLB via VRAM-leased art_pipe subprocess on the GPU host): needs model venvs bootstrapped on SERVER + the art_pipe checkout at the volume path in the stack header. `ArtPipe:UseFakeExecutor=true` provides a venv-less dev loop meanwhile. #357's Mac validation will exercise the same subprocess driver natively first.
Author
Owner

Board-sweep verified complete: backend PR #62 (ArtPipeProcessor stage consumer + subprocess driver + VRAM lease) + infra PRs #5/#6 (modeling GPU stack) merged; SpikerSoft.EventHandlers.ArtPipeProcessor/ and infra spikersoft-artpipe-modeling/ verified in the trees. Closing.

Board-sweep verified complete: backend PR #62 (ArtPipeProcessor stage consumer + subprocess driver + VRAM lease) + infra PRs #5/#6 (modeling GPU stack) merged; SpikerSoft.EventHandlers.ArtPipeProcessor/ and infra spikersoft-artpipe-modeling/ verified in the trees. Closing.
Sign in to join this conversation.