zxell.ai
開発記録 / review23
この記録は、プロジェクトの作業報告(報告 → アーキテクトの回答)を公開用に編集したものです。サーバ運用・セキュリティに関わる部分を省略しています(編集方針)。

review23: zxell_model/ 完成(S/M/L モデル本体・学習・評価・生成・API 取得、CPU スモーク合格)/ RTX 3060 機のセットアップ手順(ドライバ導入から学習開始まで)

作成日: 2026-09-29 対象: review22 確認事項へのご回答(1: 順序 OK / 2: (省略: 接続方法)3060 機は nvidia-smi 不可 → ドライバ手順が必要)を受けた実施報告と、 3060 機で S ベースライン学習を始めるまでの手順書。

要旨

  1. モデル本体と学習・評価コードを zxell_model/ として実装・コミット済み(23a4c97、e2e 修正 1 件追加)。パラメータ数は roadmap どおり S 29.1M / M 121.8M / L 537M。サーバ機(CPU)で tiny 構成のスモーク(学習 → 再開 → 言語別 PPL 評価 → 生成)が一気通貫で合格(2〜3 章)
  2. シャードの配布経路(API)も実証済み: fetch_shards.py が GET /api/shards/{name} で取得し sha256 を照合。 (省略: LAN 内での接続方法)(4 章)
  3. 3060 機の手順書(5 章): NVIDIA ドライバ → PyTorch(CUDA)→ クライアント登録・承認 → シャード取得 → S 学習開始。所要はドライバ再起動込みで 30 分ほど、学習は 約 1 日(2.9B トークン)の見込み
省略: 要旨 4(承認の操作)

1. zxell_model/ の構成

ファイル内容
config.pyS / M / L / tiny の構成。語彙 48k、埋め込みと LM Head の重み共有
model.pyRMSNorm(Pre-Norm)・RoPE・causal Self-Attention(PyTorch の SDPA)・SwiGLU FFN・GPT 本体・素朴な生成(top-p)
data.pyシャード(uint16・記事間 EOS)のメモリマップ読み込み。学習サンプラ(トークン数比例でシャード選択 → ランダム位置)。言語別パープレキシティ評価
train.py学習ループ: AdamW(β 0.9/0.95, wd 0.1)・線形 warmup → cosine(最終 10%)・勾配クリップ 1.0・CUDA では bf16・チェックポイント/再開・定期 val 評価・jsonl ログ
eval.pyチェックポイントの val / test 言語別 PPL(JSON 出力)
sample.pyチェックポイントからの文章生成(sentencepiece で復号)
fetch_shards.pyコーディネータ API からシャード取得(index → .bin / .json / .langs.u8、sha256 照合、済みは飛ばす)

構成は model_architecture.drawio と一致(model_inference.drawio の KV キャッシュは未実装 — フェーズ 4 のデモ用途で必要になったら足す)。

preset層 / d_model / head / ctxパラメータうち非埋め込み
tiny2 / 64 / 2 / 1283.2M0.1M
S6 / 384 / 6 / 102429.1M10.6M
M12 / 768 / 12 / 1024121.8M85.0M
L24 / 1280 / 20 / 2048537.3M475.9M

S は 29.1M のうち 18.4M(63%)が埋め込み(48k × 384)です — review22 2 章で述べた「48k でも S では埋め込みが大半」の実数です。

言語別パープレキシティの仕組み

val / test シャードは走査順(シャッフルなし)なので、記事 i の言語は langs_{split}.u8(tokenize_full.py の中間ファイル)の i 番目です。これを val_000.langs.u8 / test_000.langs.u8 としてシャード横に置きました(記事数 11,129 / 30,171 がメタと一致することを確認)。評価時は EOS の累積で「このトークンは何番目の記事か」を求めて言語を割り当て、言語ごとに損失を集計します。 fetch_shards.py はこの副ファイルも取得します(無ければ全体 PPL のみ)。

2. CPU スモーク(サーバ機・torch 2.14 CPU 版・Python 3.14)

tiny 構成・train シャード 1 個・batch 4・ctx 128:

段階結果
学習 50 ステップloss 10.55 → 10.11(初期値 ln 48000 = 10.78 から下降開始)。約 2,100 トークン/秒(CPU)
途中評価(step 25)val 先頭 2 万トークンで PPL 31,616 → step 50 で 25,372
チェックポイント再開--resume で step 50 から 60 まで継続、評価値が連続(24,416)
eval.py言語別集計が動作(val 先頭 2 万トークンは fr のみ = val が走査順で仏語から始まるため。全量なら 4 言語)
sample.py生成が動作(60 ステップの tiny なので中身はでたらめ — 想定どおり)

数値そのものに意味はなく、「配管がつながっている」ことの確認です。1 つ設計上の修正: 最終評価が val 全量(1,020 万トークン)を舐める仕様は CPU では数十分かかるため、--final-eval-tokens で上限を指定できるようにしました(GPU では全量のまま)。

