OpenMythos: вступление — открытая реализация архитектуры рекуррентного цикла推理 на основе Claude Mythos

April 26, 2026

TIP

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

Обзор проекта

В апреле 2026 года Anthropic представила Claude Mythos — модель следующего поколения семейства Claude, демонстрирующую поразительные способности в задачах из области разработки ПО, кибербезопасности (особенно поиска и эксплуатации zero-day уязвимостей). Однако Mythos сейчас доступен лишь в ограниченном виде через «Project Glasswing» для части партнеров по защитным исследованиям — до полноценного релиза ещё далеко.

OpenMythos — это ответ сообщества на эту закрытую архитектуру в виде открытого кода: независимый разработчик Kye Gomez на основе опубликованных статей и исследовательской литературы восстановил ключевую архитектуру Mythos, применив подход от первых принципов. Это не официальная версия, не утечка весов — это теоретическая реконструкция (theoretical reconstruction): цель — чтобы исследователи и разработчики могли экспериментально проверить идеи, похожие на заложенные.

Ключевой прорыв — Recurrent-Depth Transformer (RDT): те же веса Transformer выполняются в одном проходе вперёд до 16 раз (настраиваемо). Так реализуется «мышление» итеративно в непрерывном скрытом пространстве, а не путём наращивания сотен слоёв с независимыми весами, как у традиционных моделей. Рекуррентная модель на 770M параметров достигает качества примерно уровня стандартного Transformer на ~1.3B — при тех же возможностях, но с меньшей вдвое численностью параметров.


Сложность / длительность / польза

Уровень для начинающих, около 30 минут: вы сможете прогнать первый forward-проход OpenMythos, понять суть циклического вывода, принцип LTI-стабильного внедрения, а также то, как MoE FFN расширяет ширину модели, не увеличивая активируемые параметры.


Целевая аудитория

Разработчики, у которых есть базовое понимание LLM-архитектуры и которые хотят углубиться в «механизм циклического вывода» и инженерную реализацию, имея опыт 1–5 лет. Если вас интересуют вопросы ниже, OpenMythos — хороший старт:

  • Почему сама идея «больше циклов = глубже рассуждение» имеет теоретическое обоснование
  • Как динамические ограничения LTI помогают избежать расходимости при циклическом обучении
  • Как связка MoE + совместное использование рекуррентных весов находит новую точку равновесия между числом параметров и объёмом вычислений

Ключевые зависимости и окружение

  • Python 3.10+
  • PyTorch 2.0+ (поддержка CUDA ускоряет инференс)
  • Опционально: flash-attn >= 2.8.3 (ускоряет GQA attention, IO оптимально)
  • Минимальное железо: CPU достаточно для toy demo, GPU нужен для полноценного обучения
# только CPU
pip install open-mythos

# с Flash Attention 2 (требует CUDA + build tools)
pip install "open-mythos[flash]"

Полная структура проекта

open_mythos/
├── main.py              # ядро: класс OpenMythos, MythosConfig и все компоненты архитектуры
├── moda.py              # модули MoE / LoRA и т.п.
├── tokenizer.py         # MythosTokenizer (обёртка над openai/gpt-oss-20b)
├── variants.py          # предустановленные масштабы: mythos_1b ~ mythos_1t
├── docs/
│   ├── open_mythos.md   # полный справочник API
│   └── datasets.md      # рекомендации по выбору обучающих датасетов
training/
└── 3b_fine_web_edu.py   # скрипт обучения для 3B: single-card / multi-card
examples/
├── moda_example.py          # демонстрация MoE FFN + LoRA adapter
└── variants_example.py     # сравнение параметров для разных масштабов
tests/
├── test_main.py             # модульные тесты ядра
├── bench_vs_transformer.py  # бенчмарк против стандартного Transformer
└── small_benchmark.py       # бенчмарк производительности малого масштаба

Пошагово

Шаг 1 — Установка

pip install open-mythos

WARNING

Компиляция flash-attn требует CUDA Toolkit и nvcc. Если установка в среде без nvcc завершается ошибкой, OpenMythos автоматически откатится к стандартной реализации attention в PyTorch — корректность не пострадает, только скорость.

Шаг 2 — Сборка конфигурации

Все гиперпараметры передаются через MythosConfig. Чтобы понять несколько ключевых полей:

from open_mythos.main import MythosConfig

cfg = MythosConfig(
    vocab_size=1000,        # размер словаря; demo использует маленький vocab
    dim=256,                # размерность скрытого слоя
    n_heads=8,              # число Query-голов
    n_kv_heads=2,          # число KV-голов (GQA: меньше Q-голов — меньше расход памяти)
    max_seq_len=128,        # максимальная длина последовательности (предел предвычислений RoPE)
    max_loop_iters=4,       # глубина цикла T; при инференсе можно увеличить
    prelude_layers=1,       # число слоёв стандартного Transformer в секции Prelude
    coda_layers=1,          # число слоёв стандартного Transformer в секции Coda
    attn_type="mla",        # "mla" или "gqa"; см. шаг 5
    n_experts=8,            # общее число экспертов MoE
    n_shared_experts=1,     # число «постоянных» экспертов (активны на каждом токене)
    n_experts_per_tok=2,    # сколько top-K экспертов активируется для каждого токена
    expert_dim=64,          # скрытая размерность каждого эксперта
    lora_rank=8,            # ранг глубинного LoRA adapter
)

