7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GGUFってなんだ?〜ローカルLLMの「共通言語」を完全理解する〜

7
Posted at

この記事の対象読者

  • llama.cppやOllamaでローカルLLMを動かしたことがある方
  • HuggingFaceで「Q4_K_M」「Q8_0」などの文字列を見かけるが意味がわからない方
  • .gguf ファイルをダウンロードして使っているが、中身を理解していない方
  • 「量子化」という言葉をなんとなく使っているが、正確に説明できない方

この記事で得られること

  • GGUFの正体: 「なんとなくダウンロードするファイル」から「構造を理解して選べる」レベルへ
  • 量子化の仕組み: Q4_K_M、Q8_0などの記号の意味と、品質・サイズのトレードオフを理解できる
  • 実践スキル: モデルの変換・量子化・実行を自分の手で行えるようになる

この記事で扱わないこと

  • llama.cppの内部実装の詳細
  • 量子化手法の数学的な厳密な導出
  • safetensorsやONNXとの網羅的な比較

1. GGUFとの出会い

「RTX 5090の32GBじゃ70Bモデルは動かないよ」

ローカルLLMに手を出した人なら、VRAM制約との戦いを一度は経験したことがあるだろう。70Bパラメータのモデルをfloat16で読み込むと約140GB。RTX 5090ですら焼け石に水だ。

そこで登場するのが「量子化」という技術で、それを実現する最も普及したファイル形式がGGUF(GGML Universal File Format)だ。

私が最初にGGUFに触れたのは、llama.cppでLlama 2を動かそうとした時だった。「Q4_K_M」を選べばいいらしいぞ、と言われるがまま4bit量子化版をダウンロードして実行。70Bモデルが16GBのVRAMで動いた瞬間、「何が起きているんだ?」と素直に感動した。

でも同時に、こんな疑問が次々に湧いてきた。

「Q4_K_MのKって何?Mって何?Q8_0と何が違うの?」

調べてみると、GGUFはただの「軽いモデルファイル」どころか、モデルのアーキテクチャ情報・トークナイザー・量子化パラメータを一つのファイルにパッケージした、極めて賢いフォーマットだった。

ここまでで、GGUFが「量子化されたモデルを入れる箱」以上の存在だということが伝わっただろうか。
次は、この記事で使う用語を整理しておこう。


2. 前提知識の確認

2.1 量子化(Quantization)とは

モデルの重み(パラメータ)の精度を下げて、ファイルサイズとメモリ使用量を削減する技術。料理でたとえると、高解像度の写真をJPEG圧縮するようなもの。見た目の品質は多少落ちるが、ファイルサイズは劇的に小さくなる。

精度 ビット数 1パラメータあたり 7Bモデルのサイズ目安
float32 32bit 4 bytes 約28GB
float16 16bit 2 bytes 約14GB
int8 8bit 1 byte 約7GB
int4 4bit 0.5 byte 約3.5GB

2.2 llama.cppとは

Georgi Gerganov氏が開発した、C/C++実装のLLM推論エンジン。依存ライブラリなしでビルドでき、CPU・GPU・NPUなど幅広いハードウェアで動作する。2026年2月現在、GitHubで85,000スター以上を獲得している。GGUFはこのllama.cppのネイティブフォーマットだ。

2.3 トークナイザーとは

テキストを数値列(トークン)に変換する仕組み。モデルが「言葉を理解する」ための入り口であり、GGUFファイルにはこのトークナイザーの語彙データも同梱されている。

これらの用語が押さえられたら、GGUFの背景を見ていこう。


3. GGUFが生まれた背景

3.1 前身:GGML形式の限界

llama.cppは当初、GGML形式を使っていた。しかしGGMLには拡張性の問題があった。モデルのメタデータ(アーキテクチャ情報、コンテキスト長など)を柔軟に格納する仕組みがなく、新しいモデルアーキテクチャへの対応が困難だった。

3.2 2023年8月:GGUFの誕生

GGMLの後継として、Georgi Gerganov氏自身がGGUF(GGML Universal File Format)を設計した。設計目標は明確だった。

設計目標 実現方法
自己完結性 モデル重み + メタデータ + トークナイザーを1ファイルに
拡張性 キーバリュー形式のメタデータで任意の情報を格納可能
ポータビリティ アーキテクチャをメタデータに記録し、ツール側で自動判定
量子化の柔軟性 テンソルごとに異なる量子化手法を適用可能

