投稿

Kaggle の無料 GPU で 30B モデルを動かし、手元のコーディングエージェントにつなぐ

Kaggle の無料 GPU で 30B モデルを動かし、手元のコーディングエージェントにつなぐ

まとめ

  • Kaggle の T4 2 枚で qwen3-coder:30b(Q4_K_M)が 22.6GB で載り、44.5 tok/s 出た。cloudflared の一時 URL は Host ヘッダで振り分けられるため、Host を書き換えるプロキシを挟んで localhost に固定した
  • つまずいたのは転送ではなく、モデルに渡る手前だった。opencode の system prompt が 137,727 文字になり、48K context を超えて切り捨てられ、ツール呼び出しが本文に漏れていた。専用の HOME で起動すると 8,637 文字に収まり、ファイル編集まで通った
  • GPU の確保は kaggle kernels push のバッチだと 45 分待っても来なかった。ブラウザの対話セッションなら数分で来た

構成

手元の RTX 4080 SUPER は 16GB で、Q4_K_M の 30B は 18.6GB ある。

量子化をさらに落とす手もあるが、まずは無料枠の GPU にモデルだけ置く形を試した。 Google Colab の GPU で ComfyUI を動かしたときと同じで、手元にはエージェントとリポジトリを残す。

表1: 何をどこに置くか

場所 持つもの
手元 opencode、作業対象のリポジトリ、Host を書き換えるプロキシ
Kaggle ollama、モデル、cloudflared
ntfy 一時 URL の受け渡し

Kaggle に推論サーバを立てる

notebook は kaggle kernels push で非対話に流せるが、GPU の確保で待たされた。

NvidiaL4 を指定すると GPU の無いマシンに割り当てられ、/dev/nvidia* が存在せず CPU で動いた。size_vram は 0 だった。 NvidiaTeslaT4 を指定したバッチは 45 分経っても QUEUED のままだった。 ブラウザで notebook を開き、Session options で GPU T4 x2 と Internet を On にして Run All すると、数分で確保できた。

インストールで 1 か所止まった。 ollama の install.sh は zstd を要求するが、Kaggle のイメージには入っていない。

apt-get update -qq && apt-get install -y zstd
curl -fsSL https://ollama.com/install.sh | sh

モデルの取得は 18.6GB で 201 秒だった。 セッションをまたぐキャッシュは無いので、毎回この時間がかかる。

手元から届かせる

Kaggle の notebook に外から入る口は無いので、cloudflared で内側から外へ出る。

cloudflared tunnel --url http://127.0.0.1:11434 --no-autoupdate

URL の受け渡しで 1 つ、接続で 1 つ、それぞれ引っかかった。

実行中の kernel は kaggle kernels logs が空を返す。ログが読めるのは完了後だけなので、トンネルの URL をログから拾えない。 notebook から ntfy に URL を投げ、手元で拾う形にした。

cloudflared は Host ヘッダで振り分ける。 socat で 127.0.0.1:11435 に転送すると Host が 127.0.0.1 のままになり、Cloudflare が 403 を返す。 Host を書き換えるプロキシを挟み、手元からは常に http://127.0.0.1:11435/v1 を叩けばよい形にした。

ツール呼び出しが壊れた原因

最初はモデルとの相性を疑った。

ライブラリ版の qwen3-coder:30b は /api/show のテンプレートが `` だけで、ツール呼び出しが <function=read> という生テキストで本文に漏れた。 Hugging Face の GGUF に差し替えるとテンプレートは 1,482 文字になり、単発の呼び出しは finish_reason: tool_calls で返るようになった。

それでも opencode 経由だと 2 手目で崩れた。 プロキシに要求の骨格を記録させて気づいたのが、system prompt の長さだった。 opencode はスキル一覧と指示ファイルを読み込むため、system prompt が 137,727 文字になっていた。 48K context に対して大きすぎ、切り捨てられた状態でモデルに渡っていた。

専用の HOME で起動すると system prompt は 8,637 文字になった。 同じ依頼で、return a - b を return a + b に、a + b を a * b に直すところまで通った。

表2: 詰まった箇所

症状 原因 対処
ツール呼び出しが <function=read> として本文に出る ライブラリ版のテンプレートが `` のみ Hugging Face の GGUF に差し替える
2 手目で JSON が本文に漏れる system prompt 137,727 文字が 48K context を超える 専用 HOME で 8,637 文字に減らす
プロキシ経由で 403 Cloudflare が Host ヘッダで振り分ける Host を書き換えるプロキシを挟む
実行中の URL が取れない kernels logs が完了後しか読めない ntfy に publish する

運用上の制約

表3: 実測値

項目 値
生成速度 44.5 tok/s
VRAM 使用 24.5 / 30 GB(context 49,152)
モデル取得 18.6GB、201 秒
セッション 最長 9 時間、タブを閉じると停止
GPU 枠 30 時間/週

30B なので、複雑な指示は取りこぼす。まずは小さな修正から試している。

無料枠でサーバを立て続ける使い方が規約上どこまで許されるかは未確認で、個人の実験の範囲として使っている。

トレンドのタグ