Retour au Blog
tech/

Deal ex Machina : la stack technique

Carte visuelle de la stack : site statique en edge, inference Koyeb, secrets Infisical, et boucle sft-wagmi pour les tiers CPU et GPU de Wagmi.

Cette page est la carte courte de la stack, avec schémas. Pour le récit complet (frugalité, souveraineté, RGPD, loi IA, coûts), voir Le site web est la démo.

Pourquoi cette forme ? Un seul codebase TypeScript reste portable. Les pages publiques coûtent peu au bord. L'inférence est bi-niveau : petit modèle CPU pour tous, grand modèle GPU lorsque l'authentification justifie le coût. Les modèles sont entraînés dans sft-wagmi, bakés dans des images Docker, et configurés via Infisical pour que dev, staging et prod ne divergent pas sur les secrets.


Vue d'ensemble de la stack

flowchart TB
  visitor["Visiteur ou utilisateur connecte"]

  subgraph edge ["Edge et runtime"]
    cf["Cloudflare Pages statique et proxy API"]
    web["Koyeb web : Next.js et llama-server CPU"]
    gpu_svc["Koyeb GPU : wagmi-sft-14b scale-to-zero"]
  end

  subgraph app ["Application"]
    ui["React 19, Assistant UI, next-intl"]
    api["Routes API : chat, auth, health"]
  end

  subgraph data ["Donnees et configuration"]
    inf["Secrets Infisical"]
    pg[("PostgreSQL via Drizzle")]
    sb["Supabase OTP email"]
  end

  subgraph factory ["Usine a modeles sft-wagmi"]
    dexm_ds["Export JSONL dexm-one-page"]
    hf_space["HF Space pipeline.py"]
    hub["GGUF prives sur Hugging Face"]
    hub_dh["Images Docker Hub"]
  end

  visitor --> cf
  cf -->|proxy /api| web
  visitor --> web
  ui --> api
  api --> pg
  api --> sb
  inf -.-> web
  inf -.-> gpu_svc
  api -->|anonyme| web
  api -->|authentifie| gpu_svc
  dexm_ds --> hf_space
  hf_space --> hub
  hub --> hub_dh
  hub_dh --> web
  hub_dh --> gpu_svc
MériteCe que cela nous apporte
FrugalMarketing statique sur Cloudflare ; GPU facturé seulement quand le trafic auth le réveille
SouverainNotre code, nos poids, endpoints compatibles OpenAI interchangeables
AuditableBlog, datasets et workflows de déploiement dans des dépôts publics
PrudenceValidation Zod, rate limits, RAG BM25 sur le petit tier, portes release et AI Act

Routage Wagmi : sessions, CPU et GPU

Le chat choisit un tier d'inférence via la session Supabase, pas via un flag client opaque.

flowchart TD
  start["POST /api/chat"]
  session{"Session Supabase valide ?"}
  anon["Tier anonyme"]
  auth["Tier authentifie"]
  rag["RAG BM25 sur wagmi-skills et ai.txt"]
  cpu["CPU wagmi-sft 1.5B en loopback 127.0.0.1"]
  cpu_first["Reponse CPU-first pendant le wake GPU"]
  wake["GET LLM_GPU_WAKE_URL ou sonde mesh"]
  gpu_ready{"Modele GPU disponible ?"}
  gpu["GPU wagmi-sft-14b tier premium"]

  start --> session
  session -->|non| anon --> rag --> cpu
  session -->|oui| auth
  auth --> cpu_first --> cpu
  auth --> wake --> gpu_ready
  gpu_ready -->|oui| gpu
  gpu_ready -->|non| cpu

Anonyme : toujours CPU (wagmi-sft dans le conteneur web). Authentifié : CPU-first par défaut (CHAT_AUTH_CPU_FIRST), puis bascule GPU lorsque /v1/models signale le modèle auth prêt. L'interface affiche le tier actif.


Boucle d'entraînement : dexm-one-page vers la production

Les poids ne sont pas retouchés à la main. Le contenu et les garde-fous deviennent du JSONL dans dexm-one-page, puis sft-wagmi entraîne, évalue et exporte des GGUF pour les bakes Docker.

flowchart LR
  content["Blog, wagmi-skills, ai.txt, notes Obsidian"]
  gen["generate-wagmi-sft-dataset.ts"]
  jsonl["datasets/wagmi-sft train et eval JSONL"]
  sync["pnpm dataset:wagmi sync ou refresh"]
  space["sft-wagmi HF Space Gradio"]
  pipeline["pipeline.py preflight train eval redteam export"]
  recurring["Cursor SDK recurring quotidien et hebdo"]
  gguf["GGUF sur le Hub"]
  docker["Docker build bake web et GPU"]
  koyeb["Deploiement Koyeb"]

  content --> gen --> jsonl --> sync --> space
  recurring -.->|orchestre| space
  space --> pipeline --> gguf --> docker --> koyeb

sft-wagmi (README) exécute Unsloth et TRL sur deux profils : small (1,5B, tier anonyme) et auth (14B, tier outils). Les étapes incluent eval_sft, eval_sft_rag, redteam et export-merged avant conversion GGUF. L'automation récurrente (automation/cursor-sdk, scripts/hf/recurring_runner.py) planifie des runs légers quotidiens qwen/small et des runs hebdomadaires plus lourds qwen/auth sur l'infrastructure Hugging Face, avec des portes pass ou fail avant qu'un build soit candidat release.

Sur le dépôt site :

pnpm run dataset:wagmi:refresh   # regenere et synchronise le JSONL vers sft-wagmi/data/

Technologies cœur (index rapide)

CoucheChoix
AppNext.js 16, React 19, TypeScript strict, Tailwind, Radix
ChatVercel AI SDK, Assistant UI, ancrage BM25 local-rag.ts
SecretsInfisical UE (dev / staging / prod)
DonnéesPostgreSQL, Drizzle, auth OTP Supabase
ContenuContent Collections, Markdown dans content/blog/
ImagesDocker Hub (jeanbapt/deal-ex-machina-web, images GPU)
StagingKoyeb web et llama-gpu, scale-to-zero selon config
Front prodCloudflare Pages statique et Functions proxy vers Koyeb
QualitéBiome, Vitest, Playwright, Lighthouse CI, porte AI Act au deploy

Lectures associées