En bref
nanochat est le framework open-source d'entraînement de LLM d'Andrej Karpathy qui vous permet d'entraîner un chatbot de niveau GPT-2 pour moins de 50 $ en environ 2 heures. Le projet utilise un seul nœud GPU 8xH100, un code minimal (~500 lignes pour le modèle de base), et un seul paramètre de configuration (--depth) pour optimiser automatiquement tous les hyperparamètres. Les records actuels montrent une complétion de l'entraînement en 1,65 heure avec un score CORE de 0,2626, battant le GPT-2 d'OpenAI de 2019 qui coûtait 43 000 $ et prenait 168 heures.
Introduction
L'entraînement d'un grand modèle linguistique nécessitait autrefois des millions de dollars et une équipe de chercheurs doctorants. Cette époque est révolue.
Andrej Karpathy vient de publier nanochat, un projet open-source qui entraîne une IA conversationnelle performante pour moins que le prix d'un bon dîner. L'ensemble du pipeline s'exécute sur un seul nœud GPU 8xH100 et se termine en moins de 2 heures.
Pourquoi cela est important maintenant
Le paysage de l'IA a radicalement changé début 2026. Ce qui prenait à OpenAI 168 heures et 43 000 $ en 2019 ne prend désormais que 1,65 heure et 48 $. C'est une accélération d'un facteur 100, due aux améliorations algorithmiques, à un meilleur matériel et à l'optimisation communautaire.
Pour les développeurs d'API et les équipes qui créent des applications basées sur l'IA, cela change tout. Vous pouvez désormais expérimenter l'entraînement de modèles personnalisés, tester des modifications architecturales et comprendre les rouages des LLM sans avoir besoin de budgets d'infrastructure massifs.
button
Ce que vous apprendrez
À la fin de cet article, vous comprendrez :
- Comment nanochat réduit les coûts par un facteur 100 par rapport à l'entraînement traditionnel des LLM
- L'architecture complète (modèle GPT, optimiseur Muon, chargement des données)
- Instructions pas à pas pour entraîner votre propre modèle
- Comment utiliser nanochat pour la recherche et l'expérimentation rapides de LLM
- Les limitations réelles et ce que signifie réellement la capacité GPT-2
Qu'est-ce que nanochat ?
nanochat est un harnais minimal d'entraînement de LLM qui couvre l'ensemble du pipeline de développement : tokenisation, pré-entraînement, affinage (finetuning), évaluation, inférence et une interface utilisateur web similaire à ChatGPT.

Le code source tient dans un seul dépôt sans monstres de configuration ni complexité de framework. Karpathy l'a conçu comme une "base solide" qui est lisible, modifiable et facile à forker.
La revendication principale
Entraînez un modèle de capacité GPT-2 (1,6 milliard de paramètres) pour :
- 48 $ à la demande (2 heures à environ 24 $/heure pour 8xH100)
- ~15 $ sur des instances spot
Pour contextualiser, l'entraînement original de GPT-2 par OpenAI en 2019 coûtait environ 43 000 $ et prenait 7 jours sur 32 puces TPU v3.
Ce que nanochat couvre
| Étape | Script | Description |
|---|---|---|
| Tokenisation | scripts.tok_train |
Entraîne un tokenizer BPE (vocabulaire 32 768) |
| Pré-entraînement | scripts.base_train |
Entraîne le modèle GPT de base |
| Affinage | scripts.chat_sft |
Affinage supervisé pour le chat |
| Évaluation | scripts.base_eval |
Métrique CORE, bits par octet |
| Inférence | scripts.chat_cli |
Interface de chat en ligne de commande |
| Interface utilisateur web | scripts.chat_web |
Interface web similaire à ChatGPT |
La philosophie : un seul bouton pour tout contrôler
La plupart des frameworks LLM vous noient sous les fichiers de configuration. nanochat adopte l'approche inverse.
L'ensemble du système s'articule autour d'un seul paramètre : --depth (le nombre de couches de transformateur).
# Modèle de taille GPT-1
torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- --depth=12
# Modèle de capacité GPT-2
torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- --depth=24
# Repousser les limites
torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- --depth=26
Définissez la profondeur, et nanochat calcule tout le reste automatiquement :
- Largeur du transformateur (dimension d'incorporation)
- Nombre de têtes d'attention
- Taux d'apprentissage pour chaque groupe de paramètres
- Horizon d'entraînement (nombre total d'étapes)
- Planifications de la décroissance des poids
- Tailles de lot
Cette philosophie du "bouton unique" permet ce que Karpathy appelle les mini-séries nanochat : une famille de modèles optimisés en calcul de différentes tailles, tous entraînés avec la même approche rigoureuse.
Pourquoi cela fonctionne
L'équipe a mesuré les lois de mise à l'échelle sur des dizaines d'exécutions d'entraînement. Ils ont découvert des relations prévisibles entre la profondeur, la largeur, la taille du lot et la durée de l'entraînement. Au lieu d'exposer tous ces réglages, nanochat encode ces relations directement dans le script d'entraînement.

