[Infra][MinIO] Migrate /mnt/fusionio/spikersoft/ai → ai-models bucket for embeddings + quiz-generation (epic #413) #527

Closed
opened 2026-07-13 00:40:41 +00:00 by spikerj · 3 comments
Owner

Parent epic: #413.

Scope: ai-models bucket — /mnt/fusionio/spikersoft/ai (backend rw; embeddings + quiz-generation ro).

Current state: embeddings and quiz-generation read model files straight off the ro bind; both are pinned to SERVER solely because of it (spikersoft-embeddings/docker-stack*.yml, spikersoft-quiz-generation/docker-stack*.yml).

Steps: bucket + scoped ro keys per service → backend PR: model loader fetches from ai-models into a container-local cache dir at startup (models are read-once-at-load; an ephemeral/named local cache is fine — the decoupling goal is placement, not zero local disk for caches) → backfill mc mirror /mnt/fusionio/spikersoft/ai spiker/ai-models → dual-run → remove ro binds, relax placement to the GPU label.

Important caveat (from docs/minio-storage-migration.md non-goals): migrating ai-models is necessary but NOT sufficient to run embeddings/quiz on the 4090 — the gpu-coordinator still needs per-node lease routing (#367 U2). Placement relaxation lands together with that work.

Parent epic: #413. **Scope:** `ai-models` bucket — `/mnt/fusionio/spikersoft/ai` (backend rw; embeddings + quiz-generation ro). **Current state:** embeddings and quiz-generation read model files straight off the ro bind; both are pinned to SERVER solely because of it (`spikersoft-embeddings/docker-stack*.yml`, `spikersoft-quiz-generation/docker-stack*.yml`). **Steps:** bucket + scoped ro keys per service → backend PR: model loader fetches from `ai-models` into a container-local cache dir at startup (models are read-once-at-load; an ephemeral/named local cache is fine — the decoupling goal is *placement*, not zero local disk for caches) → backfill `mc mirror /mnt/fusionio/spikersoft/ai spiker/ai-models` → dual-run → remove ro binds, relax placement to the GPU label. **Important caveat (from `docs/minio-storage-migration.md` non-goals):** migrating `ai-models` is necessary but NOT sufficient to run embeddings/quiz on the 4090 — the gpu-coordinator still needs per-node lease routing (#367 U2). Placement relaxation lands together with that work.
Author
Owner

Backend PR #261: ObjectFileCache in SpikerSoft.Storage (local-wins → atomic bucket download → null), embeddings resolves its gguf directly, quiz-generation via a ModelPathResolver delegate so Business.Ai.Workers stays storage-free. Placement relaxation deliberately NOT included — waits on #367 U2 per the migration-doc non-goal. Deploy: ai-models bucket + ro keys, mc mirror backfill, optionally a node-local named volume for the model cache.

Backend PR #261: ObjectFileCache in SpikerSoft.Storage (local-wins → atomic bucket download → null), embeddings resolves its gguf directly, quiz-generation via a ModelPathResolver delegate so Business.Ai.Workers stays storage-free. Placement relaxation deliberately NOT included — waits on #367 U2 per the migration-doc non-goal. Deploy: ai-models bucket + ro keys, mc mirror backfill, optionally a node-local named volume for the model cache.
Author
Owner

Code MERGED (backend #261 — ObjectFileCache + embeddings direct + quiz via ModelPathResolver delegate). Remaining = ops: ai-models bucket + per-service ro keys, mc mirror /mnt/fusionio/spikersoft/ai (multi-GB), Storage__UseS3 + secrets on both GPU stacks, optional node-local named volume for the model cache. Placement relaxation stays gated on #367 U2 per the ticket.

Code MERGED (backend #261 — ObjectFileCache + embeddings direct + quiz via ModelPathResolver delegate). Remaining = ops: ai-models bucket + per-service ro keys, mc mirror /mnt/fusionio/spikersoft/ai (multi-GB), Storage__UseS3 + secrets on both GPU stacks, optional node-local named volume for the model cache. Placement relaxation stays gated on #367 U2 per the ticket.
Author
Owner

Complete and verified live (2026-07-17):

  • Code: backend #261 (ObjectFileCache + embeddings direct + quiz ModelPathResolver) — merged earlier.
  • Infra: #120 (embeddings sources the model from the ai-models bucket, /app/ai bind dropped, named cache volume) — merged and deployed; quiz-generation stack likewise runs Storage__UseS3=true.
  • Live state checked on the swarm: both services Running; embeddings has NO fusionio bind (only the named model-cache volume) and resolves its model path; quiz-generation has a working Bao-sourced storage key and generated a quiz at 2026-07-16T15:03Z (17 in book-generated-quizzes), proving the bucket holds the weights and the on-demand fetch works.

Placement relaxation (un-pinning from SERVER/GPU node) stays gated on #367 U2 per the ticket scope. Closing; #592 (quiz-generation empty secret) closed with the same evidence.

Complete and verified live (2026-07-17): - Code: backend #261 (ObjectFileCache + embeddings direct + quiz ModelPathResolver) — merged earlier. - Infra: #120 (embeddings sources the model from the `ai-models` bucket, `/app/ai` bind dropped, named cache volume) — merged and deployed; quiz-generation stack likewise runs `Storage__UseS3=true`. - Live state checked on the swarm: both services Running; embeddings has NO fusionio bind (only the named model-cache volume) and resolves its model path; quiz-generation has a working Bao-sourced storage key and **generated a quiz at 2026-07-16T15:03Z** (17 in `book-generated-quizzes`), proving the bucket holds the weights and the on-demand fetch works. Placement relaxation (un-pinning from SERVER/GPU node) stays gated on #367 U2 per the ticket scope. Closing; #592 (quiz-generation empty secret) closed with the same evidence.
Sign in to join this conversation.