Hugging FaceのLLMモデルをGGUFに変換してOllamaで動かすまでの備忘録
Hugging Faceで公開されているLLMモデルは、Safetensors形式がち
yuseiito.icon自身はエーアイにはあまり詳しくないので、Geminiに尋ねながらやって、とりあえず動いたので、履歴をまとめる。
対象モデルは tokyotech-llm/Qwen3-Swallow-30B-A3B-RL-v0.2 を例とする。
どのハードで変換作業をやるか
基本的には、メモリの大きくてストレージに余裕のあるUnified Memoryのマシンが良いと思う。
30Bクラスのモデルを変換する場合、一時的に以下のディスクスペースが必要となる。
元モデルデータ: 約60GB
F16(非量子化)GGUF中間ファイル: 約60GB
量子化後モデル (例: Q4_K_M): 約18GB
合計: 約140GB
パフォーマンスの注意点:
F16 GGUFへの変換処理: 計算は比較的単純で、I/O boundな処理. 結構な容量なので安いHDDとかで作業したくなるが、内臓または外付けのNVMe SSDを作業領域にしないと待ち時間で日が暮れる
量子化処理: 行列演算による圧縮を行うため CPU / Memory bound な処理なので、Mac Studio (M1 Max) 等の環境ではプロセッサとユニファイドメモリの恩恵で高速に処理される。
作業手順
作業用のディレクトリを作成し、以下の手順を順に実行する。
Step 1: 元モデルのダウンロード
Hugging Face CLIでダウンロードする.
code:bash
# カレントディレクトリの 'Qwen3-Swallow' フォルダに保存
hf download tokyotech-llm/Qwen3-Swallow-30B-A3B-RL-v0.2 --local-dir Qwen3-Swallow
Step 2: llama.cpp のビルド
古い情報を見るとGNU Makeを使うようになっているが、現在、llama.cpp のビルドはCMakeが標準となっている模様。
code:bash
cd llama.cpp
cmake -B build
cmake --build build --config Release
※ 筆者の作業時にはtag "b8144" のコミットを利用した。
Step 3: Python環境の構築 (uvを利用)
b8144 tag 時点での llama.cpp では、依存関係のインストール時に、PyTorchのバージョン制約やDependency Confusion防止機能によるエラーを回避するため、単にuv pip install ではダメで、以下のオプションが必要だった
code:bash
uv venv
uv pip install -r requirements.txt --index-strategy unsafe-best-match --prerelease allow
どうやらllama.cppはpoetryを使うようになっているみたいなので、poetryにしておけばもう少し楽なのかもしれないが、未検証 Step 4: GGUF (F16) への変換
ダウンロードしたモデルを16bit浮動小数点のGGUFに変換する。
code:bash
uv run python convert_hf_to_gguf.py ../Qwen3-Swallow \
--outfile ../Qwen3-Swallow-30B-A3B-RL-v0.2-F16.gguf \
--outtype f16
Step 5: モデルの量子化
実用的なサイズ(ここでは Q4_K_M)へ量子化する。
量子化レベルは Q8_0 と Q4_K_M あたりが用意されていれば多くのモデルでは十分な気がするけど、よくわかってない。
モデル依存な気がする
code:bash
./build/bin/llama-quantize \
../Qwen3-Swallow-30B-A3B-RL-v0.2-F16.gguf \
../Qwen3-Swallow-30B-A3B-RL-v0.2-Q4_K_M.gguf \
Q4_K_M
Step 6: Hugging Faceに公開する
必須ではないけど、せっかく変換モデルを作ったのであれば、後に続く人のために公開しておくと良いと思う。
publicにしておけば、無料のストレージとしてちょうどいいし。
code:bash
huggingface-cli login # 初回のみ
# 指定したリポジトリへアップロード (your-usernameは自身のアカウント名に変更)
huggingface-cli upload your-username/Qwen3-Swallow-30B-A3B-RL-v0.2-GGUF \
../Qwen3-Swallow-30B-A3B-RL-v0.2-Q4_K_M.gguf \
--commit-message "Add Q4_K_M quantized GGUF model"
Step 7: モデルカードの準備
派生モデルを公開する際は、README.md に以下の記述を含める。
YAMLフロントマターでのライセンス指定 (例: license: apache-2.0)
元モデルへのリンクとクレジット表記
変更内容(GGUF変換と量子化を行った旨)の明記 (← 元のモデルがApache License 2.0 の場合必須)
元リポジトリの LICENSE ファイル等の同梱
変換したモデルをOllamaから使う
A. ローカルの生成済みファイルを利用する(変換作業をやったマシンで)
すでに手元にGGUFファイルがある場合、いちいちHugging Faceを経由する意味はないので、直接指定すればよい。
Modelfile を作成し、ローカルのパスを指定する。
code:Modelfile
# Modelfile
FROM ./Qwen3-Swallow-30B-A3B-RL-v0.2-Q4_K_M.gguf
※ 最近の llama.cpp で変換されたGGUFには、ChatMLの TEMPLATE やデフォルトのシステムプロンプトがメタデータとして埋め込まれているため、Ollama側で明示的に定義しなくても正常にフォーマットが解釈されることが多いようです。
yuseiito.iconはそのあたりがどういう仕組みなのかよくわかってない。
登録と実行:
code:bash
ollama create qwen3-swallow-30b -f Modelfile
ollama run qwen3-swallow-30b
B. Hugging Faceから直接Pullする(別のマシンや他のユーザから)
OllamaはHugging Face Hubからの直接取得をサポートしている
リポジトリのURLの末尾に、利用したい量子化ファイルのタグ(ファイル名の .gguf を除いた部分)を指定する。
code:bash
ollama run hf.co/your-username/Qwen3-Swallow-30B-A3B-RL-v0.2-GGUF:Q4_K_M