NightRun révolutionne l’exécution locale des modèles de langage en s’inscrivant davantage dans une logique proche du micrologiciel que de l’environnement de bureau traditionnel. Le projet démarre directement à partir d’une clé USB via UEFI, charge intégralement le modèle en RAM et exécute l’inférence sur CPU sans Linux, Windows, noyau conventionnel ni pile réseau. Il ne vise pas à remplacer Ollama ou llama.cpp pour une utilisation quotidienne, mais à bâtir une machine dédiée où le logiciel existant, allant du micrologiciel aux LLM, disparaît presque entièrement.

En résumé : les clés techniques de NightRun en 30 secondes

  • NightRun est une application EFI no_std écrite en Rust, qui fonctionne directement sur les Services de démarrage UEFI.
  • Il charge des modèles quantifiés de 1,3 à 2,4 GB entièrement en RAM, puis verrouille l’accès en lecture au stockage.
  • Elle réalise l’inférence uniquement sur CPU via AVX2 sur x86_64 et NEON sur Raspberry Pi 5.
  • Il implémente Llama 3.2, Qwen3 et Granite 4.1 denses, en validation avec llama.cpp.
  • Il ne comprend pas de noyau conventionnel, processus utilisateurs, services, shell, navigateur ou pile TCP/IP.

L’utilisation du firmware via UEFI est cruciale. NightRun n’est pas bare metal au sens strict. Le projet ne décroche pas de ExitBootServices(), ce qui maintient les services du micrologiciel actifs durant toute la session. UEFI fournit ainsi les fonctions essentielles pour gérer l’affichage, le clavier, le stockage et le démarrage des différents cœurs CPU.

C’est une décision volontaire. Développer ses propres pilotes pour USB HID, xHCI, stockage, graphiques et autres particularités des nombreuses cartes mères transformerait ce projet en une œuvre proche d’un système d’exploitation.

NightRun utilise le micrologiciel comme une plateforme et construit par-dessus un chargeur de modèles, un moteur d’inférence, une gestion mémoire, un tokenizer, une interface graphique et une exécution multinoyau.

De BOOTX64.EFI au premier token sans lancer un noyau

Sur un PC x86_64, le micrologiciel exécute directement BOOTX64.EFI. Sur Raspberry Pi 5, c’est BOOTAA64.EFI.

À partir de là, une séquence très différente de celle d’une installation classique d’IA locale commence :

  1. NightRun active le mode SIMD nécessaire à la CPU.
  2. Il initialise le framebuffer et le clavier.
  3. Il démarre les cœurs disponibles via les services MP de UEFI.
  4. Il détecte la mémoire disponible.
  5. Il charge le modèle en intégralité en RAM.
  6. Il vérifie son intégrité durant la lecture.
  7. Il verrouille l’accès au stockage postérieurement.
  8. Il initialise le tokenizer et la configuration de la conversation.
  9. Il réserve la cache KV et la mémoire de travail.
  10. Il lance le chat.

Le runtime exploite le Protocole de sortie graphique UEFI (GOP) pour accéder au framebuffer et dessiner sa propre interface. Il n’y a pas de compositeur, terminal Linux ou serveur graphique caché en dessous.

De même pour le clavier. NightRun utilise les services du firmware pour recevoir l’entrée USB, mais la gestion du texte, l’historique et l’interface de chat sont intégralement sous son contrôle.

Couche Ollama sous Linux NightRun
Micrologiciel UEFI UEFI
Noyau Linux Pas de noyau
Pilotes du système Oui Services UEFI
Espace utilisateur Oui Non
Services en arrière-plan Oui Non
Runtime LLM Ollama/llama.cpp NightRun
Modèle RAM + I/O potentiel RAM uniquement
Réseau Disponible Non implémenté
Interface Terminal/web/app Framebuffer dédié

Cette architecture explique pourquoi le qualifier simplement de « Ollama sans Internet » serait réducteur.

Chargement du modèle une seule fois, stockage disparu après

Une autre différence réside dans la manière dont NightRun gère le modèle.

L’installateur part d’un fichier GGUF compatible, en inspecte la structure et le convertit au format spécifique .nrm. Ce conteneur est conçu pour permettre aux tenseurs d’être utilisés directement depuis la mémoire chargée.

