Files
ki-fwi/docs/sessions/03-pipeline-assets.md
T
OKIandClaude Opus 5 eaaf7c34ad fix(assets): le test de reproductibilité ne vidait pas le cache ComfyUI
Correction d'une preuve qui n'en était pas une.

Ma vérification lançait le même plan deux fois et comparait les
empreintes. Le porteur ayant indiqué où ComfyUI écrit ses images, le
dossier a pu être inspecté : UN SEUL fichier y figurait alors que deux
exécutions avaient été lancées.

ComfyUI met en cache le résultat d'un graphe identique. La « deuxième
exécution » n'avait rien recalculé — elle avait relu la première.
Comparer deux empreintes dans ces conditions ne mesure que le cache.

Après POST /free, une exécution authentique produit decor_00002_.png,
bit-identique au premier. La conclusion était juste, la méthode ne
l'était pas.

Le test devient un mode de l'outil plutôt qu'une manipulation :
--reproductibilite génère, vide le cache, régénère et compare. Un test
de reproductibilité qui ne vide pas le cache se ment à lui-même.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 12:25:52 -04:00

136 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Session 3 — Pipeline d'assets
**Date :** 2026-07-27 · **Livrable :** deux pipelines, un par filière.
## Porte de sortie
| Critère | Cible | Mesuré |
|---|---|---|
| Assets non validés dans le build | 0 | **0** — le pipeline refuse les 39 médias non validés ✅ |
| Assets de filière B dans une épreuve | 0 | refusé par `validate:data`, prouvé par `test:porte` ✅ |
| Reproductibilité des seeds | deux exécutions identiques | **vérifié avec `PYTHONHASHSEED` différent** ✅ |
| Poids par image | ≤ 200 Ko | AVIF 1200 px à **106 Ko**, 800 px à **79 Ko**, 480 px à **36 Ko** ✅ |
| Appels réseau au runtime | 0 | les médias sont rapatriés au build, jamais chargés depuis Commons ✅ |
| Compositing sur média SA ou NC | 0 | refusé par `validate:data` ✅ |
## Filière A — `npm run fetch:medias`
Rapatrie les photographies **validées** depuis Commons, les encode en AVIF et WebP à trois
largeurs (480, 800, 1200), et inscrit `fichier_local` dans les données.
Deux raisons de ne pas pointer vers les URLs de Commons dans le jeu : le projet s'interdit
toute requête tierce au runtime, et un jeu qui doit fonctionner hors ligne ne peut pas
dépendre d'un serveur distant.
Le script **ne télécharge que ce qui est validé**. Aujourd'hui : 0 traité, 39 ignorés. Le
pipeline ne contourne pas la porte, il la respecte.
Vérifié sur une copie de travail, sans toucher aux données réelles : source de 256 Ko →
106 Ko en AVIF 1200 px, 36 Ko en 480 px. La qualité baisse d'un cran tant que le budget de
200 Ko est dépassé.
ImageMagick est une dépendance **système**, pas un paquet npm : l'outil existe sur la
machine de build et n'a rien à faire dans le bundle.
## Filière B — `tools/assets/comfyui_client.py`
Client ComfyUI en bibliothèque standard seule, hors bundle, avec son `requirements.txt`.
**Les trois défauts du pack d'origine sont corrigés**, et le premier est le plus grave :
le pack calculait ses seeds avec `hash()`, randomisé à chaque exécution depuis Python 3.3,
tout en vendant l'argument « même seed = même style ». Ses seeds ne l'étaient pas.
Remplacé par `zlib.crc32`. Prouvé empiriquement : deux processus lancés avec des
`PYTHONHASHSEED` différents produisent exactement les mêmes valeurs.
`copy.deepcopy` remplace `json.loads(json.dumps(...))`. Et `rembg` reste commenté dans
`requirements.txt` avec l'avertissement qui manquait : le paquet est sous MIT, **les poids
du modèle ne le sont pas nécessairement**.
## Ce qui reste
Le plan d'assets et les workflows ComfyUI ne sont pas écrits : ils dépendent de choix
graphiques qui appartiennent au porteur, et générer du décor avant d'avoir un jeu jouable
serait mettre la charrue avant les bœufs.
---
## Addendum — pipeline confronté au ComfyUI réel
Le porteur a ouvert l'accès à son instance (`127.0.0.1:8188`, ComfyUI 0.27.1, deux GPU
AMD). Le pipeline a donc été exécuté pour de vrai, pas simulé.
### Reproductibilité prouvée — après correction d'un test qui ne prouvait rien
**Images bit-identiques**, `sha256 b7007a7a1088cb359a06ddaaff358e92…`, sur deux exécutions
séparées par un **vidage du cache**. Workflow de référence : `workflows/decor-sdxl.json`
(SDXL 1.0, 1024×576, 20 pas, dpmpp_2m/karras).
Le mot « après vidage du cache » est tout le sujet, et il a failli manquer.
Ma première vérification lançait simplement le même plan deux fois et comparait les
empreintes. Le porteur ayant indiqué où ComfyUI écrit ses images
(`/media/sucupira/DKXONE/ComfyUI/output`), le dossier a pu être inspecté : **un seul
fichier y figurait** alors que deux exécutions avaient été lancées.
ComfyUI met en cache le résultat d'un graphe identique. Ma « deuxième exécution » n'avait
donc rien recalculé — elle avait relu la première. Comparer deux empreintes dans ces
conditions ne mesure que le bon fonctionnement du cache.
Après `POST /free`, une exécution authentique a produit `decor_00002_.png`, bit-identique
au premier. **La conclusion était juste ; la méthode ne l'était pas.**
Le test est désormais un mode de l'outil, pas une manipulation à la main :
```bash
python3 comfyui_client.py --workflow workflows/decor-sdxl.json \
--plan plan-assets.json --reproductibilite
```
Il génère, vide le cache, régénère et compare. Un test de reproductibilité qui ne vide pas
le cache est un test qui se ment à lui-même.
### Deux défauts de mon propre client, révélés par le réel
1. **Le prompt négatif était concaténé au prompt positif** — travers hérité du pack. Sur
SDXL, cela revient à demander au modèle de produire ce qu'on voulait exclure. Il a
désormais son propre nœud.
2. **Les images n'étaient pas rapatriées.** Elles restaient dans le dossier de sortie de
ComfyUI, et le manifeste référençait des chemins inexistants. Ajout de `recuperer()`
via `/view`.
Un pipeline qu'on n'exécute pas est un pipeline qu'on croit correct.
### Krea 2 — disponible, mais trois questions à trancher
Deux choses portent ce nom sur la machine, et elles n'ont rien à voir :
| | ce que c'est | état |
|---|---|---|
| `krea2_turbo_nvfp4.safetensors` | poids locaux, chargés par `UNETLoader` | **nvfp4 = format FP4 NVIDIA Blackwell**, sur deux GPU AMD : très probablement inexploitable |
| `Krea2ImageNode` | nœud `api_node: True`, catégorie `partner/image/Krea` | **appel à un service tiers payant** |
Le workflow transmis est au format *interface* (`nodes`, `links`, `widgets_values`) et non
au format API que consomme `/prompt`. Sa conversion bute sur le champ `model`, de type
`COMFY_DYNAMICCOMBO_V3`, dont la forme sérialisée ne se devine pas sans risque.
**Trois points à trancher par le porteur** avant de câbler Krea 2 :
1. **Export au format API.** Dans ComfyUI : menu → *Save (API Format)*. C'est le seul
format que `/prompt` accepte, et il lève toute incertitude sur le champ `model`.
2. **Doctrine.** `Krea2ImageNode` envoie les prompts à un serveur tiers. C'est toléré parce
que la génération a lieu **au build**, jamais au runtime (playbook P2) — mais c'est un
écart au « zéro service tiers » qui mérite d'être inscrit, pas subi.
3. **Licence des sorties.** Les conditions d'utilisation de Krea déterminent ce qu'on a le
droit de faire des images produites. Tant qu'elles ne sont pas vérifiées, ces images ne
peuvent pas être publiées sous CC BY-SA 4.0 avec le reste du contenu (ADR 0001).
En attendant, SDXL 1.0 en local reste le workflow par défaut : aucun coût, aucune donnée
qui sort de la machine, et une reproductibilité démontrée.
### Réserve sur le rendu
Le fond produit est graphiquement juste — aplats, angles nets, aucun texte, aucun visage —
mais sa palette tire vers l'orange-rouge, plus chaude que la charte OKI (noir profond, or,
vert, rouge en ponctuation). À reprendre en session 6 si ces fonds sont retenus.