Guide d’OpenMythos : une implémentation open source de l’architecture de raisonnement en boucles de Claude Mythos

April 26, 2026

TIP

GitHub : kyegomez/OpenMythos | PyPI : open-mythos | Licence : MIT

Présentation du projet

En avril 2026, Anthropic a lancé Claude Mythos — le prochain modèle de la famille Claude, conçu pour le raisonnement. Il se démarque par des capacités inédites sur des tâches d’ingénierie logicielle, de cybersécurité (notamment la découverte et l’exploitation de vulnérabilités zero-day), etc. Cependant, Mythos n’est pour l’instant accessible que de manière limitée via « Project Glasswing », à un nombre restreint de partenaires de recherche en sécurité défensive : il est encore loin d’être publié de façon exhaustive.

OpenMythos est la réponse open source de la communauté à cette architecture fermée : porté par des développeurs indépendants, Kye Gomez a reconstruit l’architecture centrale de Mythos à partir de premiers principes, en s’appuyant sur des articles et références de recherche publiquement disponibles. Ce n’est pas une version officielle, ni une fuite de poids : c’est une reconstruction théorique (theoretical reconstruction) — l’objectif étant de permettre aux chercheurs et développeurs de valider expérimentalement des idées similaires.

Son avancée centrale est le Recurrent-Depth Transformer (RDT) : les mêmes poids de Transformer sont réexécutés jusqu’à 16 fois (configurable) dans un seul passage avant (single forward pass). L’itération se fait ainsi dans un espace latent continu, pour « réfléchir » de manière répétée, plutôt que d’empiler des centaines de couches distinctes, chacune avec ses propres poids. Un modèle récurrent de 770M paramètres atteint une qualité proche d’un Transformer standard d’environ 1,3B — avec, en contrepartie, environ la moitié des paramètres.


Difficulté / Durée / Résultats

Niveau d’entrée, environ 30 minutes : vous ferez tourner votre premier forward d’OpenMythos, afin de comprendre l’essence du raisonnement en boucle, le principe de l’injection stable LTI, et comment le MoE FFN peut élargir la largeur du modèle sans augmenter les paramètres d’activation.


Public cible

Vous avez des bases en architecture LLM et vous cherchez à approfondir le mécanisme de « raisonnement en boucle » ainsi que sa réalisation logicielle, avec 1 à 5 ans d’expérience de développement. Si les questions suivantes vous intéressent, OpenMythos est un bon point de départ :

  • Pourquoi l’idée « plus de boucles = raisonnement plus profond » a, elle-même, un socle théorique
  • Comment les contraintes de dynamique LTI garantissent que l’entraînement en boucle ne diverge pas
  • Comment le MoE + partage de poids récurrents trouvent un nouvel équilibre entre nombre de paramètres et quantité de calcul

Dépendances clés et environnement

  • Python 3.10+
  • PyTorch 2.0+ (le support CUDA accélère l’inférence)
  • Optionnel : flash-attn >= 2.8.3 (accélère l’attention GQA, IO optimisé)
  • Matériel minimal : le CPU peut lancer un toy demo, le GPU permet un entraînement complet
# CPU uniquement
pip install open-mythos

# avec Flash Attention 2 (nécessite CUDA + outils de build)
pip install "open-mythos[flash]"

Structure complète du projet

open_mythos/
├── main.py              # Cœur : la classe OpenMythos, MythosConfig et tous les composants d’architecture
├── moda.py              # Modules MoE / LoRA, etc.
├── tokenizer.py         # MythosTokenizer (encapsule openai/gpt-oss-20b)
├── variants.py          # Tailles prédéfinies : mythos_1b ~ mythos_1t
├── docs/
│   ├── open_mythos.md   # Référence complète de l’API
│   └── datasets.md      # Recommandations pour choisir les jeux de données d’entraînement
training/
└── 3b_fine_web_edu.py   # Script d’entraînement pour modèle 3B (single card / multi-card)
examples/
├── moda_example.py          # Démo MoE FFN + LoRA Adapter
└── variants_example.py     # Comparaison de paramètres entre plusieurs variantes de tailles
tests/
├── test_main.py             # Tests unitaires du module principal
├── bench_vs_transformer.py  # Comparaison de benchmarks avec un Transformer standard
└── small_benchmark.py       # Benchmarks de performance à petite échelle

