言語モデルを作る

はじめに

興味だけで言語モデルをフルスクラッチで作ってみる.
Visual StudioのC#のAI補完のように, コンテキストを踏まえたコード補完は非常に便利だ.
AIアージェントやヴァイブコーディングより便利で実用的だと思っている.

Visual StudioのC/C++にはAI補完はない, 外部サーバにデータを投げる拡張はあるのだが(そして実際便利で使っている)が, 社内では使えない.

興味も兼ねて言語モデルから自作することにした.

目標

  • Fill In the Middle (FIM)に対応した, コード補完専用言語モデル
  • ローカルで動作する. 拡張に同梱できる程度のサイズ.
  • 気に入らなければユーザが無視すればよい程度の精度
    • 知識も思考も不要, もっともらしい次を予測出来れば充分

とりあえずやってみた

Gemma-3 270mのconfigをベースに, ボキャブラリサイズを小さくした, パラメータ数250M程度の言語モデルを対象に試行錯誤していた.
loss3.2前後から下がらないし, 大した成果がないように思えた. 半年ぐらい浪費した.

ChatGPTとやり取りしながら進める

私は機械学習は専門ではないので, 言いなり状態だ. Google検索より早いので裏取りもそこそこに, 750M程度のアーキテクチャに落ち着いた.
300M前後だとそもそも英文法を詰め込むにも足りないらしい.

トーカナイザー

ボキャブラリサイズは6400だが, データセットのクリーニングは修正した. 以前はASCII以外は除去するだけだった.
コメントのエンコード効率も考慮してASCII以外も残し, 代わりに連続した改行・記号を圧縮したりしてみた.
英語テキスト50%, C/C++コード50%の割合で構築した. コード補完が目的なので英語以外は不要なのだ.

アーキテクチャ

flash attention対応を入れつつしていると肥大化した.
full attentionが元のGemma-3 270mより大幅に増えているので推論速度が遅くなりそうだ.

config.json
{
  "_sliding_window_pattern": 4,

  "architectures": [
    "Gemma3ForCausalLM"
  ],

  "model_type": "gemma3_text",
  "transformers_version": "5.5.0",

  "vocab_size": 64000,

  "bos_token_id": 2,
  "eos_token_id": 1,
  "pad_token_id": 0,

  "dtype": "bfloat16",

  "hidden_activation": "silu",

  "hidden_size": 1280,
  "intermediate_size": 5120,

  "num_hidden_layers": 28,

  "num_attention_heads": 20,
  "num_key_value_heads": 5,
  "head_dim": 64,

  "attention_bias": false,
  "attention_dropout": 0.0,

  "query_pre_attn_scalar": 64,
  "initializer_range": 0.02,
  "rms_norm_eps": 1e-6,
  "max_position_embeddings": 8192,
  "layer_types": [
    "sliding_attention",
    "sliding_attention",
    "sliding_attention",
    "full_attention",

    "sliding_attention",
    "sliding_attention",
    "sliding_attention",
    "full_attention",

    "sliding_attention",
    "sliding_attention",
    "sliding_attention",
    "full_attention",

    "sliding_attention",
    "sliding_attention",
    "sliding_attention",
    "full_attention",

    "sliding_attention",
    "sliding_attention",
    "sliding_attention",
    "full_attention",

    "sliding_attention",
    "sliding_attention",
    "sliding_attention",
    "full_attention",

    "sliding_attention",
    "sliding_attention",
    "sliding_attention",
    "full_attention"
  ],
  "sliding_window": 2048,
  "rope_parameters": {
    "full_attention": {
      "rope_type": "default",
      "rope_theta": 100000.0
    },

    "sliding_attention": {
      "rope_type": "default",
      "rope_theta": 100000.0
    }
  },
  "attn_logit_softcapping": null,
  "final_logit_softcapping": null,
  "tie_word_embeddings": true,
  "use_cache": true,
  "use_bidirectional_attention": false
}

AutoModel

RTX 4070 Ti Superが1枚なので, VRAM16GiBで戦わなければいけない.
初期はHuggingfaceのTransformersのレシピで学習していたが, Nvidia Nemo AutoModelで8bit学習を導入した.
flash attentionと合わせてVRAM16GiBでもぎりぎり動かせるようになった.
8bit Adamはエラーが出て解決できなかった.

まとめ

途中も途中で, いつ学習が終わるんだ状態だか, とりあえず以前よりlossは下がっている.
Visual Studio拡張の方はほとんど完成していたりする. こちらも, 独自の特徴の案を試してみたい.