Aller au contenu
Blogue Krizaka
Tous les billets

16 octobre 2026 · 6 min de lecture

Une plateforme d'IA sur un seul Mac : ce qui casse, ce que Spring AI 2 a changé, et où le portable abandonne

Un Mac à bout de souffle, une ClassCastException qui coupe le chat, des modèles qui deviennent des lignes en base. Ce que j'ai appris en faisant tourner Orazaka sur un portable.

Par Oussama AbidRead in English

Le 12 octobre, mon Mac a saturé. La charge système oscillait entre 100 et 260, et les outils commençaient à échouer avec ENFILE : le système refusait d'ouvrir un fichier de plus. Plusieurs sessions d'agents travaillaient en parallèle, chacune avec ses builds natifs, ses conteneurs Docker ou son simulateur mobile. Tout ça sur un MacBook Pro M1 Max avec 64 Go de mémoire.

Ce Mac est le premier serveur d'Orazaka, le moteur d'IA que je construis. L'idée d'Orazaka est simple : faire tourner l'IA sur une machine que vous contrôlez. Pour moi, cette machine, c'est d'abord mon portable. Voici ce qu'il m'a appris.

Une plateforme d'IA, c'est beaucoup de monde dans une petite cuisine

Même sans IA, une plateforme a besoin de plusieurs choses à la fois : une base de données, un courtier de messages, les services Java eux-mêmes. Ajoutez un serveur de modèles de langage, un moteur d'images, un worker pour la vidéo. Tout ce monde partage la même mémoire. Quand deux gros plats cuisent en même temps, le four sature.

Ma réponse du 12 octobre a été très simple, presque bête : un verrou. Avant une tâche lourde (un build natif, une pile Docker, une génération), une session crée un dossier .heavy.lock. Si le dossier existe déjà, elle attend une minute et réessaie. Comme la clé unique des toilettes d'un café : une personne à la fois, les autres patientent. Ça ralentit un peu tout le monde, mais plus rien ne s'effondre.

Les services Java ont aussi leur part. Orazaka compte jusqu'à onze services Spring Boot. Une proposition ouverte (orazaka#132) estime 4 à 6 Go au repos pour l'ensemble et propose un profil de développement avec une seule JVM. Ce sont des estimations, pas des mesures, et ce n'est pas encore livré.

Le modèle vidéo qui ne rentre pas

J'ai voulu générer de la vidéo en local avec Wan 2.2 TI2V 5B, en format vertical 480×832 et 25 images. Le modèle a manqué de mémoire au moment de décoder : il demandait 26 Gio alors que 62 Gio étaient déjà occupés sur une machine de 64 Go. En 704×1280, même résultat. Quand ça avançait, chaque étape prenait environ 32 secondes, d'après mes notes de travail.

La leçon est claire : la mémoire unifiée du Mac est généreuse pour l'image, pas pour la vidéo. On y reviendra.

Spring Boot 4, Spring AI 2, et les modèles qui deviennent des données

En juin, j'ai migré la plateforme vers Spring Boot 4.0 et Spring AI 2.0 (ADR-030). Ça impose Spring Framework 7 et Jackson 3, qui déplace com.fasterxml.jackson vers tools.jackson. Le changement de version m'intéressait moins que ce qu'il permettait.

Avant, le choix du modèle vivait dans la configuration : un bloc spring.ai.* dans application.yml, et des starters qui configurent les clients à votre place. Changer de modèle voulait dire redéployer. J'ai retiré tout ça. Aujourd'hui, une table ai_providers contient l'adresse et la clé de chaque fournisseur, et une table orazaka_models relie un nom de modèle à son fournisseur. Un DynamicModelRouter lit ces lignes à chaque appel et garde le client en cache.

Pensez à un répertoire téléphonique. Avant, chaque numéro était gravé dans le mur. Maintenant, il est écrit dans le répertoire : on change une ligne, et le prochain appel part au bon endroit, sans travaux. Un administrateur modifie une ligne en base, et la plateforme suit.

Un détail rend ça possible : Ollama et LocalAI parlent le même protocole qu'OpenAI. Un seul client compatible OpenAI, pointé vers une adresse lue en base, suffit pour tous les fournisseurs locaux.

La ClassCastException qui a coupé le chat

