llama.cpp serverでgemma4:31bのMTPを動かす

メモも兼ねて。


1月ほど前にvLLMでMTPを動かしてみて、動作速度の恩恵は確認できたものの、VRAMがモリモリ食べられてしまうのがちょっと辛みポイントだった。

blue1st-diary.hateblo.jp


その後、OllamaでQwen3.6のMTPイメージ(qwen3.6:27b-mtp-q4_K_M)が動くようになったということで切り替え。

ollama.com

やはりOllamaは運用が気楽だし、OpenClawのLLMもこのイメージに変えてからは、MoE系のモデルと比べれば動作こそ遅めではあるが、最新ニュースを要約してもらったり自分で設定を改善させたりスキルを作らせたりといった「おもしろ」以上の実利ある使い方ができようになった。

ただ、Qwen系は昔からその傾向があるんだけど、ちょいちょい中国漢字が混じったり受け答えが怪しい瞬間があるのが不満だったんですなあ。


やっぱ個人的にはGemma系の手触り感が好きなんだよなあ、でもQwenみたいなMTP組み込みのイメージがOllama公式にはないんだよなあ・・・って思ってたんだけど、 どうせOpenClawでほとんど常用するしOllamaとは別にllama.cpp serverを駐在させるのもアリかと方針転換。

昔一時的に使ってたdocker compose構成をちょっと書き換えて、gemma4:31bのMTP運用をすることにした。

ファイル構成

.
├── .env
└── compose.yml

compose.yml

services:
  llama-cpp-gpu:
    image: ghcr.io/ggml-org/llama.cpp:server-rocm
    ports:
      - "10000:10000"
    volumes:
      - llama-cache:/app/models
    environment:
      - LLAMA_MODEL=${LLAMA_MODEL}
      - LLAMA_N_GPU_LAYERS=${LLAMA_N_GPU_LAYERS:--1}
      - LLAMA_CTX_SIZE=${LLAMA_CTX_SIZE:-32768}
      - LLAMA_BATCH_SIZE=${LLAMA_BATCH_SIZE:-2048}
      - LLAMA_UBATCH_SIZE=${LLAMA_UBATCH_SIZE:-1024}
      - LLAMA_THREADS=${LLAMA_THREADS:-16}
      - LLAMA_N_PARALLEL=${LLAMA_N_PARALLEL:-8}
      - LLAMA_TEMP=${LLAMA_TEMP:-0.8}
      - LLAMA_TOP_K=${LLAMA_TOP_K:-40}
      - LLAMA_TOP_P=${LLAMA_TOP_P:-0.95}
      - LLAMA_MIN_P=${LLAMA_MIN_P:-0.05}
      - LLAMA_REPEAT_PENALTY=${LLAMA_REPEAT_PENALTY:-1.1}
      - LLAMA_CACHE=models
    command: >
      -hf ${LLAMA_MODEL}
      -m ${LLAMA_MAIN_FILE}
      -hfd ${LLAMA_MODEL}
      --model-draft ${LLAMA_DRAFT_FILE}
      --spec-type draft-mtp
      --spec-draft-n-max 2
      --alias ${LLAMA_MODEL_ALIAS}
      --host 0.0.0.0
      --port 10000
      --n-gpu-layers 99
      --n-gpu-layers-draft 99
      --ctx-size ${LLAMA_CTX_SIZE:-32768}
      --batch-size ${LLAMA_BATCH_SIZE:-1024}
      --ubatch-size ${LLAMA_UBATCH_SIZE:-512}
      --threads ${LLAMA_THREADS:-16}
      --threads-batch ${LLAMA_THREADS:-16}
      --parallel ${LLAMA_N_PARALLEL:-1}
      --temp ${LLAMA_TEMP:-0.8}
      --top-k ${LLAMA_TOP_K:-40}
      --top-p ${LLAMA_TOP_P:-0.95}
      --min-p ${LLAMA_MIN_P:-0.05}
      --repeat-penalty ${LLAMA_REPEAT_PENALTY:-1.1}
      --cont-batching
      --log-verbose
      --mlock
      --jinja
      --reasoning-format auto
    restart: unless-stopped
    devices:
      - /dev/kfd:/dev/kfd
      - /dev/dri:/dev/dri
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
volumes:
  llama-cache:

.env

# 同じUnslothのリポジトリを指定
LLAMA_MODEL=unsloth/gemma-4-31B-it-qat-GGUF
LLAMA_MODEL_ALIAS=gemma-4:31b

# ファイル名(または相対パス)を直接指定するために環境変数を分ける
LLAMA_MAIN_FILE=gemma-4-31B-it-qat-UD-Q4_K_XL.gguf
LLAMA_DRAFT_FILE=MTP/gemma-4-31B-it-Q4_0-MTP.gguf

# コンテキストサイズ
LLAMA_CTX_SIZE=256000

# MTPの安定動作のため、並列数は 1 を推奨
LLAMA_N_PARALLEL=1


今回の土日はどうも体調がすぐれなくてベンチをちゃんと取ろうという気にもならなかったが、体感かなり快調な速度で動いてる。

一旦OpenClawやCodexやその他常用系のLLMの向き先はこっちに変えて運用してみようと思う。


余談だけど、ollamaも最近は内部実装でllama.cppをそのまま使うようにしたっぽいけど、この手のドラフトイメージものって対応してくんだろうか?