Étapes pas à pas

Étape 1 — Installation

pip install open-mythos

WARNING

La compilation de flash-attn nécessite CUDA Toolkit et nvcc. Si l’installation échoue dans un environnement sans nvcc, OpenMythos dégradera automatiquement l’implémentation pour utiliser l’attention native standard de PyTorch. Cela n’affecte pas la correction (correctness), seulement la vitesse.

Étape 2 — Construire la configuration

Tous les hyperparamètres sont transmis via MythosConfig. Pour comprendre quelques champs clés :

from open_mythos.main import MythosConfig

cfg = MythosConfig(
    vocab_size=1000,        # Taille du vocabulaire ; demo avec petit vocabulaire
    dim=256,                # Dimension des couches cachées (hidden)
    n_heads=8,              # Nombre de têtes Query
    n_kv_heads=2,          # Nombre de têtes KV (GQA : moins de têtes que Q permet d’économiser de la VRAM)
    max_seq_len=128,        # Longueur maximale de séquence (limite supérieure de RoPE en pré-calcul)
    max_loop_iters=4,       # Profondeur de boucle T ; réglable à la hausse pour l’inférence
    prelude_layers=1,       # Nombre de couches standards dans la section Prelude
    coda_layers=1,          # Nombre de couches standards dans la section Coda
    attn_type="mla",        # "mla" ou "gqa" ; voir l’étape 5
    n_experts=8,            # Nombre total d’experts MoE
    n_shared_experts=1,     # Nombre d’experts permanents (activés pour chaque token)
    n_experts_per_tok=2,    # Nombre top-K d’experts activés par token
    expert_dim=64,          # Dimension cachée de chaque expert
    lora_rank=8,            # Rang de l’adapter LoRA pour la profondeur
)

MythosConfig dispose d’un constructeur par défaut ; un simple MythosConfig() utilisera des valeurs prédéfinies de taille intermédiaire.

Étape 3 — Initialiser le modèle et exécuter un forward

import torch
from open_mythos.main import OpenMythos, MythosConfig

cfg = MythosConfig()
model = OpenMythos(cfg)

# Statistiques : nombre de paramètres
total = sum(p.numel() for p in model.parameters())
print(f"Parameters: {total:,}")

# Forward : input_ids shape (B, T), logits shape (B, T, vocab_size)
ids = torch.randint(0, cfg.vocab_size, (2, 16))   # batch=2, seq=16
logits = model(ids, n_loops=4)                    # 4 itérations de raisonnement en boucle
print(f"Logits shape: {logits.shape}")            # torch.Size([2, 16, 32000])

n_loops contrôle la profondeur de boucle. La valeur par défaut provient de cfg.max_loop_iters. Pendant l’inférence, vous pouvez l’augmenter : c’est une caractéristique clé du RDT : extrapolation de profondeur (depth extrapolation). En clair : vous entraînez le modèle avec N boucles, puis en inférence vous pouvez en utiliser N+k pour traiter des problèmes plus complexes.

Étape 4 — Génération autoregressive

# Générer de nouveaux tokens (jusqu’à 8), profondeur de boucle = 8
out = model.generate(ids, max_new_tokens=8, n_loops=8)
print(f"Generated shape: {out.shape}")  # torch.Size([2, 24])

La méthode generate conserve un KV cache en interne : lors du premier appel, elle traite le prompt complet ; ensuite, à chaque appel, elle ne décode qu’un token. temperature contrôle la randomisation de l’échantillonnage, et top_k limite l’espace de choix :

out = model.generate(
    ids,
    max_new_tokens=64,
    n_loops=16,
    temperature=0.8,   # plus bas = plus déterministe
    top_k=40,          # 0 = désactivé
)

Étape 5 — Choisir le mécanisme d’attention : MLA vs GQA

# Multi-Latent Attention (par défaut, recommandé pour de grands contextes)
cfg_mla = MythosConfig(
    attn_type="mla",
    kv_lora_rank=512,      # Dimension latente de KV mise en cache (plus petit = moins de VRAM)
    q_lora_rank=1536,      # Dimension de compression pour Q
    qk_rope_head_dim=64,   # Dimension par tête avec RoPE
    qk_nope_head_dim=128,  # Dimension par tête sans RoPE
    v_head_dim=128,
)