Vous obtenez un entraînement optimisé en calcul sans avoir besoin d'un doctorat en apprentissage profond.
Le classement : La course pour battre GPT-2
nanochat maintient un classement public qui suit la capacité "temps pour atteindre GPT-2". L'objectif est de dépasser le score CORE original d'OpenAI de 0,256525 sur 22 tâches d'évaluation (ARC, MMLU et d'autres de la suite de benchmarks DCLM).
Records actuels
| Exécution | Modèle | Temps | Score CORE | Innovation clé |
|---|---|---|---|---|
| GPT-2 original | 1.6B | 168 heures | 0.2565 | Référence OpenAI 2019 |
| Exécution 1 | d24 | 3.04 heures | 0.2585 | Référence initiale |
| Exécution 2 | d26 | 2.91 heures | 0.2578 | Entraînement FP8 |
| Exécution 3 | d26 | 2.76 heures | 0.2602 | Taille de lot de 1M de tokens |
| Exécution 4 | d24 | 2.02 heures | 0.2571 | Jeu de données ClimbMix |
| Exécution 5 | d24 | 1.80 heures | 0.2690 | Optimisations découvertes par l'IA |
| Exécution 6 | d24 | 1.65 heures | 0.2626 | Amélioration du smear/backout |
Comment l'IA a découvert des optimisations
Les exécutions 5 et 6 ont intégré des modifications issues du système "autorecherche" de Karpathy. Un agent IA a exploré des modifications architecturales sur de petits modèles d12 (exécutions d'entraînement de 5 minutes), puis a traduit les changements gagnants pour la configuration complète d24.
Le système a trouvé des améliorations pour :
- Mécanisme de backout : Meilleure soustraction résiduelle en milieu de couche
- Implémentation du Smear : Mélange de bigrammes plus efficace à partir des tokens précédents
Ces modifications ont réduit le temps d'entraînement de 2,02 heures à 1,65 heure, soit une amélioration de 19 % découverte grâce à l'expérimentation autonome.
Comment nanochat fonctionne
Le code contient environ 3 000 lignes réparties sur les modules principaux. Examinons chaque composant.
1. Le modèle GPT (nanochat/gpt.py)
Le transformateur suit les meilleures pratiques modernes avec plusieurs optimisations :
Caractéristiques architecturales :
- Embeddings rotatifs (RoPE) : Encodage positionnel relatif sans embeddings de position appris
- Normalisation QK : Stabilise l'entraînement à grande échelle
- Poids non liés : Couches d'embedding de token et de projection de sortie séparées
- Activation ReLU² : ReLU au carré dans le MLP au lieu de GeLU
- Attention de requête groupée (GQA) : Moins de têtes KV que de têtes de requête pour une inférence plus rapide
- Attention à fenêtre glissante : Motif configurable (par exemple, "SSSL" alterne les contextes courts/longs)
- Flash Attention 3 : Optimisation GPU Hopper avec repli SDPA
Embeddings de valeur (ResFormer) :Les couches alternées incluent des embeddings de valeur apprenables mélangés via un gating dépendant de l'entrée :
# Résiduel de valeur : mélange l'embedding de valeur avec un gating par tête
if ve is not None:
ve = ve.view(B, T, self.n_kv_head, self.head_dim)
gate = 3 * torch.sigmoid(self.ve_gate(x[..., :self.ve_gate_channels]))
v = v + gate.unsqueeze(-1) * ve
Cela ajoute de la capacité sans surcharge de calcul significative.
Astuces d'efficacité :
Le modèle inclut trois mécanismes appris qui améliorent la dynamique d'entraînement :
# 1. Mise à l'échelle résiduelle par couche
x = self.resid_lambdas[i] * x + self.x0_lambdas[i] * x0
# 2. Smear : mélange l'embedding du token précédent pour des informations de bigramme
gate = self.smear_lambda * torch.sigmoid(self.smear_gate(x[:, :, :24]))
x = x + gate * x_pre_smear
# 3. Backout : soustrait le résiduel de mi-couche
x = x - self.backout_lambda * x_backout
2. L'optimiseur Muon (nanochat/optim.py)
nanochat utilise une stratégie d'optimiseur mixte :
| Type de paramètre | Optimiseur | Objectif |
|---|---|---|
| Embeddings, lm_head | AdamW | Optimisation adaptative standard |
| Paramètres scalaires | AdamW | Facteurs d'échelle appris |
| Matrices 2D | Muon | Mises à jour orthogonalisées |
Muon (Momentum orthogonalisé par Newton-Schulz) :
L'optimiseur Muon orthogonalise les mises à jour des poids en utilisant une itération quintique de Newton-Schulz appelée "Polar Express" :
# Coefficients de Polar Express (5 itérations)
polar_express_coeffs = [
(8.156, -22.483, 15.879),
(4.043, -2.809, 0.500),
# ... plus de coefficients
]
# Boucle d'orthogonalisation
for a, b, c in polar_express_coeffs[:ns_steps]:
A = X.mT @ X
B = b * A + c * (A @ A)
X = a * X + X @ B
Réduction de la variance NorMuon :
Après l'orthogonalisation, les mises à jour sont normalisées par neurone pour éviter l'effondrement de l'échelle :
v_mean = g.float().square().mean(dim=red_dim, keepdim=True)
v_norm = v_mean.sum(dim=(-2, -1), keepdim=True).sqrt()
final_scale = step_size * (v_norm / v_norm_new.clamp_min(1e-10))
g = g * final_scale.to(g.dtype)
Entraînement distribué :
Pour les configurations multi-GPU, l'optimiseur implémente un partitionnement de style ZeRO-2 avec une communication asynchrone en trois phases :
Phase 1 : Lance toutes les opérations asynchrones reduce_scatter
Phase 2 : Attend les réductions, calcule les mises à jour, lance les all_gathers
Phase 3 : Attend les collectes, recopie les paramètres mis à jour
Cela superpose la communication et le calcul, maximisant l'utilisation du GPU.
3. Gestion de la précision (nanochat/common.py)
nanochat gère la précision explicitement au lieu d'utiliser torch.amp.autocast :
| Matériel | dtype par défaut | Raison |
|---|---|---|
| CUDA SM 80+ (A100, H100) | bfloat16 | Cœurs de tenseurs BF16 natifs |
| CUDA SM < 80 (V100, T4) | float32 | Pas de support BF16 |
| CPU / MPS | float32 | Pas de cœurs à précision réduite |
La couche Linear personnalisée convertit les poids pour correspondre au dtype de calcul pendant le passage avant :
class Linear(nn.Linear):
def forward(self, x):
return F.linear(x, self.weight.to(dtype=x.dtype))
Les poids maîtres restent en FP32 pour la précision de l'optimiseur. Pour les GPU H100 et Blackwell, l'entraînement FP8 est disponible via --fp8, convertissant la plupart des couches en Float8Linear avec une mise à l'échelle par tenseur.
4. Chargement des données (nanochat/dataloader.py)
Le dataloader utilise un conditionnement "best-fit" aligné sur BOS :
- Chaque ligne commence par le token BOS (Début de Séquence)
- Documents empaquetés avec l'algorithme "best-fit" pour minimiser le gaspillage
- Quand aucun document ne tient, un est rogné pour remplir exactement
- Utilisation à 100 % avec environ 35 % de rognage de tokens pour une longueur de séquence de 2048
Cela garantit que chaque token peut se référer au BOS et voir le contexte complet du document.
# Trouve le plus grand document qui tient entièrement
best_idx = -1
best_len = 0
for i, doc in enumerate(doc_buffer):
doc_len = len(doc)
if doc_len <= remaining and doc_len > best_len:
best_idx = i
best_len = doc_len
if best_idx >= 0:
doc = doc_buffer.pop(best_idx)
# Ajoute le document complet
else:
# Rogne le document le plus court pour remplir l'espace restant
5. Unification de Flash Attention (nanochat/flash_attention.py)
Le projet fournit une interface unifiée qui bascule automatiquement entre FA3 et PyTorch SDPA :
from nanochat.flash_attention import flash_attn
# Fonctionne sur n'importe quel matériel - sélectionne automatiquement le meilleur backend
y = flash_attn.flash_attn_func(q, k, v, causal=True, window_size=window_size)
Sur les GPU Hopper avec bfloat16, il utilise Flash Attention 3. Partout ailleurs, il revient à l'attention par produit scalaire à échelle de PyTorch.
6. Moteur d'inférence (nanochat/engine.py)
La classe Engine gère la génération efficace avec :
- Cache KV : Cache de prompt pré-rempli avec
flash_attn_with_kvcachede FA3 - Utilisation d'outils : Les tokens spéciaux déclenchent une calculatrice Python via
eval() - Génération par lots : Clone le cache KV pour l'échantillonnage parallèle
Le moteur coordonne le flux de conversation, y compris en forçant les tokens de sortie d'outil lorsque le modèle invoque la calculatrice.
Pas à pas : Entraînez votre propre modèle
L'ensemble du pipeline se trouve dans runs/speedrun.sh. Voici comment l'exécuter.
Prérequis
- Nœud GPU 8xH100 (ou similaire)
- ~20 Go d'espace disque pour le jeu de données
- Python 3.10+
- Gestionnaire de paquets uv
Étape 1 : Configuration de l'environnement
# Installer uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Créer et activer l'environnement virtuel
uv venv
source .venv/bin/activate
# Installer les dépendances
uv sync --extra gpu
Étape 2 : Téléchargement des données d'entraînement
# Télécharger ~2 milliards de caractères du jeu de données ClimbMix
python -m nanochat.dataset -n 170
# Cela télécharge ~170 fragments de ~100 Mo chacun
# Total : ~17 Go compressés
Le script télécharge les fragments de données de pré-entraînement avec un verrouillage de fichiers pour gérer la coordination multi-rangs.
Étape 3 : Entraîner le tokenizer
# Entraîner un tokenizer BPE avec un vocabulaire de 32 768
python -m scripts.tok_train
# Évaluer le taux de compression
python -m scripts.tok_eval
Le tokenizer utilise un motif de division de style GPT-4 avec un BPE de repli en octets. L'entraînement se termine en environ 10 minutes sur 2 milliards de caractères.
Étape 4 : Pré-entraîner le modèle de base
# Entraîner le modèle d24 (capacité GPT-2)
torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- \
--depth=24 \
--target-param-data-ratio=8 \
--device-batch-size=16 \
--fp8 \
--run=my-first-model
Paramètres clés :
--depth=24: Modèle de taille GPT-2--target-param-data-ratio=8: Légèrement sous-entraîné pour la vitesse--device-batch-size=16: Taille de lot par GPU--fp8: Active l'entraînement FP8 (H100+ uniquement)
Durée d'exécution prévue : ~2 heures.
Étape 5 : Affinage supervisé
# Télécharger les conversations d'identité
curl -L -o ~/.cache/nanochat/identity_conversations.jsonl \
https://karpathy-public.s3.us-west-2.amazonaws.com/identity_conversations.jsonl
# Exécuter le SFT pour la capacité de chat
torchrun --standalone --nproc_per_node=8 -m scripts.chat_sft -- \
--device-batch-size=16 \
--run=my-sft
Cela enseigne au modèle le format de conversation, les tokens spéciaux et l'utilisation d'outils.
Étape 6 : Chatter avec votre modèle
# Chat en ligne de commande
python -m scripts.chat_cli -p "Why is the sky blue?"
# Ou lancer l'interface web
python -m scripts.chat_web
L'interface web s'exécute sur le port 8000 et fournit une interface similaire à ChatGPT.
Flux de travail de recherche : Expérimentation rapide
Pour tester de nouvelles idées, utilisez des modèles plus petits pour une itération plus rapide.
Expériences rapides (~5 minutes)
OMP_NUM_THREADS=1 torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- \
--depth=12 \
--run="d12-test" \
--core-metric-every=999999 \
--sample-every=-1 \
--save-every=-1
Ceci entraîne un modèle d12 (taille GPT-1) avec une journalisation minimale. Parfait pour tester les changements architecturaux.
Métriques à surveiller
Suivez celles-ci dans Weights & Biases :
- val_bpb : Bits-per-byte de validation (perte indépendante de la taille du vocabulaire)
- core_metric : Score d'évaluation DCLM CORE
- train/mfu : Utilisation des FLOPS du modèle (efficacité matérielle)
- train/tok_per_sec : Débit d'entraînement
Exigences de test
Toute amélioration doit fonctionner sur toutes les profondeurs (de d12 à d26). Cela évite le surapprentissage à une taille de modèle unique et garantit des avancées fondées sur des principes.
Pourquoi nanochat est important
Accessibilité des coûts
| Approche | Coût | Temps | Matériel |
|---|---|---|---|
| GPT-2 d'OpenAI (2019) | 43 000 $ | 168 heures | 32 TPU v3 |
| nanochat (2026) | 48 $ | 2 heures | 8xH100 |
| nanochat spot | ~15 $ | 2 heures | 8xH100 spot |
Cela met l'entraînement des LLM à la portée de :
- Chercheurs individuels
- Petites startups
- Cours universitaires
- Passionnés
Valeur éducative
Le code source sert de ressource d'apprentissage :
- ~500 lignes pour le modèle GPT
- ~530 lignes pour l'optimiseur
- Commentaires clairs sur chaque décision de conception
- Pas de configuration cachée
Les étudiants peuvent lire, modifier et expérimenter un pipeline LLM complet.
Vitesse de recherche
Réduire l'entraînement de jours à des heures permet :
- Tests d'hypothèses plus rapides
- Plus d'expériences par semaine
- Coût d'échec réduit
- Collaboration communautaire via le classement
Transparence
Chaque choix de conception est documenté :
- Lois de mise à l'échelle dans
dev/LOG.md - Études d'ablation dans les discussions GitHub
- Détails complets de reproduction pour les entrées du classement
- Divulgation claire de la contribution de l'IA
Limitations et vérification de la réalité
nanochat est impressionnant mais a des limites claires.
Exigences matérielles
Le chiffre de 48 $ suppose l'accès à un nœud 8xH100. Les coûts de location dans le cloud varient :
- Lambda Labs : ~25 $/heure pour 8xH100
- RunPod : ~15 $/heure pour les tarifs spot
- Durée totale d'exécution : ~2 heures de pré-entraînement + SFT
Vous aurez besoin d'environ 50 à 100 $ pour une exécution complète, selon le fournisseur.
Plafond de capacité
nanochat atteint un niveau de performance équivalent à GPT-2 (technologie de 2019). Cela signifie :
Ce qu'il peut faire :
- Conversation de base
- Raisonnement simple
- Mathématiques élémentaires
- Rappel factuel (limité)
Ce qu'il ne peut pas faire :
- Raisonnement complexe en plusieurs étapes
- Génération de code au-delà des fonctions simples
- Suivi d'instructions nuancées
- Compétitif avec GPT-4, Claude ou Gemini
Considérez-le comme un enfant de maternelle : capable d'une conversation de base mais pas d'un travail de niveau expert.
Exigences en matière de données
L'exécution complète télécharge :
- ~170 fragments de données
- ~17 Go compressés
- ~2 milliards de caractères au total
Vous aurez besoin d'un espace de stockage et d'une bande passante adéquats.
Limitations de la métrique
Le score CORE mesure 22 tâches mais ne capture pas :
- Qualité de la conversation dans le monde réel
- Connaissances spécifiques au domaine
- Nuance du suivi d'instructions
- Sécurité et alignement
Différentes graines aléatoires produisent une variance CORE d'environ 0,016. Vos résultats peuvent varier.
FAQ
Combien coûte l'entraînement d'un modèle avec nanochat ?
Environ 48 $ à la demande (24 $/heure × 2 heures) ou ~15 $ sur des instances spot. Cela couvre uniquement le pré-entraînement. Ajoutez environ 30 minutes pour le SFT.
De quel GPU ai-je besoin ?
Minimum : Un seul GPU (tout GPU de centre de données moderne). Optimal : 8xH100 ou 8xA100 pour l'entraînement le plus rapide. Le code s'adapte de 1 GPU à 8 GPU avec une accumulation de gradient automatique.
Combien de temps dure l'entraînement ?
De 1,65 à 3 heures selon la configuration et le matériel. Le record actuel du classement est de 1,65 heure pour un modèle d24.
Qu'est-ce que la métrique CORE ?
Le score DCLM CORE évalue les modèles sur 22 tâches, dont ARC (questions scientifiques), MMLU (compréhension du langage multi-tâches) et d'autres benchmarks. GPT-2 a obtenu un score de 0,256525. nanochat dépasse régulièrement 0,26.
Puis-je m'entraîner sur un seul GPU ?
Oui. Omettez torchrun et le code utilisera automatiquement l'accumulation de gradient. L'entraînement prendra 8 fois plus de temps mais produira des résultats presque identiques.
Quel jeu de données nanochat utilise-t-il ?
La meilleure version actuelle utilise ClimbMix (le jeu de données web sélectionné par NVIDIA). Les versions précédentes utilisaient FineWeb-EDU. Le tokenizer s'entraîne sur environ 2 milliards de caractères provenant des ~8 premiers fragments.
nanochat fonctionne-t-il sur Apple Silicon ?
Oui. Le code s'exécute sur MPS (Metal Performance Shaders) avec une précision float32. L'entraînement est plus lent qu'avec CUDA mais fonctionnel pour l'expérimentation.
Puis-je reprendre l'entraînement à partir d'un checkpoint ?
Oui. Utilisez --resume-from-step=<step> pour reprendre à partir d'un checkpoint sauvegardé. L'état du dataloader est également sauvegardé pour une reprise exacte.
Quelle est la différence entre nanochat et nanoGPT ?
nanoGPT ne couvrait que le pré-entraînement. nanochat s'étend à l'ensemble du pipeline : tokenisation, pré-entraînement, SFT, RLHF, évaluation, inférence et interface utilisateur web.
Conclusion
nanochat prouve que l'entraînement de LLM ne nécessite plus de budgets massifs ou d'infrastructures spécialisées. Ce qui coûtait 43 000 $ en 2019 coûte maintenant moins de 50 $.
L'impact du projet s'étend au-delà de la simple réduction des coûts. En fournissant une base de code minimale et lisible avec une interface "à bouton unique", Karpathy a créé à la fois un outil de recherche et une ressource éducative.
Points clés à retenir
- Réduction des coûts par 100 : De 43 000 $ à 48 $ pour la capacité GPT-2
- Accélération par 100 : De 168 heures à 1,65 heure
- Un seul bouton de configuration :
--depthcontrôle tout - Pipeline complet : De la tokenisation à l'interface utilisateur web
- Piloté par la communauté : Classement public avec améliorations continues
Prochaines étapes
Prêt à entraîner votre propre modèle ? Commencez avec le dépôt nanochat et le script runs/speedrun.sh.
Pour les développeurs d'API qui construisent des applications alimentées par l'IA, comprendre les rouages de l'entraînement des LLM n'a jamais été aussi accessible. La barrière à l'entrée est passée de "startup financée par du capital-risque" à "projet de week-end".
button