3.3 2024-2026年:エコシステムの爆発的成長

GGUFは急速に普及し、2026年現在では事実上のローカルLLM標準フォーマットとなっている。HuggingFace Hubでは GGUF-my-repo スペースでワンクリック変換が可能になり、HuggingFace Inference EndpointsもGGUFをネイティブサポート。Ollama、LM Studio、GPT4Allなど主要なローカルLLMツールがすべてGGUFを採用している。

背景がわかったところで、基本的な仕組みを見ていこう。


4. 基本概念と仕組み

4.1 ファイル構造:「全部入り」のバイナリ

GGUFファイルは4つのセクションで構成される。

┌─────────────────────────────────────┐
│  ヘッダー                            │
│  - マジックナンバー: "GGUF"           │
│  - バージョン番号                     │
│  - テンソル数 / メタデータ数           │
├─────────────────────────────────────┤
│  メタデータ(キーバリュー形式)         │
│  - general.architecture: "llama"     │
│  - llama.context_length: 4096       │
│  - tokenizer.ggml.model: "llama"    │
│  - tokenizer.ggml.tokens: [...]     │
│  - general.file_type: 10            │
├─────────────────────────────────────┤
│  テンソル情報                         │
│  - 各テンソルの名前、次元、型、オフセット │
├─────────────────────────────────────┤
│  テンソルデータ(バイナリ)             │
│  - 実際の重みデータ(量子化済み)       │
└─────────────────────────────────────┘

safetensorsとの決定的な違いは、メタデータの豊富さ。safetensorsがテンソルの保存に特化しているのに対し、GGUFはモデルの実行に必要な情報(アーキテクチャ、コンテキスト長、トークナイザー語彙)をすべて同梱する。つまり、GGUFファイル1つあれば、追加の設定ファイルなしで推論を開始できるのだ。

4.2 量子化タイプの解読表

HuggingFaceで見かける Q4_K_M のような記号。これを分解して理解しよう。

Q4_K_M
│ │ │
│ │ └─ M = Medium(品質とサイズのバランス)
│ └── K = K-Quant方式(新しい高品質な量子化手法)
└─── 4 = 4ビット量子化
量子化タイプ ビット数 品質 7Bモデルサイズ 用途
Q2_K 2bit 約2.7GB 極限の省メモリ
Q3_K_S 3bit やや低 約3.2GB メモリ厳しい環境
Q4_0 4bit 約3.8GB レガシー。Q4_K_Mを推奨
Q4_K_M 4bit 中〜高 約4.1GB 最も人気。バランス最良
Q5_K_M 5bit 約5.0GB 品質重視かつ省メモリ
Q6_K 6bit かなり高 約5.9GB 品質重視
Q8_0 8bit 非常に高 約7.2GB ほぼ無劣化。変換の中間形式にも
F16 16bit 最高 約14GB 量子化なし(参照用)

実践的なアドバイス: 迷ったらQ4_K_Mを選べば間違いない。品質とサイズのバランスが最も良く、コミュニティでも最も使われている。

4.3 K-Quant vs 旧方式

「K」がつく量子化タイプ(Q4_K_M等)は、テンソルの重要度に応じてビット数を変える賢い方式だ。例えば注意機構の重みは高精度(6bit)で保持し、FFN層の重みは低精度(4bit)にするといった最適化を自動で行う。旧方式のQ4_0は全テンソル一律4bitだったので、同じ4bitでもK-Quantの方が品質が高い。

4.4 safetensors vs GGUF:住み分け

観点 safetensors GGUF
主な用途 学習・ファインチューニング・HF Hub配布 ローカル推論・エッジデプロイ
量子化 格納のみ(量子化自体は別ツール) 量子化の仕組みを内蔵
メタデータ テンソル情報のみ アーキテクチャ + トークナイザー + 設定全部
主な利用ツール PyTorch / HuggingFace Transformers llama.cpp / Ollama / LM Studio
セキュリティ pickle排除で安全 実行コードなしで安全

結論: 競合ではなく補完関係。学習済みモデルはsafetensorsで配布し、ローカル推論にはGGUFに変換して使う、というのが現在の主流ワークフローだ。

基本概念が理解できたところで、実際にコードを書いて動かしてみよう。


5. 実践:実際に使ってみよう

5.1 環境構築

# llama.cppのインストール(brew経由が最も簡単)
brew install llama.cpp

