TIP
GitHub: kyegomez/OpenMythos | PyPI: open-mythos | License: MIT
项目简介
2026 年 4 月,Anthropic 推出了 Claude Mythos——Claude 系列的下一代推理模型,在软件工程、网络安全(尤其是零日漏洞发现与利用)等任务上展现出前所未有的能力。不过 Mythos 目前仅通过 "Project Glasswing" 有限开放给部分防御性安全研究合作伙伴,远未全面发布。
OpenMythos 就是社区对这一封闭架构的开源回应:由独立开发者 Kye Gomez 基于公开论文和研究文献,从第一性原理重建了 Mythos 的核心架构。它不是官方版本,不是权重泄露,而是一个理论重建(theoretical reconstruction)——目的是让研究者和开发者能够实验验证类似想法。
它的核心突破是 Recurrent-Depth Transformer(RDT):同一个 Transformer 权重在单次前向传播中循环执行最多 16 次(可配置),以迭代方式在连续隐空间中完成"思考",而非像传统模型那样堆叠数百层独立权重。770M 参数的循环模型可以达到约 1.3B 标准 Transformer 的质量——同样的能力,少了一半的参数。
难度 / 时长 / 收获
入门级难度,约 30 分钟,带你跑通第一个 OpenMythos 前向传播,理解循环推理的本质、LTI 稳定注入的原理,以及 MoE FFN 如何在不增加激活参数的前提下扩展模型宽度。
目标读者
对 LLM 架构有基础了解,想深入理解"循环推理"机制及其工程实现的 1-5 年经验开发者。如果你对以下问题感兴趣,OpenMythos 是个好起点:
- 为什么"更多循环 = 更深推理"这件事本身是有理论支撑的
- LTI 动力学约束如何保证循环训练不发散
- MoE + 循环权重共享如何在参数量和计算量之间找到新平衡点
核心依赖与环境
- Python 3.10+
- PyTorch 2.0+(CUDA 支持可加速推理)
- 可选:
flash-attn >= 2.8.3(加速 GQA 注意力,IO 最优) - 最低硬件:CPU 可跑toy demo,GPU 可完整训练
# CPU only
pip install open-mythos
# with Flash Attention 2 (requires 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 模型单卡 / 多卡训练脚本
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 会自动降级到标准 PyTorch 注意力实现,不影响正确性,只影响速度。
步骤 2 — 构建配置
所有超参数通过 MythosConfig 传入。来理解几个关键字段:
from open_mythos.main import MythosConfig
cfg = MythosConfig(
vocab_size=1000, # 词表大小,demo 用小词表
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, # Prelude 段的标准 Transformer 层数
coda_layers=1, # Coda 段的标准 Transformer 层数
attn_type="mla", # "mla" 或 "gqa",见步骤 5
n_experts=8, # MoE 路由专家总数
n_shared_experts=1, # 常驻专家数(每个 token 都激活)
n_experts_per_tok=2, # 每个 token 激活的 top-K 专家数
expert_dim=64, # 每个专家的隐藏维度
lora_rank=8, # 深度 LoRA adapter 的秩
)
MythosConfig 有一个默认构造函数,直接 MythosConfig() 会使用一套中等规模的预设值。
步骤 3 — 初始化模型并运行前向传播
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:,}")
# 前向传播: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 次循环推理
print(f"Logits shape: {logits.shape}") # torch.Size([2, 16, 32000])
n_loops 控制循环深度。默认值来自 cfg.max_loop_iters,推理时可以调高——这是 RDT 的关键特性:深度外推(depth extrapolation),即模型在训练时用 N 次循环,在推理时可以用 N+k 次,处理更复杂的问题。
步骤 4 — 自回归生成
# 生成新 token,最多 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,后续每次只解码一个 token。temperature 控制采样随机性,top_k 限制采样范围:
out = model.generate(
ids,
max_new_tokens=64,
n_loops=16,
temperature=0.8, # 越低越确定性
top_k=40, # 0 = 关闭
)
步骤 5 — 选择注意力机制:MLA vs GQA
# Multi-Latent Attention(默认,推荐用于大上下文)
cfg_mla = MythosConfig(
attn_type="mla",
kv_lora_rank=512, # 缓存的 KV 潜在维度(越小越省显存)
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 压缩成低秩潜在向量缓存,显存减少约 10–20 倍,但每次需要重建 K/V(一个线性投影);GQA 直接缓存完整 KV 头,配合 Flash Attention 2 时 IO 最优。生产规模下 MLA 更省显存,开发阶段 GQA 调试更简单。
步骤 6 — 验证循环稳定性:谱半径检查
RDT 训练最容易出的问题是循环发散——hidden state 在每次循环中指数级放大。OpenMythos 通过 LTI 稳定注入 从构造上保证了稳定性,验证方法是检查谱半径 ρ(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.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")
| 变体 | dim | Experts | 循环深度 | 上下文 | 最大输出 |
|---|---|---|---|---|---|
mythos_1b | 2048 | 64 | 16 | 4k | 4k |
mythos_3b | 3072 | 64 | 16 | 4k | 4k |
mythos_10b | 4096 | 128 | 24 | 8k | 4k |
mythos_100b | 8192 | 256 | 32 | 1M | 128k |
步骤 8 — 运行训练脚本
项目内置了 FineWeb-Edu 数据集上的 3B 模型训练脚本:
# 单 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 token),适合快速验证。要跑完整 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 via MythosTokenizer
常见问题排查
1. 显存爆炸:循环次数 × 批次大小的组合陷阱
RDT 的循环阶段不像标准 Transformer 那样层间独立——每个循环步骤都会把所有 token 的 KV 状态累积到 cache。循环 16 次 × 序列 4096 × 批次 8,显存压力是普通模型的数倍。
解法:先用小 n_loops(如 4)验证,收敛后再逐步增加;批次按线性缩放而非固定。
2. Flash Attention 缺失但想加速
安装 flash-attn 编译失败时(常见于 Windows + CUDA 环境),OpenMythos 会自动降级到 PyTorch 原生注意力。注意这个降级不影响正确性,只影响速度——原生实现在小批量场景下差距不大。
3. 谱半径检查失败:训练发散
如果你自己改了 LTIInjection 的参数化,或在微调时 freeze 了错误的层导致 injection 参数被破坏,会出现 ρ(A) >= 1。不要直接 clip 参数——回到默认初始化重新开始。LTI 约束靠的是参数化结构,不是事后修正。
4. ACT 提前停导致循环实际次数不足
act_threshold=0.99 意味着每个位置累积到 99% 概率后就会提前退出。如果你在某些任务上发现实际循环次数远低于 n_loops,检查数据中的 token 难度分布——太简单的 token 会过早触发 halting,导致复杂 token 得不到足够深度。
5. MoE 路由崩溃:某些专家永远不激活
DeepSeekMoE 风格的辅助损失-free 负载均衡依赖 router_bias 的动态调整。如果你从头训练没有调用这个调整逻辑,路由器会快速收敛到只激活少数专家(通常是前 1-2 个)。项目中 MoEFFN.forward 已内置了 bias 调整的占位,但在自定义训练脚本中需要定期调用 bias 更新逻辑。
6. 生成质量差:温度和 top_k 怎么配
| 场景 | temperature | top_k | 备注 |
|---|---|---|---|
| 代码 / 数学 | 0.3–0.5 | 10–20 | 低随机性 |
| 创意写作 | 0.7–0.9 | 0(关闭) | 高多样性 |
| 调试 / 推理验证 | 0.0(贪心) | 1 | 最确定性 |
扩展阅读 / 进阶方向
核心论文
| 论文 | 解决的问题 |
|---|---|
| Loop, Think & Generalize (2025) | 循环 Transformer 如何在隐空间做隐式推理 |
| Parcae (Prairie et al., 2026) | LTI 约束保证循环稳定性的 Scaling Law |
| DeepSeekMoE (Dai et al., 2024) | 细粒度 MoE + 共享专家的路由设计 |
| DeepSeek-V2 MLA (2024) | Multi-Latent Attention 的 KV 压缩原理 |
| Relaxed Recursive Transformers (Bae et al., 2024) | LoRA adapter 如何在不增加太多参数的前提下提升循环表达力 |
进阶方向
1. 自定义 LoRA Adapter:当前 lora_rank 是全局统一的,可以改成逐层配置,让不同循环深度使用不同的适配强度。
2. ACT 阈值扫描:默认 0.99 是一个经验值。跑一个 0.8–0.999 的网格搜索,你会发现在某些任务上 0.95 比 0.99 更好(早停避免了 overthinking)。
3. Depth Extrapolation 实验:用固定 n_loops 训练,然后在推理时 sweep n_loops,画一条"循环次数 → 下游任务准确率"的曲线。理论上应该看到指数衰减形状——这是 RDT 最重要的可证性质之一。
4. 对比标准 Transformer:用 bench_vs_transformer.py 脚本,在相同参数量下对比循环模型和标准模型在 compositional / systematic generalization 任务上的差距。这是 RDT 最显著的优势场景。