0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

科学と神々株式会社アドベントカレンダー 2025

LLM量子化 Day 12: 出力の検証

「できた」だけでは不十分

量子化処理が終わり、ファイルが生成された。しかし、それで本当に「成功」と言えるでしょうか?

  • ファイルが途中で切れていないか?
  • 正しいGGUF形式になっているか?
  • 実際にllama.cppで読み込めるか?

これらを確認するのが「検証」です。

検証が必要なシナリオ

よくある問題

1. ディスク容量不足
   → ファイルが途中で切れる
   → 開こうとするとクラッシュ

2. 変換中のエラー
   → 不完全なGGUF構造
   → 一部のテンソルが欠落

3. 電源断・強制終了
   → ファイル破損
   → メタデータの不整合

これらの問題は、ファイルが「存在する」だけでは検出できません。

検証の階層

llm-quantizeは、複数の検証レベルを提供します:

検証レベル:
├── Level 1: 存在確認
│   └── ファイルが存在するか
│
├── Level 2: 形式確認
│   ├── 拡張子が正しいか
│   ├── ファイルサイズが0でないか
│   └── マジックバイトが正しいか
│
└── Level 3: 構造確認(将来拡張)
    ├── バージョン番号が有効か
    ├── テンソル数が妥当か
    └── メタデータが読み込めるか

検証結果の表現

検証結果は、シンプルなデータ構造で表現されます:

@dataclass
class ValidationResult:
    is_valid: bool           # 検証に成功したか
    error_message: str = ""  # エラーの詳細(失敗時のみ)

    @classmethod
    def valid(cls):
        """検証成功を表す"""
        return cls(is_valid=True)

    @classmethod
    def invalid(cls, message: str):
        """検証失敗を表す"""
        return cls(is_valid=False, error_message=message)

使用例:

# 検証成功
result = ValidationResult.valid()
print(result.is_valid)  # True

# 検証失敗
result = ValidationResult.invalid("ファイルが空です")
print(result.is_valid)       # False
print(result.error_message)  # "ファイルが空です"

GGUF固有の検証

GGUFファイルには特有の検証ポイントがあります:

1. ファイル形式の確認

def _validate_gguf(path: Path) -> ValidationResult:
    # ファイルであることを確認(ディレクトリではない)
    if not path.is_file():
        return ValidationResult.invalid(f"Must be a file: {path}")

    # 拡張子の確認
    if path.suffix.lower() != ".gguf":
        return ValidationResult.invalid(f"Must have .gguf extension: {path}")

2. ファイルサイズの確認

    # 空ファイルでないことを確認
    file_size = path.stat().st_size
    if file_size == 0:
        return ValidationResult.invalid(f"File is empty: {path}")

3. マジックバイトの確認

GGUFファイルの最初の4バイトは必ず「GGUF」(0x47475546)です:

    # マジックバイトの確認
    with open(path, "rb") as f:
        magic = f.read(4)
        if magic != b"GGUF":
            return ValidationResult.invalid(
                f"Invalid magic bytes: {magic!r}, expected b'GGUF'"
            )

    return ValidationResult.valid()

なぜマジックバイトが重要か

マジックバイト(ファイルシグネチャ)は、ファイル形式を識別するための「指紋」です。

ファイル形式とマジックバイト:
├── GGUF: "GGUF" (0x47 0x47 0x55 0x46)
├── PNG:  0x89 0x50 0x4E 0x47
├── PDF:  "%PDF"
└── ZIP:  "PK" (0x50 0x4B)

マジックバイトを確認することで、以下の問題を検出できます:

  • 拡張子だけ変えた別形式のファイル
  • 完全に破損したファイル
  • 意図しない上書き

検証ステータスの追跡

量子化結果には、検証状態が記録されます:

class ValidationStatus(Enum):
    VALID = "valid"         # 検証成功
    INVALID = "invalid"     # 検証失敗
    UNCHECKED = "unchecked" # 未検証

状態遷移

量子化直後:
  status = UNCHECKED
      │
      ▼ 検証実行
      │
  ├── 成功 → status = VALID
  │
  └── 失敗 → status = INVALID
              error_message = "詳細なエラー情報"

検証のタイミング

検証はいつ行うべきでしょうか?

量子化完了直後(推奨)

result = quantizer.quantize()
result = update_validation_status(result, OutputFormat.GGUF)

if result.validation_status == ValidationStatus.INVALID:
    print(f"警告: 検証に失敗しました")

使用前

# 既存のGGUFファイルを使う前に
result = validate_output("model.gguf", "gguf")
if not result.is_valid:
    print(f"エラー: {result.error_message}")
    sys.exit(1)

CLIでの検証統合

llm-quantizeでは、量子化完了時に自動的に検証が行われます:

$ llm-quantize quantize model gguf -q Q4_K_M

Quantizing to GGUF Q4_K_M...
[████████████████████████████████] 100%

✓ Quantization complete
✓ Validation passed

Output: model-Q4_K_M.gguf
Size: 4.0 GB
Compression: 72%

検証に失敗した場合:

$ llm-quantize quantize model gguf -q Q4_K_M

Quantizing to GGUF Q4_K_M...
[████████████████████████████████] 100%

✓ Quantization complete
✗ Validation failed: Invalid GGUF magic bytes: b'\x00\x00\x00\x00'

Warning: The output file may be corrupted.

検証の限界

現在の検証は「ファイルとして正しいか」を確認します。しかし、以下は確認できません:

  • 品質: 量子化後のモデルの推論品質
  • 完全性: すべてのテンソルが正しく量子化されているか
  • 互換性: 特定のllama.cppバージョンで動作するか

より深い検証を行うには、実際にモデルを読み込んで推論を試す必要があります。

Tips: 検証のベストプラクティス

自動検証を有効にする

量子化後は必ず検証を行いましょう。llm-quantizeではデフォルトで有効です。

検証失敗時の対処

1. ディスク空き容量を確認
   df -h

2. 量子化をやり直す
   rm model-Q4_K_M.gguf
   llm-quantize quantize model gguf -q Q4_K_M

3. それでも失敗する場合
   - 別の量子化レベルを試す
   - llama.cppを最新版に更新
   - モデルの互換性を確認

手動での検証

GGUFファイルを手動で確認するには:

# マジックバイトを確認
xxd -l 4 model.gguf
# 出力: 00000000: 4747 5546  GGUF

# ファイルサイズを確認
ls -lh model.gguf
# 出力: -rw-r--r--  1 user  staff   4.0G Dec 12 12:00 model.gguf

# llama.cppで読み込みを試す
llama-cli -m model.gguf -p "Hello" -n 10

次回予告

Day 13からは「AWQ/GPTQ形式編」として、GPU推論に最適化された量子化形式について6日間にわたって解説します。


「信頼するが検証せよ(Trust, but verify)」——これはソフトウェア開発の基本原則です。自分の書いたコードも、外部ツールの出力も、必ず検証しましょう。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?