# または手動ビルド(GPU対応したい場合)
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build -DGGML_CUDA=ON  # NVIDIA GPU有効化
cmake --build build --config Release

# Python変換ツールの依存パッケージ
pip install -r requirements.txt

Windows環境の場合: Visual Studio 2022のC++ビルドツールが必要。cmake -G "Visual Studio 17 2022" -A x64 -DGGML_CUDA=ON -B build でビルドする。

5.2 環境別の設定ファイル

開発環境用(config.yaml)

# config.yaml - 開発環境用
project:
  name: "gguf-local-llm"

environment: development

llama_cpp:
  binary_path: "./llama.cpp/build/bin"
  model_dir: "./models"

inference:
  n_gpu_layers: 0            # 開発時はCPUで
  context_length: 2048       # 小さめ
  threads: 4
  batch_size: 512
  temperature: 0.7
  repeat_penalty: 1.1

quantization:
  default_type: "Q8_0"      # 開発時は高品質で

本番環境用(config.production.yaml)

# config.production.yaml - 本番環境用
project:
  name: "gguf-local-llm"

environment: production

llama_cpp:
  binary_path: "/usr/local/bin"
  model_dir: "/opt/models"

inference:
  n_gpu_layers: -1           # 全層GPUオフロード
  context_length: 8192       # 長いコンテキスト
  threads: 8
  batch_size: 2048
  temperature: 0.7
  repeat_penalty: 1.1

quantization:
  default_type: "Q4_K_M"    # バランス重視

テスト環境用(config.test.yaml)

# config.test.yaml - CI/CD用
project:
  name: "gguf-local-llm"

environment: test

llama_cpp:
  binary_path: "./llama.cpp/build/bin"
  model_dir: "./test_models"

inference:
  n_gpu_layers: 0
  context_length: 512        # 最小限
  threads: 2
  batch_size: 128
  temperature: 0.0           # 確定的出力
  seed: 42

quantization:
  default_type: "Q4_0"       # テストは最軽量で

5.3 基本的な使い方:モデルの変換と実行

# Step 1: HuggingFaceモデルをGGUF (FP16) に変換
python llama.cpp/convert_hf_to_gguf.py \
  meta-llama/Llama-3.2-3B-Instruct \
  --outtype f16 \
  --outfile models/llama3.2-3b-f16.gguf

# Step 2: 量子化(FP16 → Q4_K_M)
./llama.cpp/build/bin/llama-quantize \
  models/llama3.2-3b-f16.gguf \
  models/llama3.2-3b-q4km.gguf \
  Q4_K_M

# Step 3: 推論実行
llama-cli -m models/llama3.2-3b-q4km.gguf \
  -p "PyTorchとTensorFlowの違いを3行で説明してください。" \
  -n 256

# Step 4: OpenAI互換APIサーバーとして起動
llama-server -m models/llama3.2-3b-q4km.gguf --port 8080

5.4 Python経由でGGUFメタデータを読む

"""
GGUFファイルのメタデータ確認スクリプト
実行方法: pip install gguf && python inspect_gguf.py model.gguf
"""
import sys
from gguf import GGUFReader


def inspect_gguf(filepath: str):
    """GGUFファイルの中身を確認"""
    reader = GGUFReader(filepath)

    print(f"=== {filepath} ===\n")

    # メタデータ
    print("[メタデータ]")
    for field in reader.fields.values():
        if len(field.parts) > 0:
            name = field.name
            # 長すぎるデータ(トークナイザー語彙等)はスキップ
            if 'tokens' not in name and 'merges' not in name:
                print(f"  {name}")

    # テンソル情報
    print(f"\n[テンソル数: {len(reader.tensors)}]")
    for i, tensor in enumerate(reader.tensors[:5]):  # 先頭5個
        print(f"  {tensor.name}: shape={tensor.shape}, type={tensor.tensor_type.name}")
    if len(reader.tensors) > 5:
        print(f"  ... 他 {len(reader.tensors) - 5} テンソル")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("使い方: python inspect_gguf.py <model.gguf>")
        sys.exit(1)
    inspect_gguf(sys.argv[1])

5.5 よくあるエラーと対処法