Évidemment, ça a cassé. Tout passe par le client compatible OpenAI, qui attend des options de type OpenAiChatOptions. Mais une étape plus haut dans le pipeline étiquetait les fournisseurs locaux avec des OllamaChatOptions. Résultat : une ClassCastException, et plus de chat du tout.

Le correctif, dans RoutedChatModel, convertit les options avant l'appel :

static Prompt toOpenAiPrompt(Prompt prompt) {
  ChatOptions options = prompt.getOptions();
  if (options == null || options instanceof OpenAiChatOptions) {
    return prompt;
  }
  OpenAiChatOptions.Builder builder =
      OpenAiChatOptions.builder()
          .model(options.getModel())
          .temperature(options.getTemperature())
          .maxTokens(options.getMaxTokens());
  // ...tool callbacks, when present
  return new Prompt(prompt.getInstructions(), builder.build());
}

Il y a eu un deuxième piège, plus discret. Une étape qui demandait qwen2.5:7b partait parfois vers l'inférence hébergée, parce que le nom du modèle était ignoré sauf pour deux fournisseurs. Depuis orazaka-ai-engine#13, le routage suit le lien du catalogue entre le modèle et son fournisseur. Et un modèle dont le fournisseur ne répond pas échoue avec une erreur qui nomme le modèle et le fournisseur, au lieu de partir ailleurs en silence. Pour une IA souveraine, ce silence-là est le pire bug possible.

Le disque qui oublie et le tunnel qui coupe

Deux autres problèmes sont venus du mélange entre le Mac et le cloud. La plateforme de dev tourne sur DigitalOcean, et le Mac la rejoint par un tunnel, à travers un relais.

