OpenMythosがローカル環境で動くか検証してみた
はじめに
みなさんClaude Mythos(クロード ミュトス)をご存知でしょうか?Anthropic社が開発した「最強のAI」として噂されていますが、現在は限定的なプレビューにとどまっており、一般ユーザーは利用できません。そんな中、公開されている研究論文やアーキテクチャを元に、理論的に再現しようというプロジェクトが立ち上がりました。それが今回触ってみるOpenMythosです。気になったので、さっそく試してみました!
実行環境
動作環境
| 項目 | スペック |
|---|---|
| OS | macOS Sequoia |
| チップ | Apple M4 |
| メモリ | 16GB |
動作検証用ファイル
今回はローカルで動作検証するため、最低限のDockerfileを用意しています。
FROM python:3.14
WORKDIR /app
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir torch open-mythos loguru sentencepiece tiktoken protobuf
COPY src/ ./src/
WORKDIR /app/src
CMD ["/bin/bash"]
compose.ymlも同様、最低限の内容になります。
services:
openmythos:
build: .
container_name: openmythos_env
working_dir: /app/src
volumes:
- ./src:/app/src
tty: true
example.pyの検証
まずは、OpenMythosの基本的な仕組みを確認するため、リポジトリに用意されている example.pyを動かしてみました。
import torch
from open_mythos.main import OpenMythos, MythosConfig
attn_type = "mla" # or "gqa"
base = {
"vocab_size": 1000,
"dim": 256,
"n_heads": 8,
"max_seq_len": 128,
"max_loop_iters": 4,
"prelude_layers": 1,
"coda_layers": 1,
"n_experts": 8,
"n_shared_experts": 1,
"n_experts_per_tok": 2,
"expert_dim": 64,
"lora_rank": 8,
"attn_type": attn_type,
}
if attn_type == "gqa":
cfg = MythosConfig(**base, n_kv_heads=2)
else:
cfg = MythosConfig(
**base,
n_kv_heads=8,
kv_lora_rank=32,
q_lora_rank=64,
qk_rope_head_dim=16,
qk_nope_head_dim=16,
v_head_dim=16,
)
model = OpenMythos(cfg)
total = sum(p.numel() for p in model.parameters())
print(f"\n[{attn_type.upper()}] Parameters: {total:,}")
ids = torch.randint(0, cfg.vocab_size, (2, 16))
logits = model(ids, n_loops=4)
print(f"[{attn_type.upper()}] Logits shape: {logits.shape}")
out = model.generate(ids, max_new_tokens=8, n_loops=8)
print(f"[{attn_type.upper()}] Generated shape: {out.shape}")
A = model.recurrent.injection.get_A()
print(
f"[{attn_type.upper()}] Spectral radius ρ(A) max: {A.max().item():.4f} (must be < 1)"
)
実行結果
Attaching to openmythos_env
openmythos_env |
openmythos_env | [MLA] Parameters: 1,538,626
openmythos_env | [MLA] Logits shape: torch.Size([2, 16, 1000])
openmythos_env | [MLA] Generated shape: torch.Size([2, 24])
openmythos_env | [MLA] Spectral radius ρ(A) max: 0.3679 (must be < 1)
openmythos_env exited with code 0
問題なく出力されることを確認できました!
それぞれの項目について解説します。
| 項目 | 内容 |
|---|---|
Parameters |
モデルの総パラメーター数 |
Logits shape |
モデルが予測した「次の単語」の候補のデータ構造 [バッチサイズ, 入力トークン数,語彙数] |
Generated shape |
テキスト生成後のデータの長さ [バッチサイズ,トークン数] |
Spectral radius ρ(A) max |
Mythos特有の機構の安定性を示す数値。1未満であれば、安定して推論が行える。 |
Spectral radiusの値が0.3679であり、理論通り安定した推論が可能な状態であることが確認できました!この小規模な構成での成功を踏まえ、いよいよ実用的なサイズである1Bパラメータモデルでのトレーニング検証に進みます。
トレーニングの検証
次は1Bパラメータの本格的なモデルを使って、日本語の学習ができるか試してみました。OpenMythosではTokenizerモデルにgpt-oss-20bを使用しているのですが、メモリ的に動かすのが厳しいため、Tokenizerモデルをrinna/japanese-gpt-1bに変更して検証しています。
import math
import os
import time
import torch
import torch.nn as nn
from loguru import logger
from open_mythos import OpenMythos
from open_mythos.tokenizer import MythosTokenizer
from open_mythos.variants import mythos_1b
from torch.utils.data import DataLoader, IterableDataset
class LocalTestDataset(IterableDataset):
def __init__(self, encoding, seq_len: int, file_path: str):
self.encoding = encoding
self.seq_len = seq_len
self.file_path = file_path
def __iter__(self):
with open(self.file_path, "r", encoding="utf-8") as f:
text = f.read()
tokens = self.encoding.encode(text)
buf = tokens
while len(buf) >= self.seq_len + 1:
chunk = buf[: self.seq_len + 1]
buf = buf[self.seq_len:]
yield (
torch.tensor(chunk[:-1], dtype=torch.long),
torch.tensor(chunk[1:], dtype=torch.long),
)
def get_lr(step: int, warmup: int, total: int, max_lr: float, min_lr: float) -> float:
if step < warmup:
return max_lr * step / warmup
if step >= total:
return min_lr
decay = (step - warmup) / (total - warmup)
return min_lr + 0.5 * (max_lr - min_lr) * (1.0 + math.cos(math.pi * decay))
def main():
if torch.backends.mps.is_available():
device = "mps"
elif torch.cuda.is_available():
device = "cuda"
else:
device = "cpu"
logger.info(f"Using device: {device}")
encoding = MythosTokenizer(model_id="rinna/japanese-gpt-1b")
vocab_size = encoding.vocab_size
seq_len = 16
micro_batch = 1
total_steps = 100
warmup_steps = 10
lr = 1e-4
ckpt_dir = "checkpoints"
input_file = "input.txt"
logger.info("Loading mythos_1b configuration...")
cfg = mythos_1b()
cfg.vocab_size = vocab_size
cfg.max_seq_len = seq_len
model = OpenMythos(cfg)
model.to(device)
n_params = sum(p.numel() for p in model.parameters())
logger.info(f"Model parameters: {n_params:,}")
optimizer = torch.optim.AdamW(
model.parameters(), lr=lr, weight_decay=0.1, fused=(device == "cuda")
)
dataset = LocalTestDataset(encoding, seq_len, input_file)
loader = DataLoader(dataset, batch_size=micro_batch)
model.train()
step = 0
t0 = time.perf_counter()
logger.info("Starting training...")
for x, y in loader:
if step >= total_steps:
break
cur_lr = get_lr(step, warmup_steps, total_steps, lr, lr * 0.1)
for g in optimizer.param_groups:
g["lr"] = cur_lr
x, y = x.to(device), y.to(device)
optimizer.zero_grad()
logits = model(x)
loss = nn.functional.cross_entropy(logits.view(-1, vocab_size), y.view(-1))
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()
if step % 5 == 0:
dt = time.perf_counter() - t0
logger.info(
f"Step {step:3d} | Loss: {loss.item():.4f} | LR: {cur_lr:.2e} | {dt:.2f}s/step"
)
t0 = time.perf_counter()
step += 1
logger.success("Training complete.")
if __name__ == "__main__":
main()
今回は試しに俳句を挿入してみました。
古池や蛙飛びこむ水の音
夏草や兵どもが夢の跡
閑さや岩にしみ入る蝉の声
柿食えば鐘が鳴るなり法隆寺
目には青葉山ほととぎす初鰹
春の海ひねもすのたりのたりかな
五月雨を集めて早し最上川
秋深き隣は何をする人ぞ
朝顔に釣瓶とられてもらい水
行く春や鳥啼き魚の目は泪
実行結果
実際にトレーニングを実施してみた結果がこちらになります。残念ながら、処理落ちしてしまいました...
Attaching to openmythos_env
openmythos_env | 2026-05-15 02:43:16.830 | INFO | __main__:main:57 - Using device: cpu
config.json: 100% 578/578 [00:00<00:00, 1.17MB/s]
openmythos_env | Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
tokenizer_config.json: 100% 283/283 [00:00<00:00, 713kB/s]
spiece.model: 100% 1.04M/1.04M [00:01<00:00, 1.00MB/s]
special_tokens_map.json: 100% 153/153 [00:00<00:00, 377kB/s]
openmythos_env | 2026-05-15 02:43:20.291 | INFO | __main__:main:70 - Loading mythos_1b configuration...
openmythos_env | 2026-05-15 02:43:44.649 | INFO | __main__:main:79 - Model parameters: 1,090,398,082
openmythos_env | 2026-05-15 02:43:44.663 | INFO | __main__:main:92 - Starting training...
openmythos_env | 2026-05-15 02:45:48.213 | INFO | __main__:main:114 - Step 0 | Loss: 11.2153 | LR: 0.00e+00 | 123.43s/step
openmythos_env exited with code 137
1ステップのみ処理されて、2回目でコンテナが終了しています。終了コードの137はメモリ不足による強制終了です。1BモデルをCPUで動かすとなると、私のMacBookのスペックでは足りないようです。
まとめ
今回は、話題のClaude Mythosを再現しようとするOpenMythosをローカルで動かしてみました。OpenMythosのリポジトリにあるexample.pyの動作確認はできましたが、実際にトレーニングをしようとするとパソコンのスペックが足りないようです。今後はクラウドのGPUインスタンスを活用したり、パラメーターの調整を行うなど、アプローチを変えて引き続きOpenMythosの検証を行っていきます!
Discussion