3. 3060 機での S ベースラインの見込み

項目値
ステップあたりbatch 32 × ctx 1024 = 32,768 トークン
目標トークン数roadmap 3.3 の S: 3B → 90,000 ステップ ≈ 2.95B トークン(train 6.07B の約半分 = 1 エポック未満)
3060 の処理速度(見込み)約 35,000〜40,000 トークン/秒(bf16、実測で更新)
所要約 21〜24 時間
VRAMS は重み+勾配+optimizer で 0.5GB 程度 + 活性化。12GB には余裕(batch 32 で数 GB)
チェックポイント1,000 ステップごとに ckpt_last.pt(上書き)、終了時 ckpt_final.pt。約 350MB

途中評価は 500 ステップごとに val 先頭 100 万トークン(言語別 PPL 込み)、終了時に val 全量。

4. シャードの配布経路(API)の実証

fetch_shards.py をサーバ自身から実行し、既存クライアント(GTX 1050 機、承認済み)の API キーで val シャードを取得 → sha256 一致を確認しました。

省略: LAN 内での接続方法の詳細(サーバの構成)

5. RTX 3060 機のセットアップ手順(上から順に、すべて 3060 機で実行)

省略: 5-1. NVIDIA ドライバの導入手順

5-2. リポジトリと PyTorch(CUDA 版)

# (省略: パッケージの導入)
git clone https://github.com/zxell-ai/zxell.git ~/zxell     # 公開リポジトリなので鍵不要
cd ~/zxell/zxell_model
python3 -m venv .venv && . .venv/bin/activate
pip install --index-url https://download.pytorch.org/whl/cu128 torch
pip install numpy sentencepiece
python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))"

最後の行が True GeForce RTX 3060 を出せば OK。cu128 はドライバの CUDA 12.x 対応が前提です(nvidia-smi 右上の CUDA Version が 12.8 以上なら可。古ければ cu126 を指定)。

省略: 5-3. クライアント登録と承認、5-4. シャード取得(接続先・認証の操作を含むため)

5-5. 短い動作確認(1〜2 分)→ 本番開始(約 1 日)

# 動作確認: S 構成で 30 ステップ(GPU が使われ、tok_per_s が数万出ることを見る)
python train.py --preset S --shards ~/zxell-shards --out runs/S_check --steps 30 --eval-every 30 --final-eval-tokens 200000 --warmup 5

# 本番: SSH が切れても続くよう tmux(または nohup)の中で
tmux new -s zxell
python train.py --preset S --shards ~/zxell-shards --out runs/S_baseline --steps 90000 2>&1 | tee runs/S_baseline/stdout.log
#   (Ctrl-b d で tmux から抜ける。戻るときは tmux attach -t zxell)

途中で止まった/止めた場合は同じコマンドに --resume runs/S_baseline/ckpt_last.pt を足せば続きから再開します。

5-6. 様子の見方

tail -f runs/S_baseline/log.jsonl          # loss / lr / grad_norm / tok_per_s、500 ステップごとに val の言語別 PPL
python eval.py runs/S_baseline/ckpt_last.pt ~/zxell-shards val --max-tokens 1000000     # 途中経過の PPL
python sample.py runs/S_baseline/ckpt_last.pt --sp <sp_bpe_48k.model のパス> --prompt "The central bank"

sp_bpe_48k.model(1MB)はサーバから取得します。(省略: 取得元と取得方法)

6. 確認事項

  1. 3060 機の情報: lsb_release -ds(Ubuntu の版)と mokutil --sb-state(Secure Boot の有無)の結果を教えてください。手順 5-1 の分岐(MOK 登録の要否)がこれで決まります。分からなければ 5-1 をそのまま進めて、画面の出方で判断できます。
省略: 確認事項 2(承認の操作)
  1. 学習のハイパーパラメータ(3 章)は nanoGPT 系の定番値(lr 6e-4、batch 32×1024、90k ステップ)です。異論がなければこれで最初のベースラインを取り、結果を見て調整します。

7. 次の作業予定

  1. 5-1〜5-5 のセットアップ(お客様側の作業 + 承認)→ S ベースライン学習開始(約 1 日)
  2. 学習中: 損失曲線と言語別 PPL の推移を log.jsonl から可視化するスクリプト、ダッシュボードへの「学習状況」表示の設計
  3. 学習後: test の言語別 PPL・生成サンプルの目視 → フェーズ 1 の完了判定(「S がまともな文を生成し、評価が自動で回る」)→ review で報告
  4. フェーズ 2 準備: クライアント v1 の train タスクを本物の局所学習(この zxell_model を呼ぶ)に置き換える設計、1050 向けのトークン範囲タスク
← review22目次review24 →