エラー 原因 対処法
error: unknown model architecture llama.cppが対応していないアーキテクチャ llama.cppを最新版に更新。対応アーキテクチャは頻繁に追加される
CUDA error: out of memory GPUオフロード層が多すぎる -ngl の値を減らしてCPUとの分担を調整
failed to load model GGUFバージョン不一致 llama.cppとGGUFファイルのバージョンを合わせる。古いGGMLファイルは再変換が必要
token not found トークナイザーの不整合 変換元モデルのtokenizer_config.jsonを確認
cmake: command not found ビルドツール未インストール apt install cmake(Linux)or brew install cmake(Mac)
Windows: 'cl' is not recognized MSVCが未設定 Visual Studio Installerで「C++によるデスクトップ開発」を追加

5.6 環境診断スクリプト

#!/usr/bin/env python3
"""
GGUF/llama.cpp環境診断スクリプト
実行方法: python check_gguf_env.py
"""
import shutil
import subprocess
import sys


def check_environment():
    """GGUF関連の環境をチェック"""
    issues = []
    info = []

    info.append(f"Python: {sys.version_info.major}.{sys.version_info.minor}")

    # cmake確認
    if shutil.which("cmake"):
        result = subprocess.run(["cmake", "--version"], capture_output=True, text=True)
        version = result.stdout.split("\n")[0] if result.stdout else "不明"
        info.append(f"cmake: {version}")
    else:
        issues.append("cmakeが見つかりません(llama.cppのビルドに必要)")

    # llama-cli確認
    for cmd in ["llama-cli", "llama-server", "llama-quantize"]:
        if shutil.which(cmd):
            info.append(f"{cmd}: 利用可能")
        else:
            issues.append(f"{cmd}が見つかりません")

    # gguf Pythonパッケージ
    try:
        import gguf
        info.append("gguf (Python): インストール済み")
    except ImportError:
        issues.append("gguf Pythonパッケージ未インストール: pip install gguf")

    # GPU確認
    try:
        result = subprocess.run(["nvidia-smi", "--query-gpu=name,memory.total",
                                 "--format=csv,noheader"], capture_output=True, text=True)
        if result.returncode == 0:
            for line in result.stdout.strip().split("\n"):
                info.append(f"GPU: {line.strip()}")
    except FileNotFoundError:
        info.append("NVIDIA GPU: 未検出(CPU推論は可能)")

    # 結果出力
    print("=" * 50)
    print(" GGUF / llama.cpp 環境診断レポート")
    print("=" * 50)
    print("\n[環境情報]")
    for item in info:
        print(f"  {item}")
    if issues:
        print(f"\n[問題点: {len(issues)}件]")
        for issue in issues:
            print(f"  - {issue}")
    else:
        print("\n  環境は正常です!")
    print("=" * 50)


if __name__ == "__main__":
    check_environment()

実装方法がわかったので、次は具体的なユースケースを見ていこう。


6. ユースケース別ガイド

6.1 ユースケース1: Ollamaでお手軽ローカルLLM

想定読者: コマンド一発でローカルLLMを試したい方

推奨構成: Ollama(内部的にllama.cpp + GGUF)

サンプルコード:

# Ollamaのインストール後
ollama run llama3.2:3b

# カスタムGGUFモデルを使う場合
cat > Modelfile << 'EOF'
FROM ./my_model-q4km.gguf
PARAMETER temperature 0.7
PARAMETER num_ctx 4096
SYSTEM "あなたは有能な日本語アシスタントです。"
EOF

ollama create my-model -f Modelfile
ollama run my-model
"""Ollama Python APIでの利用"""
import requests
import json

response = requests.post("http://localhost:11434/api/generate", json={
    "model": "llama3.2:3b",
    "prompt": "GGUFとは何かを一言で説明してください。",
    "stream": False
})
print(json.loads(response.text)["response"])

6.2 ユースケース2: OpenAI互換APIサーバー構築

想定読者: 既存のOpenAI APIコードをローカルLLMに切り替えたい方

推奨構成: llama-server + OpenAI Python SDK

サンプルコード:

# サーバー起動
llama-server \
  -m models/llama3.2-3b-q4km.gguf \
  --port 8080 \
  --host 0.0.0.0 \
  -ngl -1
"""OpenAI SDKで透過的にローカルLLMを使う"""
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8080/v1",
    api_key="not-needed"  # ローカルなので不要
)

response = client.chat.completions.create(
    model="local-model",
    messages=[
        {"role": "system", "content": "簡潔に回答してください。"},
        {"role": "user", "content": "GGUFファイルの利点を3つ教えて。"}
    ],
    temperature=0.7
)
print(response.choices[0].message.content)

