← Retour au portfolio English

Technocompost

Vue d'ensemble de l'architecture — projet : cbicari/technocompost

Objectif

Technocompost est une installation de traitement d'image multi-agents auto-entretenue, fonctionnant sur une grappe de cartes Raspberry Pi 4. Chaque Pi exécute un agent IA OpenClaw connecté à un serveur d'inférence local partagé, LM Studio. Les agents font passer une image à travers un cycle continu de décomposition et de repousse, chaque Pi prenant en charge une étape et décidant lui-même quel script de transformation appliquer, en s'appuyant sur ses propres capteurs système (température CPU, charge, mémoire, disque, réseau).

Le dépôt contient deux modes d'orchestration différents, construits sur la même infrastructure partagée :

Les deux modes partagent la même installation physique, le même dossier synchronisé par Syncthing, et le même sous-système d'affichage en direct (display_server.py / preview.py).

Infrastructure partagée

ComposantRôle
3× Raspberry Pi 4 (rpiagent01/02/03)Un par étape du pipeline
Serveur LM StudioMoteur d'inférence central (p. ex. google/gemma-4-e4b, nvidia/nemotron-3-nano-4b), accessible à une adresse LAN fixe, utilisé par l'agent OpenClaw de chaque Pi
OpenClawEnvironnement d'exécution de l'agent IA installé sur chaque Pi ; peut aussi communiquer de pair à pair via son propre protocole ACP en mode lan
SyncthingMaintient ~/.openclaw/workspace/tmp/ (et son sous-dossier canvas/) identique sur tous les Pi
display_server.pyVisionneuse pygame plein écran (sur un Pi désigné pour l'affichage) qui reçoit des images via TCP et fait un fondu enchaîné entre elles
preview.pyPetit client utilisé par les scripts de traitement pour transmettre une image à display_server.py via flush()

install.sh configure un Pi neuf : paquets système (git, curl, build-essential, feh, python3-pillow, inotify-tools, btop), Syncthing, Node.js 22 LTS + npm, et OpenClaw, puis crée un lien symbolique du dossier scripts/ vers ~/.openclaw/workspace/scripts. L'assistant de configuration openclaw (URL de base LM Studio + choix du modèle) et l'unité systemd optionnelle openclaw.service sont ensuite configurés manuellement, comme décrit dans le README.

Infrastructure partagée de Technocompost Une grappe de trois Raspberry Pi partage un dossier synchronisé par Syncthing, tous servis par un serveur d'inférence LM Studio central, un Pi pilotant un affichage pygame plein écran. Serveur LM Studio Moteur d'inférence partagé Grappe de Raspberry Pi Dossier partagé synchronisé par Syncthing rpiagent01 Agent OpenClaw Étape 1 rpiagent02 Agent OpenClaw Étape 2 rpiagent03 Agent OpenClaw Étape 3 Pi d'affichage Fenêtre pygame plein écran
Infrastructure partagée par les deux modes d'orchestration

Mode A — pipeline agentique distribué

Déroulement

hummus.png → [rpiagent01] → gas.png → [rpiagent02] → liquid.png → [rpiagent03] → hummus.png → ...
Technocompost mode A : pipeline agentique distribué Le script watcher de chaque Pi détecte le fichier d'entrée de son étape, decide.sh construit un prompt tenant compte des capteurs, l'agent OpenClaw local choisit un script et ses paramètres, le script s'exécute et écrit un fichier de sortie, et Syncthing transporte ce fichier vers le Pi suivant, bouclant ainsi le cycle. watcher.sh Surveille le fichiermot-clé de l'étape decide.sh Construit un prompt basé sur les capteurs Agent OpenClaw Choisit un script et ses paramètres Exécution du script choisi Écrit le fichier de sortie de l'étape Synchronisation Syncthing Livre le fichier au Pi suivant ↻ le watcher.sh du Pi suivant récupère le fichier, relançant le cycle
Mode A — un cycle complet d'étape, répété par chaque Pi

Étapes

  1. watcher.sh <étape> interroge le dossier partagé toutes les 3 secondes à la recherche du fichier mot-clé de cette étape (hummus/gas/liquid), en suivant les fichiers déjà vus dans /tmp/watcher_seen_stage<N>.txt. Au premier lancement, il démarre aussi display_server.py s'il n'est pas déjà actif.
  2. Lorsqu'un nouveau fichier apparaît, il appelle decide.sh <étape> <fichier_entrée>, qui :
  3. Le fichier de sortie (gas.png, liquid.png, ou hummus.png) est réécrit dans le dossier partagé, où Syncthing le propage à tous les Pi ; le watcher.sh de l'étape suivante le récupère, bouclant ainsi le cycle.

Étape → réservoirs de scripts

PiÉtapeSurveilleProduitRéservoir de scripts
rpiagent01 (« Fragmenteur »)1hummus.pnggas.pngchunk_shuffle, conway, diffuse, erode, spore, degrade
rpiagent02 (« Hydrolyseur »)2gas.pngliquid.pnghydrolyse, decompose, diffuse, erode
rpiagent03 (« Lignivore »)3liquid.pnghummus.pnglignine, spore, decompose

(Le README mentionne également mushroom, wind et growth dans la référence globale des scripts, utilisés de façon similaire par le pipeline.)

Mode B — canevas concurrent par tuiles

Ce mode remplace entièrement watcher.sh + decide.sh par tile_worker.py, lancé une fois par Pi/étape, et ne nécessite pas d'appel à un modèle de langage à chaque opération — le choix du script repose plutôt sur un tirage aléatoire pondéré local et un « niveau de stress » dérivé des capteurs.

Technocompost mode B : canevas concurrent par tuiles Chaque Pi exécute la même boucle sur une grille partagée de tuiles d'image : réserver une tuile libre, vérifier le stress local via les capteurs et choisir un script de persona et un préréglage, l'exécuter et fondre le résultat à faible opacité, libérer la réservation, puis recomposer et diffuser le canevas complet vers l'affichage. tile_init.py Découpe l'image source en tuiles Réserver une tuile libre Fichier .claim exclusif, TTL 30s Choix du script de persona Pondéré selon le stress CPU Exécution et fondu Fondu alpha du résultat dans la tuile Recomposition et diffusion Envoie le canevas complet à l'affichage ↻ libère la tuile, puis en réserve une autre et recommence
Mode B — un cycle de worker, exécuté simultanément par chaque Pi

Initialisation

tile_init.py <image_source.png> [--rows N] [--cols N] [--reset] découpe une image source en une grille R×C (4×4 par défaut) et écrit chaque morceau sous la forme canvas/tile_<ligne>_<colonne>.png. --reset permet de réamorcer la grille à partir d'une nouvelle image sans perturber les fichiers déjà présents.

Boucle de travail (par Pi, par étape)

Chaque instance de tile_worker.py --stage <1|2|3> répète, indéfiniment :

  1. Nettoyage des réservations périmées — tout fichier .claim vieux de plus de 30 secondes est supprimé, au cas où un worker serait mort en cours de traitement d'une tuile.
  2. Réservation d'une tuile libre — les tuiles et leurs coordonnées sont mélangées, et la première tuile sans fichier .claim existant est réservée de façon atomique (création exclusive de fichier, afin que deux Pi ne puissent pas saisir la même tuile).
  3. Lecture du stress local — la température CPU et la charge moyenne sur 1 minute sont converties en un niveau 0/1/2 (« froid / tiède / chaud »).
  4. Choix d'un script de persona — dans le réservoir pondéré de cette étape (le script utilisé la dernière fois voit ses chances à peu près divisées par deux, pour encourager la variété) et son préréglage de paramètres correspondant au niveau de stress.
  5. Exécution du script sur la tuile vers un fichier temporaire, puis fondu alpha du résultat dans la tuile d'origine (--alpha, 0.30 par défaut) afin que les changements s'accumulent progressivement plutôt que de remplacer la tuile d'un coup.
  6. Libération de la réservation, recomposition du canevas complet à partir de toutes les tuiles actuelles, et diffusion vers display_server.py via preview.flush().
  7. Courte pause (--pause, 0.3 s par défaut) puis retour à l'étape 1.

Étape → réservoirs de scripts de persona

ÉtapePersonaRéservoir de scripts
1insectesfault_shift, chunk_hoard, repetition_smash, chunk_shuffle, byte_scramble, metadata_wipe
2bactériesgas_liquid, xor_cascade, bit_rotate, hydrolyse, memory_purge, activity_log
3champignonsbutterfly_permute, hilbert_shatter, cat_map_scramble, lignin_bore, lignine, mycelium_spread

Chaque script de persona réside dans un sous-dossier nommé selon l'étape (scripts/insects/, scripts/bacteria/, scripts/fungi/) et accepte un préréglage de paramètres « froid / tiède / chaud » sélectionné par tile_worker.py selon le niveau de stress capté à cet instant.

Sous-système d'affichage partagé

Utilisation typique

Mode A

./watcher.sh 1   # sur rpiagent01
./watcher.sh 2   # sur rpiagent02
./watcher.sh 3   # sur rpiagent03

Déposez une image nommée hummus.png dans ~/.openclaw/workspace/tmp/ sur n'importe quel Pi pour démarrer la boucle.

Mode B

python3 scripts/tile_init.py seed.png --rows 4 --cols 4
python3 scripts/tile_worker.py --stage 1 --display   # sur le Pi équipé d'un écran
python3 scripts/tile_worker.py --stage 2             # sur les autres Pi
python3 scripts/tile_worker.py --stage 3

Afficher directement une seule image

DISPLAY=:0 feh --fullscreen /chemin/vers/image.png &
killall feh   # fermer