Le premier : les médias générés étaient écrits sur le disque du conteneur, effacé à chaque déploiement. Les lignes en base survivaient, les fichiers disparaissaient. On passe maintenant par un stockage durable, avec un adaptateur Bunny (orazaka-ai-engine#21).

Le second : chaque déploiement redémarre le relais et coupe le tunnel. Un clip en cours de calcul était perdu, puis refait de zéro. Le worker se reconnecte désormais et ne traite jamais deux fois la même tâche (orazaka-worker-media#24).

Ce que le Mac fait bien

Pour tout le reste, le Mac est un très bon point de départ. Il fait le chat avec Ollama, la voix avec Piper, la musique avec ACE-Step et les images avec stable-diffusion.cpp. Une image FLUX.2 [klein] 4B en 1024×1024 prend 62 secondes en médiane, de la commande au fichier. Pas de facture, pas de compte cloud, pas de pilote à installer. Et tout nouveau développeur a déjà un portable.

Trois images sorties de cette machine. Sous chacune, « Comment c'est fait » donne le prompt, la graine, la durée et l'exécution Orazaka qui l'a produite.

Figurines miniatures en tilt-shift qui patinent sur un étang gelé
Patineurs miniatures, 75 s sur le Mac.
Comment c'est fait
Modèle
FLUX.2 [klein] 4B (Q8_0 GGUF) · Apache-2.0
Moteur
stable-diffusion.cpp on Metal, 4 steps, guidance 1.0
Machine
MacBook Pro, Apple M1 Max, 64 GB (Metal)
Via
Orazaka Studio run on dev.orazaka.com
Studio
art-miniature
Prompt
A tiny winter park in Montreal: figurines skating on a frozen pond, a small plain wooden cabin with a glowing window and no signboard, snow-covered spruce trees and warm string lights at dusk. Tilt-shift miniature diorama photograph: handcrafted figurines and props at 1:24 scale, macro lens, extremely shallow depth of field with a thin plane of focus, soft window light, ultra-detailed textures of felt, embroidered thread, painted resin and carved wood. Warm ochre, saffron and indigo palette, playful and tender. No text, no lettering, no logos.
Graine (seed)
1643
Taille
1360×768
Durée
75 s, telles qu'enregistrées par le run
Coût
aucun coût en argent (matériel à nous ; électricité non mesurée)
Run Orazaka
non enregistré
Miniature en tilt-shift d'une ruelle de souk avec des marchands d'épices
Une ruelle d'épices, 100 s sur le Mac.
Comment c'est fait
Modèle
FLUX.2 [klein] 4B (Q8_0 GGUF) · Apache-2.0
Moteur
stable-diffusion.cpp on Metal, 4 steps, guidance 1.0
Machine
MacBook Pro, Apple M1 Max, 64 GB (Metal)
Via
Orazaka Studio run on dev.orazaka.com
Studio
art-miniature
Prompt
A tiny souk alley: figurine spice merchants behind pyramids of saffron, paprika and cumin, hanging pierced-brass lanterns, woven baskets, a cat asleep on a blue doorstep. Tilt-shift miniature diorama photograph: handcrafted figurines and props at 1:24 scale, macro lens, extremely shallow depth of field with a thin plane of focus, soft window light, ultra-detailed textures of felt, embroidered thread, painted resin and carved wood. Warm ochre, saffron and indigo palette, playful and tender. No text, no lettering, no logos.
Graine (seed)
1212
Taille
1024×1280
Durée
100 s, telles qu'enregistrées par le run
Coût
aucun coût en argent (matériel à nous ; électricité non mesurée)
Run Orazaka
non enregistré
Une ruelle du Plateau la nuit après la pluie
Une ruelle du Plateau, 109 s sur le Mac.
Comment c'est fait
Modèle
FLUX.2 [klein] 4B (Q8_0 GGUF) · Apache-2.0
Moteur
stable-diffusion.cpp on Metal, 4 steps, guidance 1.0
Machine
MacBook Pro, Apple M1 Max, 64 GB (Metal)
Via
Orazaka Studio run on dev.orazaka.com
Studio
art-montreal-night
Prompt
A narrow back alley of the Plateau between plain brick walls with no signs, exterior spiral staircases, wooden balconies with potted plants and parked bicycles, a lone cyclist far away. Night street photograph in Montreal after rain: wet cobblestones and asphalt mirroring warm window light and a neon glow of magenta and teal, light mist, 35mm lens at f/1.8, cinematic colour grading, deep blacks, rich textures of old brick, wrought-iron spiral staircases and wet pavement. No readable signs, no lettering, no logos.
Graine (seed)
12
Taille
1360×768
Durée
109 s, telles qu'enregistrées par le run
Coût
aucun coût en argent (matériel à nous ; électricité non mesurée)
Run Orazaka
non enregistré

Elles sont plus grandes que 1024×1024, d'où des durées de 75 à 109 secondes.

Où le portable abandonne

La vidéo part ailleurs. En hébergé, un clip de cinq secondes de Wan 2.2 A14B en 832×480 prend 131 secondes en médiane. Sur un H100 loué, on monte en 720p. La vidéo part donc vers un GPU quand je choisis de l'y envoyer, et le reste du travail reste sur le portable. Les chiffres, les factures et les erreurs de ce choix sont dans le billet sur les coûts.

Ce que vous pouvez en retenir

Si vous démarrez une plateforme d'IA, commencez sur votre portable : c'est la machine la moins chère que vous possédez déjà. Mettez un verrou sur les tâches lourdes avant que la machine ne le fasse pour vous. Rangez le choix des modèles dans des données plutôt que dans le code. Et ne laissez jamais un appel partir vers un autre modèle sans le dire.

Ce que je n'ai pas mesuré : la mémoire et le swap du Mac sur une journée, la mémoire réelle des JVM au repos, et la vitesse du chat en local. Je les utilise tous les jours, mais je n'ai pas encore d'enregistrement chiffré pour les montrer.

Abonnez-vous au fil pour suivre les nouveaux billets

Billets liés

16 octobre 2026 · 5 min de lecture

Pourquoi je construis une IA souveraine à Montréal

Un GPU loué à Montréal, une loi québécoise et trois questions simples à poser à tout logiciel d'IA. Ce que souverain veut dire chez Krizaka, ce que ça coûte, et ce qui n'est pas réglé.

  • Souveraineté
  • IA
  • Montréal

16 octobre 2026 · 8 min de lecture

L'anatomie d'un prompt d'IA : ce que change vraiment chaque ligne ajoutée

Un prompt de six mots, puis trois couches de détail, sur mon Mac avec la même graine. Ce qui s'améliore, ce qui empire, ce qu'un prompt négatif peut faire, et ce que je n'ai pas prouvé.

  • IA
  • Prompts
  • Orazaka

16 octobre 2026 · 9 min de lecture

Ce que coûte vraiment la génération d'images et de vidéo : mes factures, mesurées

Un Mac, une API hébergée et un H100 loué, sur les mêmes images et les mêmes clips. Les secondes, les dollars, les erreurs qui ont coûté cher, et un petit calcul pour savoir quand louer un GPU.

  • Coûts
  • Mesures
  • Orazaka