MythosConfig имеет конструктор по умолчанию: просто MythosConfig() будет использовать набор значений среднего масштаба.

Шаг 3 — Инициализация модели и запуск forward-прохода

import torch
from open_mythos.main import OpenMythos, MythosConfig

cfg = MythosConfig()
model = OpenMythos(cfg)

# подсчёт числа параметров
total = sum(p.numel() for p in model.parameters())
print(f"Parameters: {total:,}")

# forward: shape input_ids (B, T), shape logits (B, T, vocab_size)
ids = torch.randint(0, cfg.vocab_size, (2, 16))   # batch=2, seq=16
logits = model(ids, n_loops=4)                    # 4 цикла inference
print(f"Logits shape: {logits.shape}")            # torch.Size([2, 16, 32000])

n_loops задаёт глубину рекурсии. По умолчанию значение берётся из cfg.max_loop_iters; при инференсе можно увеличить — это ключевая особенность RDT: экстраполяция глубины (depth extrapolation), то есть модель тренируется с N циклами, а при инференсе может использовать N+k, чтобы решать более сложные задачи.

Шаг 4 — Автарегрессионная генерация

# генерация новых токенов: максимум 8, глубина цикла 8
out = model.generate(ids, max_new_tokens=8, n_loops=8)
print(f"Generated shape: {out.shape}")  # torch.Size([2, 24])

Метод generate внутри поддерживает KV cache: первый вызов обрабатывает полный prompt, а дальше при каждом следующем вызове декодируется только один токен. temperature задаёт случайность семплирования, top_k ограничивает диапазон семплирования:

out = model.generate(
    ids,
    max_new_tokens=64,
    n_loops=16,
    temperature=0.8,   # чем ниже — тем детерминированнее
    top_k=40,          # 0 = выключено
)

Шаг 5 — Выбор механизма attention: MLA vs GQA

# Multi-Latent Attention (по умолчанию, рекомендовано для длинного контекста)
cfg_mla = MythosConfig(
    attn_type="mla",
    kv_lora_rank=512,      # потенциальная размерность K/V в кеше (меньше — меньше расход памяти)
    q_lora_rank=1536,      # компрессия размерности Q
    qk_rope_head_dim=64,   # размерность на голову с RoPE
    qk_nope_head_dim=128,  # размерность на голову без RoPE
    v_head_dim=128,
)

# Grouped Query Attention (дружелюбно к памяти; с flash-attn обычно эффективно)
cfg_gqa = MythosConfig(
    attn_type="gqa",
    n_kv_heads=4,         # меньше, чем n_heads; KV-кэш в n_heads/n_kv_heads раз меньше
)

Компромисс: MLA сжимает KV в low-rank потенциальные векторы для кэширования, уменьшая расход памяти примерно в 10–20 раз, но при этом при каждом шаге нужно перестраивать K/V (одна линейная проекция). GQA кэширует полный KV head напрямую, и в паре с Flash Attention 2 получается оптимальный IO. В продакшене MLA экономит память сильнее, а на этапе разработки GQA проще отлаживать.

Шаг 6 — Проверка стабильности рекурсии: контроль спектрального радиуса

Самая частая проблема при обучении RDT — расходимость цикла: скрытое состояние может экспоненциально возрастать на каждой итерации. OpenMythos обеспечивает стабильность по построению через LTI-stable injection. Проверка выполняется через спектральный радиус ρ(A).

# получение дискретизированной матрицы состояний 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

Если при собственном обучении вы обнаружили rho >= 1, не пытайтесь вручную «подкрутить» параметры — это означает, что параметризация LTI injection была обойдена. Проверьте, не было ли ошибочно присвоено значение напрямую injection.log_A или injection.log_dt.

Шаг 7 — Использование вариаций предустановленного масштаба

Не хочется вручную собирать MythosConfig? В variants.py подготовлены предустановки от 1B до 1T:

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

# mythos_7b() возвращает MythosConfig
cfg = mythos_3b()
model = OpenMythos(cfg)
print(f"Variant 3B: {sum(p.numel() for p in model.parameters()):,} params")
ВариантdimExpertsглубина циклаконтекстмаксимальный вывод
mythos_1b204864164k4k
mythos_3b307264164k4k
mythos_10b4096128248k4k
mythos_100b8192256321M128k

Шаг 8 — Запуск обучающих скриптов

В проекте есть встроенный скрипт обучения 3B на FineWeb-Edu:

# одна GPU
python training/3b_fine_web_edu.py

# несколько GPU (автоматическое определение количества GPU)
torchrun --nproc_per_node=$(python -c "import torch; print(torch.cuda.device_count())") \
    training/3b_fine_web_edu.py