Pendant le démarrage, il lit le fichier par blocs et calcule simultanément leur CRC-32, évitant ainsi une passe supplémentaire uniquement pour vérifier l’intégrité.

Une fois le processus terminé, les poids restent en RAM.

Le runtime impose alors une règle : toute tentative ultérieure de lecture du stockage échoue. La recherche via USB ou microSD est interrompue définitivement.

De plus, toute la mémoire nécessaire est réservée d’avance.

Le design prévoit des régions spécifiques pour les poids, la cache KV, l’espace de travail du pre-fill, la mémoire tampon du decode et les buffers graphiques. Une fonction calcule à l’avance la taille de cette zone mémoire ; si la RAM est insuffisante, le démarrage échoue avant d’entamer la conversation.

Le cycle de génération évite toute allocation dynamique (c’est la règle du zéro heap), selon la documentation du projet.

La conséquence pratique : la RAM détermine quels modèles peuvent être utilisés.

Un Llama 3.2 1B de 1,3 GB requiert une machine avec environ 4 GB. Llama 3.2 3B et Granite 4.1 3B ont besoin d’environ 6 GB, tandis que Qwen3 4B en nécessite 8 GB.

Inférence CPU avec poids quantifiés directement utilisables

NightRun ne supporte pas actuellement la GPU.

Son moteur est orienté vers l’inférence quantifiée sur CPU, utilisant les poids sans générer une copie décompressée en FP32 préalable.

Sur x86_64, il implémente des kernels spécifiques pour AVX2, FMA et F16C. Sur ARM, il utilise NEON et une approche par sdot pour les processeurs compatibles comme le Cortex-A76 de Raspberry Pi 5.

Les méthodes de quantification incluent Q8_0, Q4_K et Q6_K, ainsi que certains tenseurs en F32.

Le projet précise également une particularité souvent oubliée avec les fichiers GGUF : Q4_K_M ne signifie pas que tous les tenseurs sont en Q4_K. Un modèle peut combiner Q4_K, Q6_K et F32 selon le tenseur, et NightRun conserve ces configurations lors de la conversion.

Le pre-fill traite jusqu’à 64 tokens par passage, tandis que le decode fonctionne token par token.

Ceci est crucial car ces deux phases ont des profils très différents. Le traitement initial peut réutiliser les poids entre plusieurs tokens, mais lors de la génération interactive, la performance dépend largement de la bande passante mémoire.

NightRun recommande aussi de prendre en compte une conséquence fréquente : la génération devient plus lente avec la longueur du contexte, car l’attention doit parcourir une cache KV de plus en plus grande.

Llama, Qwen et Granite, mais pas tous les fichiers GGUF

NightRun ne vise pas une compatibilité universelle.

Il supporte actuellement trois familles principales : Llama 3.2, Qwen3 et Granite 4.1 en architecture transformer classique.

Modèle validé Quantification Taille .nrm RAM cible
Llama 3.2 1B Instruct Q8_0 1,3 GB 4 GB
Llama 3.2 3B Instruct Q4_K_M 1,9 GB 6 GB
Granite 4.1 3B Q4_K_M 2,0 GB 6 GB
Qwen3 4B Instruct 2507 Q4_K_M 2,3 GB 8 GB

Les variantes hybrides SSM/MoE de Granite sont explicitement exclues lors de la conversion. Ajouter une nouvelle architecture nécessite d’en implémenter et valider l’exécution, pas simplement de l’ajouter au catalogue.

Ce choix technique résulte d’efforts importants pour gérer ces différences :

Qwen3, par exemple, utilise une disposition RoPE différente de Llama, une normalisation RMSNorm spécifique à Q/K, ainsi qu’une largeur d’attention différente de la dimension cachée. NightRun implémente ces caractéristiques plutôt que de tenter une résolution générique.

Le tokenizer bénéficie aussi de traitements spécifiques.

Les configurations de conversation sont comparées token par token avec apply_chat_template de Hugging Face, et des tests spécifiques empêchent que du texte utilisateur ne soit interprété accidentellement comme des tokens de contrôle.

Référence de validation : llama.cpp

L’un des aspects techniques clés est la vérification que la suppression de couches n’altère pas le résultat du modèle.