6.3 ユースケース3: 用途別の量子化タイプ選択

想定読者: プロジェクトの制約に合わせて最適な量子化を選びたい方

選択ガイド:

"""量子化タイプ選択ヘルパー"""

QUANT_GUIDE = {
    "VRAM_4GB": {
        "recommended": "Q3_K_S",
        "reason": "4GB GPUでは3bit量子化がほぼ唯一の選択肢",
        "7b_size": "~3.2GB"
    },
    "VRAM_8GB": {
        "recommended": "Q4_K_M",
        "reason": "最も人気のバランス型。8GB GPUで7Bモデルが快適に動く",
        "7b_size": "~4.1GB"
    },
    "VRAM_16GB": {
        "recommended": "Q6_K",
        "reason": "余裕があるなら品質重視。Q8_0も選択可能",
        "7b_size": "~5.9GB"
    },
    "VRAM_24GB_PLUS": {
        "recommended": "Q8_0",
        "reason": "ほぼ無劣化。品質最優先の場合はF16も",
        "7b_size": "~7.2GB"
    },
    "CPU_ONLY": {
        "recommended": "Q4_K_M",
        "reason": "CPU推論でもQ4_K_Mはバランスが良い。RAMに注意",
        "7b_size": "~4.1GB"
    }
}

def suggest_quantization(vram_gb: float = 0, cpu_only: bool = False):
    """VRAM容量に応じた量子化タイプを推奨"""
    if cpu_only:
        key = "CPU_ONLY"
    elif vram_gb >= 24:
        key = "VRAM_24GB_PLUS"
    elif vram_gb >= 16:
        key = "VRAM_16GB"
    elif vram_gb >= 8:
        key = "VRAM_8GB"
    else:
        key = "VRAM_4GB"

    rec = QUANT_GUIDE[key]
    print(f"推奨: {rec['recommended']}")
    print(f"理由: {rec['reason']}")
    print(f"7Bモデルサイズ目安: {rec['7b_size']}")
    return rec["recommended"]


if __name__ == "__main__":
    print("=== VRAM 8GB の場合 ===")
    suggest_quantization(vram_gb=8)
    print("\n=== CPU のみの場合 ===")
    suggest_quantization(cpu_only=True)

ユースケースを把握できたところで、この先の学習パスを確認しよう。


7. 学習ロードマップ

初級者向け(まずはここから)

  1. Ollamaでローカルモデルを動かしてみる - GGUF意識せず体験できる
  2. HuggingFace GGUF docs - GGUFの全体像を掴む
  3. GGUF-my-repo で好きなモデルをワンクリックGGUF変換してみる

中級者向け(実践に進む)

  1. llama.cpp公式リポジトリ のREADMEを通読する
  2. 自分でHuggingFaceモデル→FP16→Q4_K_Mの変換パイプラインを構築する
  3. llama-server でOpenAI互換APIを立て、既存アプリケーションと接続する

上級者向け(さらに深く)

  1. GGUF仕様書(gguf-py) でバイナリフォーマットの詳細を読む
  2. K-Quant方式のアルゴリズムを理解する
  3. カスタムアーキテクチャのGGUF対応(convert_hf_to_gguf.py への貢献)

8. まとめ

この記事では、GGUFについて以下を解説した。

  1. GGUFの正体 - llama.cpp発の「全部入り」モデルフォーマット。メタデータ・トークナイザー・量子化重みを1ファイルに格納
  2. 量子化タイプの仕組み - Q4_K_MのQ/K/Mの意味と、VRAM容量別の選択指針
  3. 実践的な使い方 - 変換・量子化・推論・API化まで

私の所感

GGUFの本当の功績は「ローカルLLMの民主化」だと思う。

70Bのモデルが140GBから35GBに縮み、さらにCPU+GPUのハイブリッド推論で動く。これはGGUFとllama.cppの組み合わせがなければ実現しなかった世界だ。

「Q4_K_Mを選べ」は、もはやローカルLLMの合言葉になっている。でも、その背後にある「テンソルの重要度に応じてビット数を変える」という賢い設計思想を知ると、ただダウンロードして使うだけでは得られない理解が生まれる。

safetensorsが「安全な保存」を、GGUFが「効率的な推論」を担当する。この2つのフォーマットを理解しておけば、OSS系AI利用者として一段上のステージに行けるはずだ。


参考文献

7
7
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
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?