TIP

По умолчанию обучение использует сабсет sample-10BT (30B токенов) — подходит для быстрой проверки. Чтобы прогнать полный датасет 100BT, в скрипте поменяйте параметр dataset_name на "sample-100BT".

Ключевая настройка обучения:

# training/3b_fine_web_edu.py (ключевые параметры)
optimizer = torch.optim.AdamW(model.parameters(), lr=3e-4, weight_decay=0.1)
# точность: H100/A100 — bfloat16, старые карты — float16 + GradScaler
# планировщик: 2000 шагов warmup → далее косинусное затухание
# Tokenizer: openai/gpt-oss-20b через MythosTokenizer

Частые проблемы и их устранение

1. Взрыв по памяти: ловушка «количество циклов × размер батча»

Рекуррентная стадия RDT отличается от стандартного Transformer: между слоями независимости меньше — каждый шаг цикла накапливает KV-состояния всех токенов в кэш. Циклы 16 раз × последовательность 4096 × батч 8 создают нагрузку на память в несколько раз выше, чем у обычной модели.

Решение: сначала проверьте с меньшим n_loops (например, 4). После сходимости постепенно увеличивайте; батч масштабируйте линейно, а не фиксированно.

2. Нет Flash Attention, но хочется ускорить

Если компиляция flash-attn не проходит (часто встречается на Windows + CUDA-средах), OpenMythos автоматически откатится к нативной attention в PyTorch. Важно: такой даунгрейд не влияет на корректность, только на скорость — в сценариях с маленькими батчами разница обычно невелика.

3. Не проходит проверка спектрального радиуса: обучение расходится

Если вы изменили параметризацию LTIInjection или при fine-tuning заморозили неправильные слои, из-за чего параметризация injection окажется нарушенной, появится ρ(A) >= 1. Не делайте обрезку (clip) параметров напрямую — вернитесь к настройкам инициализации по умолчанию и начните заново. Стабилизация LTI опирается на структурную параметризацию, а не на постфактум-коррекцию.

4. ACT приводит к раннему завершению: фактическое число циклов меньше, чем n_loops

act_threshold=0.99 означает, что на каждой позиции выход из цикла происходит после накопления 99% вероятности. Если на некоторых задачах вы видите, что фактическое число циклов существенно ниже n_loops, проверьте распределение сложности токенов в данных: слишком «простые» токены будут слишком рано инициировать halting, и для сложных токенов не будет хватать глубины.

5. Крах MoE-роутинга: некоторые эксперты никогда не активируются

Вспомогательная loss для балансировки нагрузки в стиле DeepSeekMoE без loss-знака опирается на динамическую настройку router_bias. Если вы обучаете с нуля и не вызываете логику этого обновления, роутер быстро сойдётся к активации лишь небольшой части экспертов (обычно первых 1–2). В проекте MoEFFN.forward уже содержит место под bias-адаптацию, но в пользовательских обучающих скриптах нужно регулярно вызывать логику обновления bias.

6. Плохое качество генерации: как подбирать temperature и top_k

Сценарийtemperaturetop_kПримечание
Код / математика0.3–0.510–20низкая случайность
Творческое письмо0.7–0.90 (выкл.)высокая вариативность
Отладка / проверка инференса0.0 (greedy)1максимум детерминизма

Дополнительное чтение / направления развития

Ключевые статьи

СтатьяЧто решает
Loop, Think & Generalize (2025)Как рекуррентный Transformer делает неявный вывод в скрытом пространстве
Parcae (Prairie et al., 2026)Scaling Law: как LTI-ограничения обеспечивают стабильность рекурсии
DeepSeekMoE (Dai et al., 2024)Дизайн роутинга для fine-grained MoE + shared experts
DeepSeek-V2 MLA (2024)Принцип сжатия KV в Multi-Latent Attention
Relaxed Recursive Transformers (Bae et al., 2024)Как LoRA adapter повышает рекуррентную выразительность, не увеличивая слишком много параметров

Направления развития

1. Собственный LoRA Adapter: текущий lora_rank одинаковый для всего пайплайна; его можно сделать послойной настройкой, чтобы разные глубины рекурсии использовали разную силу адаптации.

2. Сканирование порога ACT: дефолт 0.99 — эмпирическое значение. Сделайте grid search по 0.8–0.999, и вы обнаружите, что для некоторых задач 0.95 лучше, чем 0.99 (раннее завершение помогает избежать overthinking).

3. Эксперименты с Depth Extrapolation: тренируйте на фиксированном n_loops, а при инференсе делайте sweep n_loops и нарисуйте кривую «число циклов → точность на downstream-задаче». Теоретически должна проявиться форма экспоненциального затухания — это одно из самых важных доказуемых свойств RDT.

4. Сравнение со стандартным Transformer: с помощью скрипта bench_vs_transformer.py сравните рекуррентную модель и стандартную на задачах compositional / systematic generalization при одинаковом количестве параметров. Это наиболее яркий сценарий преимуществ RDT.

Updated April 26, 2026