# Grouped Query Attention (économe en VRAM ; efficace avec flash-attn)
cfg_gqa = MythosConfig(
    attn_type="gqa",
    n_kv_heads=4,         # moins que n_heads ; KV cache réduit de n_heads/n_kv_heads fois
)

Le choix entre les deux : MLA compresse le KV en une mise en cache de vecteurs latents de faible rang, ce qui réduit la VRAM d’environ 10 à 20 fois, mais nécessite de reconstruire K/V à chaque fois (une projection linéaire). GQA met en cache directement les têtes KV complètes : avec Flash Attention 2, l’IO est optimal. En production, MLA consomme moins de VRAM ; en phase de développement, GQA est souvent plus simple à déboguer.

Étape 6 — Vérifier la stabilité de la boucle : test du rayon spectral

Le problème le plus facile à rencontrer en entraînement RDT est la divergence en boucle : le state caché (hidden state) s’amplifie exponentiellement à chaque itération. OpenMythos garantit la stabilité par construction grâce à l’injection stable LTI. La méthode de vérification consiste à contrôler le rayon spectral ρ(A) :

# Récupérer la matrice d’état discrétisée A_discrete
A = model.recurrent.injection.get_A()           # shape (dim,)
rho = torch.linalg.eigvals(A).abs().max().item()

print(f"Spectral radius ρ(A) = {rho:.4f}")
assert rho < 1.0, f"Unstable: ρ(A) = {rho:.4f} >= 1"

WARNING

Si, lors d’un entraînement personnalisé, vous constatez rho >= 1, n’essayez pas de corriger manuellement les paramètres : cela signifie que votre paramétrisation de l’injection LTI est contournée. Vérifiez si vous n’avez pas, par erreur, affecté directement injection.log_A ou injection.log_dt.

Étape 7 — Utiliser des variantes de taille prédéfinies

Vous ne voulez pas configurer MythosConfig à la main ? variants.py fournit des préréglages de 1B à 1T :

from open_mythos import mythos_1b, mythos_3b, mythos_10b, mythos_50b, mythos_100b

# mythos_7b() renvoie un MythosConfig
cfg = mythos_3b()
model = OpenMythos(cfg)
print(f"Variant 3B : {sum(p.numel() for p in model.parameters()):,} params")
VariantedimExpertsProfondeur de boucleContexteSortie max
mythos_1b204864164k4k
mythos_3b307264164k4k
mythos_10b4096128248k4k
mythos_100b8192256321M128k

Étape 8 — Exécuter les scripts d’entraînement

Le projet inclut un script d’entraînement du modèle 3B sur le dataset FineWeb-Edu :

# Une seule GPU
python training/3b_fine_web_edu.py

# Multi GPU (détecte automatiquement le nombre de GPU)
torchrun --nproc_per_node=$(python -c "import torch; print(torch.cuda.device_count())") \
    training/3b_fine_web_edu.py

TIP

Par défaut, l’entraînement utilise le sous-ensemble sample-10BT (30B tokens), pratique pour valider rapidement. Pour lancer le sous-ensemble complet 100BT, modifiez le paramètre dataset_name dans le script pour "sample-100BT".

Configurations d’entraînement clés :

# training/3b_fine_web_edu.py (paramètres clés)
optimizer = torch.optim.AdamW(model.parameters(), lr=3e-4, weight_decay=0.1)
# Précision : bfloat16 pour H100/A100, float16 + GradScaler pour les vieilles cartes
# Schedule : 2000 steps de warmup → décroissance cosinus
# Tokenizer : openai/gpt-oss-20b via MythosTokenizer

Dépannage des problèmes fréquents

1. Explosion de VRAM : le piège de la combinaison nombre de boucles × taille de batch

La phase de boucle de RDT n’est pas identique à un Transformer standard où les couches sont indépendantes : à chaque étape de boucle, l’état KV de tous les tokens s’accumule dans le cache. Faire 16 boucles × séquence de 4096 × batch de 8 entraîne une pression mémoire de plusieurs fois celle d’un modèle classique.

