MacBookでllama.cpp + Gemmaを使ってローカルLLM APIサーバーを構築する
前回、Ollamaを使ってGemmaをローカルのマルチモーダルAPIサーバーとして利用する方法を紹介しました。
👉 前回の記事(Ollama版)
https://qiita.com/kazuki_kuriyama/items/b051dc2b407d236721ba
Ollamaは、インストールからモデルの取得、APIサーバーの起動まで非常に簡単で、ローカルLLM・ローカルVLMを試すにはとても良い選択肢です。
一方で、実際にローカルLLMを触っていると、次のようなことをしたくなる場面があります。
- GGUFモデルを直接読み込みたい
- 量子化モデルを自分で選びたい
- コンテキスト長や推論パラメータを細かく調整したい
- Ollamaのモデル管理に頼らず、モデルファイルを自分で管理したい
- より軽量なAPIサーバーを立ち上げたい
- Claude Code / Cline / Aider などからローカルLLMを使いたい
このような場合は、llama.cpp を直接使う方法が便利です。
この記事では、MacBook上で llama.cpp + Gemma を使い、OpenAI互換APIサーバーを構築する方法を紹介します。
完成イメージ
この記事で作る構成は次のとおりです。
MacBook (Apple Silicon)
│
▼
llama-server
│
▼
OpenAI Compatible API
http://127.0.0.1:8080/v1/chat/completions
│
├── curl
├── Python
├── Node.js
├── Claude Code
├── Cline
└── Aider
Ollamaを使わず、llama-server を直接起動して、OpenAI互換APIとして利用します。
llama.cppとは
llama.cpp は、LLMをローカル環境で高速に動かすためのC/C++製の推論エンジンです。
もともとはLLaMA系モデルをローカルで動かすために広まりましたが、現在ではGemma、Qwen、Mistral、Phiなど、多くのモデルに対応しています。
特徴は以下のとおりです。
- ローカル環境でLLMを実行できる
- CPUでも動作する
- Apple SiliconのMetalアクセラレーションに対応している
- GGUF形式のモデルを直接読み込める
- 量子化モデルを扱いやすい
-
llama-serverによりHTTP APIサーバーとして使える - OpenAI互換APIとして既存のSDKやツールから呼び出せる
Ollamaも内部的にはllama.cpp系の仕組みやGGUFモデルを活用していますが、llama.cppを直接使うと、より低レイヤーでモデルや推論設定を制御できます。
Ollamaとllama.cppの違い
Ollamaとllama.cppは、どちらもローカルLLMを使うための強力な選択肢です。
| 項目 | Ollama | llama.cpp |
|---|---|---|
| セットアップ | とても簡単 | やや手動 |
| モデル取得 |
ollama pull で簡単 |
GGUFを自分で選ぶ |
| モデル管理 | Ollamaが管理 | 自分で管理 |
| APIサーバー | 自動で起動 |
llama-server を起動 |
| OpenAI互換API | 対応 | 対応 |
| パラメータ調整 | 比較的シンプル | 細かく指定可能 |
| 実験・検証 | 手軽 | 自由度が高い |
| Vision用途 | Ollamaの方が簡単 | モデルや設定依存 |
ざっくり言うと、
- すぐに使いたいならOllama
- 細かく制御したいならllama.cpp
という使い分けです。
GGUFモデルとは
llama.cppを使ううえで重要なのが、GGUF というモデル形式です。
GGUF(GGML Universal Format)は、ローカル推論向けに設計されたモデルファイル形式です。
通常、Hugging Faceなどで公開されているモデルには、PyTorch形式、Safetensors形式、GGUF形式などがあります。
llama.cppで利用する場合は、基本的に GGUF形式のモデルファイル を使います。
GGUFの特徴は次のとおりです。
- llama.cppで読み込める
- モデル本体とメタデータを1つのファイルにまとめられる
- 量子化モデルを扱いやすい
- CPU / GPU / Apple Siliconでの推論に向いている
- ローカルLLM用途で広く使われている
例えば、以下のようなファイル名のモデルがGGUFです。
gemma-3-4b-it-Q4_K_M.gguf
gemma-3-12b-it-Q4_K_M.gguf
gemma-3-1b-it-q4_0.gguf
拡張子が .gguf になっている点が目印です。
量子化とは
GGUFモデル名には、よく次のような文字列が含まれています。
Q4_K_M
Q5_K_M
Q8_0
Q4_0
これは量子化方式を表しています。
量子化とは、モデルの重みを低いビット数で表現することで、メモリ使用量を削減し、ローカル環境でも扱いやすくする技術です。
ざっくりしたイメージは次のとおりです。
| 量子化 | 特徴 |
|---|---|
| Q2 | 非常に軽いが精度は落ちやすい |
| Q3 | 軽量重視 |
| Q4 | 速度・容量・品質のバランスが良い |
| Q5 | 品質寄り |
| Q6 | さらに品質寄り |
| Q8 | 元モデルに近いが重い |
MacBook 16GB環境では、最初は Q4系 が扱いやすいです。
特に以下のようなモデルから試すとよいです。
Q4_K_M
Q4_0
MacBookのメモリ別おすすめ
目安としては以下です。
| Macのメモリ | おすすめ |
|---|---|
| 8GB | 1B〜4B / Q4 |
| 16GB | 4B〜12B / Q4 |
| 24GB以上 | 12B以上も検討可能 |
| 32GB以上 | 大きめのモデルや長めのコンテキストも試しやすい |
ただし、実際の快適さは以下にも左右されます。
- モデルサイズ
- 量子化方式
- コンテキスト長
- 同時リクエスト数
- 他に起動しているアプリ
- Metalオフロードの効き方
16GB MacBookでは、まず 4B〜12BのQ4量子化モデル から試すのがおすすめです。
前提環境
この記事では以下の環境を想定します。
- macOS
- Apple Silicon Mac
- Homebrew導入済み
- ターミナル操作ができる
- PythonまたはNode.jsが利用可能
Homebrewが未導入の場合は、先にHomebrewをインストールしてください。
llama.cppのインストール
Homebrewでインストールできます。
brew install llama.cpp
インストール後、以下のコマンドで確認します。
llama-cli --version
llama-server --version
バージョンが表示されればOKです。
もし command not found になる場合は、パスが通っているか確認します。
which llama-cli
which llama-server
Gemma GGUFモデルを準備する
llama.cppでは、GemmaのGGUFモデルを使います。
ここでは2つの方法を紹介します。
- Hugging Faceのモデルを
-hfオプションで直接指定する - GGUFファイルをローカルにダウンロードして
-mで指定する
まずは -hf を使う方法の方が簡単です。
方法1:Hugging Faceのモデルを直接指定する
llama.cpp では、Hugging Face上のGGUFモデルを直接指定できます。
例:
llama-cli \
-hf ggml-org/gemma-4-E2B-it-GGUF \
-p "日本語で自己紹介してください。"
この方法では、モデルを手動でダウンロードしてパスを指定する手間が少なくなります。
ただし、モデルによっては利用規約への同意やHugging Faceへのログインが必要になる場合があります。
方法2:GGUFファイルをローカルに置く
モデルを自分で管理したい場合は、GGUFファイルをローカルに保存します。
mkdir -p ~/models
cd ~/models
Hugging FaceからGGUFファイルをダウンロードし、例えば次のように配置します。
~/models/gemma-3-4b-it-Q4_K_M.gguf
以降は、このパスを指定して起動します。
llama-cli \
-m ~/models/gemma-3-4b-it-Q4_K_M.gguf \
-p "llama.cppとは何か、日本語で簡単に説明してください。"
まずはCLIで動作確認する
APIサーバーを立ち上げる前に、まずCLIでモデルが動くか確認します。
llama-cli \
-m ~/models/gemma-3-4b-it-Q4_K_M.gguf \
-p "MacでローカルLLMを使うメリットを3つ教えてください。"
正常に読み込めると、日本語の回答が返ってきます。
例:
MacでローカルLLMを使うメリットは主に3つあります。
1つ目は、入力データを外部サーバーに送信せずに処理できるため、プライバシー面で安心できることです。
2つ目は、API料金を気にせず何度でも試せることです。
3つ目は、ネットワーク環境に依存せず、オフラインでも利用できることです。
CLIで動くことを確認してから、APIサーバー化するとトラブルシュートしやすくなります。
llama-serverでAPIサーバーを起動する
次に、llama-server を使ってOpenAI互換APIサーバーを起動します。
GGUFファイルを指定する場合:
llama-server \
-m ~/models/gemma-3-4b-it-Q4_K_M.gguf \
--host 127.0.0.1 \
--port 8080 \
-c 4096
Hugging Faceのモデルを直接指定する場合:
llama-server \
-hf ggml-org/gemma-4-E2B-it-GGUF \
--host 127.0.0.1 \
--port 8080 \
-c 4096
起動すると、以下のURLでサーバーが待ち受けます。
http://127.0.0.1:8080
OpenAI互換のChat Completions APIは以下です。
http://127.0.0.1:8080/v1/chat/completions
-c オプションとは
-c はコンテキスト長を指定するオプションです。
-c 4096
コンテキスト長を大きくすると、長い文章や長い会話履歴を扱えるようになります。
ただし、コンテキスト長を大きくするとメモリ使用量も増えます。
16GB MacBookでは、まず以下から試すのがおすすめです。
4096
8192
いきなり 32768 など大きな値にすると、メモリ不足で重くなる場合があります。
curlでOpenAI互換APIを叩く
別のターミナルを開いて、以下を実行します。
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "local-gemma",
"messages": [
{
"role": "user",
"content": "MacBookでローカルLLMを使うメリットを日本語で3つ教えてください。"
}
],
"temperature": 0.7,
"max_tokens": 512
}'
model には local-gemma のような任意の名前を指定できます。
実際に使われるモデルは、llama-server 起動時に -m または -hf で指定したモデルです。
レスポンス例
以下のようなJSONが返ってきます。
{
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"role": "assistant",
"content": "MacBookでローカルLLMを使うメリットは主に3つあります。1つ目は、入力データを外部サーバーへ送信せずに処理できるため、プライバシー面で安心できることです。2つ目は、API料金を気にせず何度でも試せることです。3つ目は、ネットワーク環境に依存せず、オフラインでも利用できることです。"
}
}
],
"created": 1783248152,
"model": "local-gemma",
"object": "chat.completion"
}
OpenAI APIと似た形式で返ってくるため、既存のOpenAI SDKを利用したコードを流用しやすいです。
ストリーミング出力を試す
長い回答を生成する場合は、stream: true を使うと体感速度が上がります。
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "local-gemma",
"messages": [
{
"role": "user",
"content": "ローカルLLMを使った開発アイデアを10個出してください。"
}
],
"stream": true,
"max_tokens": 1024
}'
トークンが少しずつ返ってくるため、CLIやチャットUIで使う場合に便利です。
Pythonから利用する
OpenAI SDKを使えば、base_url をローカルサーバーに向けるだけで利用できます。
まずSDKをインストールします。
pip install openai
Pythonコードは以下です。
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8080/v1",
api_key="dummy"
)
response = client.chat.completions.create(
model="local-gemma",
messages=[
{
"role": "user",
"content": "llama.cppを使うメリットを日本語で説明してください。"
}
],
temperature=0.7,
max_tokens=512
)
print(response.choices[0].message.content)
ローカルサーバーなので、api_key は実質的に使いません。
ただし、OpenAI SDK側で必須になるため、dummy のような任意の文字列を入れています。
Pythonでストリーミングする
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8080/v1",
api_key="dummy"
)
stream = client.chat.completions.create(
model="local-gemma",
messages=[
{
"role": "user",
"content": "MacでローカルLLMを活用するアイデアを10個ください。"
}
],
stream=True,
max_tokens=1024
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
長文生成やチャットアプリに組み込む場合は、ストリーミングの方が自然です。
Node.jsから利用する
Node.jsでもOpenAI SDKを使えます。
npm install openai
index.mjs を作成します。
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://127.0.0.1:8080/v1",
apiKey: "dummy",
});
const response = await client.chat.completions.create({
model: "local-gemma",
messages: [
{
role: "user",
content: "ローカルLLM APIサーバーの使い道を3つ教えてください。",
},
],
temperature: 0.7,
max_tokens: 512,
});
console.log(response.choices[0].message.content);
実行します。
node index.mjs
Node.jsでストリーミングする
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "http://127.0.0.1:8080/v1",
apiKey: "dummy",
});
const stream = await client.chat.completions.create({
model: "local-gemma",
messages: [
{
role: "user",
content: "llama.cppを使った開発アイデアを10個出してください。",
},
],
stream: true,
max_tokens: 1024,
});
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content;
if (text) {
process.stdout.write(text);
}
}
Claude Code / Cline / Aiderから使う
llama-server はOpenAI互換APIとして動かせるため、OpenAI互換APIを指定できるツールから接続できます。
接続情報は基本的に以下です。
Base URL: http://127.0.0.1:8080/v1
API Key: dummy
Model: local-gemma
ツール側でOpenAI互換APIの接続先を指定できる場合、上記を設定します。
ただし、コーディング用途ではモデルの性能が重要です。
小さすぎるモデルだと、複雑なコード修正や大きなリポジトリの理解は苦手です。
MacBook 16GB環境では、以下のような使い分けがおすすめです。
| 用途 | モデル目安 |
|---|---|
| 簡単な質問 | 1B〜4B |
| README作成 | 4B〜12B |
| 軽いコード補助 | 4B〜12B |
| 本格的なコード修正 | 12B以上またはクラウド併用 |
Apple Siliconで快適に使うコツ
1. 最初は小さめのモデルで試す
いきなり大きなモデルを使うと、メモリ不足やスワップで重くなります。
最初は以下がおすすめです。
4B / Q4
動作が軽ければ、12Bなどに上げていきます。
2. コンテキスト長を上げすぎない
-c を大きくすると、扱える文章量は増えますがメモリも使います。
最初は以下で十分です。
-c 4096
長文を扱いたい場合にだけ、8192 や 16384 を試します。
3. 他の重いアプリを閉じる
ローカルLLMはメモリを多く使います。
特に16GB環境では、以下を同時に開きすぎると重くなります。
- Chromeの大量タブ
- Docker
- Xcode
- 動画編集ソフト
- 他のLLMサーバー
- IDE複数起動
推論が重いと感じたら、まずアクティビティモニタでメモリ使用量を確認します。
4. 量子化モデルを選ぶ
16GB MacBookでは、Q8よりもQ4の方が扱いやすいです。
例:
Q4_K_M
Q4_0
高精度が必要な場合だけ、Q5やQ8を試します。
Visionモデルを使う場合の注意点
Gemmaにはテキストモデルだけでなく、マルチモーダル用途のモデルもあります。
ただし、llama.cppでVisionモデルを使う場合は、テキストモデルより注意点が多いです。
- モデルがVision対応である必要がある
- GGUF側がVision対応している必要がある
-
mmprojなどの追加ファイルが必要な場合がある - llama.cppのバージョンが対応している必要がある
- OpenAI互換API形式で画像入力できるかは実装状況に依存する
そのため、画像認識を目的にする場合は、まず前回紹介したOllama版で試すのが簡単です。
👉 前回の記事(Ollama版)
https://qiita.com/kazuki_kuriyama/items/b051dc2b407d236721ba
一方で、テキストLLMとしてGemmaをOpenAI互換API化する用途であれば、llama.cppは非常に使いやすいです。
よくあるエラーと対処法
command not found: llama-server
llama.cpp がインストールされていないか、パスが通っていません。
brew install llama.cpp
確認します。
which llama-server
failed to load model
モデルファイルのパスが間違っている可能性があります。
ls ~/models
ファイル名を確認して、-m の指定を修正します。
llama-server \
-m ~/models/正しいファイル名.gguf \
--port 8080
error loading model architecture
利用しているllama.cppが古く、モデルのアーキテクチャに対応していない可能性があります。
Homebrew版を更新します。
brew update
brew upgrade llama.cpp
それでも動かない場合は、最新のllama.cppをGitHubからビルドする必要がある場合があります。
メモリ不足でMacが重い
モデルが大きすぎるか、コンテキスト長が大きすぎる可能性があります。
対処法:
- 小さいモデルを使う
- Q4量子化を使う
-
-c 4096に下げる - 他のアプリを閉じる
- 同時リクエスト数を増やしすぎない
日本語が不自然
モデルによって日本語性能は異なります。
プロンプトで明示すると改善する場合があります。
必ず自然な日本語で回答してください。
専門用語は必要に応じて補足してください。
また、モデルサイズを上げると改善する場合もあります。
APIは起動しているのにSDKからつながらない
Base URLを確認します。
正しい例:
http://127.0.0.1:8080/v1
間違いやすい例:
http://127.0.0.1:8080
OpenAI SDKでは、/v1 まで含める必要があります。
ポート8080が使われている
別のプロセスが同じポートを使っている可能性があります。
別ポートで起動します。
llama-server \
-m ~/models/gemma-3-4b-it-Q4_K_M.gguf \
--port 8081
この場合、APIのURLも変わります。
http://127.0.0.1:8081/v1/chat/completions
Ollama版との使い分け
最後に、Ollama版とllama.cpp版の使い分けを整理します。
| やりたいこと | おすすめ |
|---|---|
| すぐにローカルLLMを試したい | Ollama |
| Visionを簡単に試したい | Ollama |
| GGUFを直接管理したい | llama.cpp |
| 推論パラメータを細かく調整したい | llama.cpp |
| モデル比較やベンチマークをしたい | llama.cpp |
| OpenAI互換APIだけ欲しい | どちらでもOK |
| チームに簡単に共有したい | Ollama |
| 低レイヤーで検証したい | llama.cpp |
まずはOllamaで試し、必要に応じてllama.cppへ進むのがスムーズです。
まとめ
この記事では、MacBook上で llama.cpp + Gemma を使い、OpenAI互換APIサーバーを構築する方法を紹介しました。
今回のポイントは以下です。
- llama.cppはローカルLLMを細かく制御できる推論エンジン
- GemmaのGGUFモデルを使えばMacBook上で動かせる
-
llama-serverを使うとOpenAI互換APIとして公開できる - Python / Node.js / curl から簡単に呼び出せる
- Claude Code / Cline / Aiderなどの接続先としても利用できる
- 16GB MacではQ4量子化モデルから試すのがおすすめ
- Vision用途はOllama版の方が始めやすい
最小構成で試すなら、以下です。
llama-server \
-hf ggml-org/gemma-4-E2B-it-GGUF \
--host 127.0.0.1 \
--port 8080 \
-c 4096
別ターミナルからAPIを叩きます。
curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "local-gemma",
"messages": [
{
"role": "user",
"content": "日本語で自己紹介してください。"
}
],
"max_tokens": 512
}'
Ollamaで手軽に始め、llama.cppで細かく制御する。
この2つを使い分けると、MacBookだけでかなり実用的なローカルLLM環境を構築できます。
👉 前回の記事(Ollama版)
https://qiita.com/kazuki_kuriyama/items/b051dc2b407d236721ba
参考リンク
-
llama.cpp GitHub
https://github.com/ggml-org/llama.cpp -
llama.cpp server README
https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md -
Google AI for Developers - Run Gemma with Llama.cpp
https://ai.google.dev/gemma/docs/integrations/llamacpp -
Hugging Face GGUF documentation
https://huggingface.co/docs/hub/en/gguf