2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

llama.cpp + Gemmaを使ってローカルLLM APIサーバーを構築する

2
Posted at

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つの方法を紹介します。

  1. Hugging Faceのモデルを -hf オプションで直接指定する
  2. 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

長文を扱いたい場合にだけ、819216384 を試します。


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


参考リンク

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?