Solution : commencez avec un petit n_loops (par ex. 4) pour valider, puis augmentez progressivement une fois la convergence atteinte ; le batch doit être ajusté par mise à l’échelle linéaire, pas fixé à l’identique.

2. Absence de Flash Attention, mais vous voulez accélérer

Si la compilation de flash-attn échoue (fréquent sur Windows + environnement CUDA), OpenMythos basculera automatiquement sur l’attention native de PyTorch. Notez que cette dégradation n’affecte pas la correction, uniquement la vitesse : dans les scénarios de petits batchs, l’écart est souvent limité.

3. Échec du test de rayon spectral : entraînement qui diverge

Si vous modifiez la paramétrisation de LTIInjection, ou si, pendant le fine-tuning, vous figez (freeze) la mauvaise couche entraînant la destruction des paramètres d’injection, vous observerez ρ(A) >= 1. Ne clippez pas directement les paramètres : revenez à l’initialisation par défaut et redémarrez. La contrainte LTI repose sur la structure paramétrisée, pas sur une correction « après coup ».

4. Arrêt anticipé dû à ACT : le nombre réel de boucles est insuffisant

act_threshold=0.99 signifie que chaque position s’arrête dès qu’elle a accumulé 99% de probabilité. Si, sur certaines tâches, vous constatez que le nombre réel d’itérations est bien inférieur à n_loops, inspectez la distribution de difficulté des tokens dans les données : des tokens trop faciles déclenchent le halting trop tôt, et les tokens complexes n’obtiennent alors pas la profondeur nécessaire.

5. Crash du routage MoE : certains experts ne s’activent jamais

Le load-balancing auxiliary loss à la DeepSeekMoE dépend d’un ajustement dynamique de router_bias. Si vous n’utilisez pas ce mécanisme d’ajustement dès le départ lors de l’entraînement, le routeur va converger rapidement vers l’activation d’un petit nombre d’experts (généralement les 1–2 premiers). Dans le projet, MoEFFN.forward contient une place-holder pour l’ajustement du bias, mais dans un script d’entraînement personnalisé, vous devez appeler régulièrement la logique de mise à jour du bias.

6. Qualité de génération faible : comment régler temperature et top_k

Scénariotemperaturetop_kRemarque
Code / Math0.3–0.510–20faible aléa
Écriture créative0.7–0.90 (désactivé)forte diversité
Débogage / validation d’inférence0.0 (glouton)1maximum de déterminisme

Lecture complémentaire / Directions avancées

Articles clés

ArticleProblème résolu
Loop, Think & Generalize (2025)Comment une boucle Transformer effectue un raisonnement implicite dans l’espace latent
Parcae (Prairie et al., 2026)Lois de scaling qui garantissent la stabilité en boucle via les contraintes LTI
DeepSeekMoE (Dai et al., 2024)Conception fine du routage MoE + experts partagés
DeepSeek-V2 MLA (2024)Principe de compression KV de Multi-Latent Attention
Relaxed Recursive Transformers (Bae et al., 2024)Comment les adapters LoRA améliorent la capacité de représentation en boucle sans ajouter trop de paramètres

Directions avancées

1. Adapter LoRA personnalisé : actuellement, lora_rank est global et identique partout. Vous pouvez le remplacer par une configuration par couche, afin d’utiliser des forces d’adaptation différentes selon la profondeur de boucle.

2. Balayage du seuil ACT : la valeur par défaut 0.99 est un repère empirique. Lancez une recherche sur grille de 0.8–0.999 : sur certaines tâches, 0.95 peut être meilleur que 0.99 (un arrêt anticipé évite l’overthinking).

3. Expériences sur l’extrapolation de profondeur : entraînez avec un n_loops fixe, puis en inférence balayez n_loops et tracez une courbe « nombre de boucles → précision sur la tâche aval ». En théorie, vous devriez observer une forme de décroissance exponentielle : c’est l’une des propriétés les plus importantes et vérifiables du RDT.

4. Comparaison avec un Transformer standard : utilisez le script bench_vs_transformer.py pour comparer, à nombre de paramètres égal, l’écart entre le modèle en boucle et le modèle standard sur des tâches de generalization compositionnelle / systématique. C’est un des scénarios où le RDT montre le plus d’avantages.

Updated April 26, 2026