Gemma 4 がすごいらしい。 Android 上で動かしたりもできるモデルらしいので、活用していきたいと目論む。
AI 質問しつつなんとなくできたはいいけど絶対忘れるので記録を残す。 ollama ではなく llama cpp を使う。 使用環境は Macbook Air M2 16GB /Tahoe 26.4 です。
llama-cli, llama-mtmd-cli, llama-server をソースからビルドする。
llama-mtmd-cli というのはマルチモーダル用らしい。これを使えば 画像からテキストを生成(image captioning とか)できるのかも。試してない。
llama cpp は こちら https://github.com/ggml-org/llama.cpp 。
レポジトリを clone:
git clone https://github.com/ggml-org/llama.cpp
ビルドします。(環境はできているとして)
cd llama.cpp
cmake -B build -DBUILD_SHARED_LIBS=OFF -DGGML_CUDA=OFF
cmake --build build
--config Release -j --clean-first \
--target llama-cli llama-mtmd-cli llama-server
ビルドできたら成果物は $HOME/.local/llama.cpp/ に配置することにします。
mkdir ~/.local/llama.cpp
cp ./build/bin/llama-* ~/.local/llama.cpp/
~/.local/llama.cpp にパスを通した上で llama-cli が使えることを確認:
$ which llama-cli
/Users/foo/.local/llama.cpp/llama-cli
次のように -hf (これは hugging face からモデルを取得するオプション)を使うと 実行と同時にモデルを入手できるのだが...
llama-cli -hf unsloth/gemma-4-E4B-it-GGUF:Q4_K_M ...
モデルがどこに保存されるか自分で指定したいので、環境変数をセットしておく。
mkdir ~/.local/llama.cpp/models
export LLAMA_CACHE="~/.local/llama.cpp/models"
その上で実行してみる:
llama-cli \
-hf unsloth/gemma-4-E4B-it-GGUF:Q4_K_M \
-p "tell me please how to code STDOUT Hello,World! with JS"
初回は -hf で指定したモデルをダウンロードするので時間がかかる。 ダウンロードしたファイルは LLAMA_CACHE 環境編集で指定したところにダウンロード(キャッシュ)される。
この環境ではここにキャッシュされた:
~/.local/llama.cpp/models/models--unsloth--gemma-4-E4B-it-GGUF/snapshots/960a8cd001a5ec7a679e2c5d93f9916238e76d10/gemma-4-E4B-it-Q4_K_M.gguf
二回目に起動する場合は -hf の代わりに -m オプションでモデルを直接指定する:
というか、試してないけど -hf オプションをそのまま使えば別に良い気がする。 ローカルに指定モデルのキャッシュがあればそれを使い、なければダウンロードしてくれる、という振る舞いに違いない。(試してはいない)
m=~/.local/llama.cpp/models/models--unsloth--gemma-4-E4B-it-GGUF/snapshots/960a8cd001a5ec7a679e2c5d93f9916238e76d10/gemma-4-E4B-it-Q4_K_M.gguf
llama-cli \
-m $m \
-p "tell me please how to code STDOUT Hello,World! with JS"
次のようにしてサーバを起動:
m=~/.local/llama.cpp/models/models--unsloth--gemma-4-E4B-it-GGUF/snapshots/960a8cd001a5ec7a679e2c5d93f9916238e76d10/gemma-4-E4B-it-Q4_K_M.gguf
llama-server \
-m $m \
--jinja \
--port 8080 \
-ngl 99 \
-c 32768
サーバにプロンプトを投げる:
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"gemma-4-e4b","messages":[{"role":"user","content":"tell me please how to code STDOUT Hello,World! with JS"}]}'
Gemma 4 のモデルの説明
もし使用するマックのメモリが 32GB あれば gemma-4-E4B-it-GGUF の代わりに gemma-4-26B-A4B-it-GGUF を使うことができます。 その場合は -hf オプションを次のように指定します:
-hf unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_XL
実行すると(この環境では)モデルは次の場所にキャッシュされました。
.local/llama.cpp/models/models--unsloth--gemma-4-26B-A4B-it-GGUF/snapshots/8bacec5c8e829a25502cdfe3c3f5b6aabee3218c/gemma-4-26B-A4B-it-UD-Q4_K_XL.gguf
この環境でもビルドして動かしてみました。
CUDA 12.8 がセットアップされていることが前提として:
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build \
-DCMAKE_BUILD_TYPE=Release \
-DGGML_CUDA=ON \
-DCMAKE_CUDA_ARCHITECTURES="86"
cmake --build build \
--config Release -j$(nproc) --clean-first \
--target llama-cli llama-mtmd-cli llama-server
先ほどと同じですが、生成した llama.cpp コマンドに所定の場所にコピーしてそこにパスを通します。
mkdir ~/.local/llama.cpp
cp ./build/bin/llama-* ~/.local/llama.cpp/
モデルを用意します。
unsloth/gemma-4-E4B-it-GGUF:Q8_0
試しに llama-cli を -hf 指定して実行します。
llama-cli -hf unsloth/gemma-4-E4B-it-GGUF:Q8_0 -ngl 99
これで llama-cli コマンドの動作確認とローカルにモデルをキャッシュできたので、 次のような llama-server 起動ファイル start.sh を用意:
#!/bin/bash
model=~/.local/llama.cpp/models/models--unsloth--gemma-4-E4B-it-GGUF/snapshots/960a8cd001a5ec7a679e2c5d93f9916238e76d10/gemma-4-E4B-it-Q8_0.gguf
$HOME/.local/llama.cpp/llama-server -m $model \
-ngl 99 \
--jinja \
--host 127.0.0.1 \
--port 8080
このサーバにプロンプトを投げて結果は result.json に保存:
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"gemma-4-e4b","messages":[{"role":"user","content":"tell me STDOUT Hello,World! code with haskell, only code no description"}]}' > result.json
結果の result.json のうち関心のある部分だけを取り出す:
jq -r '.choices[0].message.content' result.json
結局こうなりました:
main :: IO ()
main = putStrLn "Hello,World!"
かきかけです。