NightRun s’appuie sur llama.cpp comme référence pour la génération greedy.

Pour les familles supportées, tout changement dans le moteur doit conserver la génération token par token par rapport à cette référence. Les kernels scalaires servent aussi à valider les versions vectorisées AVX2 et NEON.

Le projet vérifie également que le pre-fill par lots génère les mêmes logits et cache KV que le traitement séquentiel des tokens.

Cela ne garantit pas que NightRun est sans erreur, mais offre une méthode reproductible pour détecter toute divergence dans un moteur d’inférence presque entièrement développé à la main.

Il évite également une affirmation tentante : il ne prétend pas être globalement plus rapide que llama.cpp.

Les benchmarks publiés indiquent environ 20 tokens par seconde lors du decode de Llama 3.2 1B en utilisant QEMU/KVM avec huit cœurs et AVX2. Granite 4.1 3B tourne autour de 13-14 tokens/sec, Qwen3 4B environ 10-11.

Sur Raspberry Pi 5, Granite 4.1 3B a atteint 3 tokens/sec dans le test publié, avant l’arrivée des nouveaux kernels sdot.

Les estimations indiquent que, dans certaines conditions, le decode peut atteindre des performances comparables à llama.cpp, le pre-fill étant quant à lui 1,15 à 1,4 fois plus lent.

L’objectif n’est pas d’écraser llama.cpp en benchmark, mais de vérifier où il est possible d’exécuter le modèle.

Pas de TCP/IP : l’isolement fait partie de l’architecture

Un machine utilisant Ollama peut aussi être déconnectée physiquement d’Internet. D’un point de vue pratique, cela peut assurer un excellent isolement si bien configuré.

NightRun adopte une approche encore plus radicale : aucune pile réseau n’est présente dans le runtime.

Pas de navigateur, pas de démons, pas de mises à jour automatiques, pas de télémétrie, et surtout aucun processus susceptible d’ouvrir une connexion TCP. Le logiciel nécessaire pour cela n’est tout simplement pas implémenté.

Cela réduit considérablement la surface d’attaque pendant une session, mais ne garantit pas une invulnérabilité totale de la machine.

UEFI reste partie intégrante de la chaîne de confiance. La provenance du modèle, l’image générée, la machine utilisée pour la préparer et le code de NightRun lui-même restent aussi des éléments importants à considérer.

Ce choix s’inscrit plus dans une logique d’architecture systèmes, que comme une affirmation absolue de sécurité.

Un projet d’IA aussi construit avec de l’IA

NightRun présente une autre particularité : selon ses développeurs, la majorité du code a été écrite à l’aide de Claude Code avec le modèle Fable 5.

Ce détail est d’autant plus remarquable compte tenu du type de logiciel produit.

Il ne s’agit pas d’une simple application web classique. Le dépôt inclut du code pour UEFI, formats binaires, SIMD, gestion mémoire, tokenisation, inferencing quantifié, framebuffer et un installateur capable d’écrire directement sur des supports de stockage.

De plus, une attention rigoureuse est portée à la validation via des implémentations de référence, à la comparaison avec llama.cpp, au test du parser et au contrôle du processus d’installation.

NightRun reste expérimental. Il requiert UEFI, Secure Boot désactivé, des modèles qui tiennent tout en RAM, et une CPU relativement récente pour des performances interactives. La compatibilité sur du matériel x86_64 réel demeure limitée, et différentes implémentations de firmwares peuvent poser problème.

Mais, d’un point de vue technique, il soulève une question passionnante sur l’avenir de l’IA locale.

Jusqu’à présent, l’essentiel était de rendre chaque fois plus simple l’intégration d’un LLM dans un système d’exploitation. NightRun explore une voie inverse : supprimer le système d’exploitation traditionnel pour transformer tout le PC en un appliance dédié au modèle.

Le résultat ne cherche pas à concurrencer la commodité d’Ollama. C’est une toute autre catégorie : un runtime d’inférence pour USB, démarré depuis le firmware, qui charge ses poids en RAM et fonctionne ensuite sans disque ni réseau.

Pour certains usages : vie privée, systèmes isolés, edge computing, cette approche peut être bien plus pertinente que de viser quelques tokens par seconde en plus.

Source : Noticias inteligencia artificial

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *