🧶

llama.cpp用言語モデルファイル「GGUF」の作り方

2024/06/07に公開

GGUFとは?

ご家庭のローカルマシンのCPUでLLMを動作させるのに大変重宝されている「llama.cpp」であるが、残念ながらHuggingFaceを介したモデル配布で一般的な「safetensors」形式のモデルを直接読み込むことはできない。
そのため、safetensors形式で配布されている言語モデルをllama.cppで扱いたいならば、独自のフォーマットである「GGUF」形式への変換作業が必要だ。
その具体的な手順について本記事では解説する。

手順

Step0. gitの準備

一連の手順で複数回gitコマンドを使用するので、gitコマンドに関してはあらかじめ使用可能な状態にしておいてほしい。

Step1. llama.cppのクローン

まだllama.cppをクローンしていない場合は、git clone https://github.com/ggerganov/llama.cpp.gitで適当なディレクトリにクローンしておこう。
なお、筆者の検証によると、llama.cppをクローンしたフォルダにもある程度(モデルファイルが丸々乗るくらい?)の空き容量が必要なようだ。仮想メモリとして使用するためだろうか?

Step2. モデルのクローン

使いたい言語モデルをクローンする。HuggingFace(大抵のモデルは配布先へ向かおうとすると、ここに誘導されるのではなかろうか?)の右上の、点が縦に三つ並んでいる場所を押すと「Clone repository」というボタンが出現するので、これを使ってコマンドをコピペすると便利である。
大抵の言語モデルのファイルは容量が非常に大きいため、空き容量に余裕のあるストレージ上でcloneコマンドを使おう。

Step3. 変換

llama.cppの中に「convert-hf-to-gguf.py」というファイルがあるので、これを使ってフォーマットの変換を行う。
使い方は簡単で、python .\convert-hf-to-gguf.py さっき落としてきたモデルのディレクトリ
また、--outtype引数でgguf変換後のデータ型を指定できる。選べるのはf32、f16、bf16、q8_0の4通り。デフォルトでモデルと同じものを選んでくれるような機能はないので、精度劣化を防ぐために人間が手動でモデルと同じデータ型を選択しておくことを推奨する
(なお、元モデルのデータ型に関しては「config.json」ファイルの「torch_dtype」の項に記載があるので、わからない場合はそれを活用しよう。)

念のため例を挙げておこう。
モデル「llama.cpp」と「Meta-Llama-3-70B-Instruct」を、どちらも「パブリックのダウンロード」ディレクトリにクローンしたとしよう。「Meta-Llama-3-70B-Instruct」のデータ型はbfloat16だ。

この場合に行うべきは
①まず、「convert-hf-to-gguf.py」の位置する「llama.cpp」ディレクトリに移動し
②次いでこれに適切な引数を渡して起動する
ことだ

つまり、打つべきコマンドは

cd C:\Users\Public\Downloads\llama.cpp
python .\convert-hf-to-gguf.py "C:\Users\Public\Downloads\Meta-Llama-3-70B-Instruct" --outtype bf16

となる。

ちなみに、やや古めの解説サイトには「convert.py」を使うと書かれている場合もある。しかしこれは2024年6月現在deplicate扱いになっているようなので、筆者としては非推奨とさせて頂きたい。

変換作業は以上になります。お疲れさまでした!

トラブルシューティング

変換時にこんな警告が出現したとき

WARNING:hf-to-gguf:**************************************************************************************
WARNING:hf-to-gguf:** WARNING: The BPE pre-tokenizer was not recognized!
WARNING:hf-to-gguf:**          There are 2 possible reasons for this:
WARNING:hf-to-gguf:**          - the model has not been added to convert-hf-to-gguf-update.py yet
WARNING:hf-to-gguf:**          - the pre-tokenization config has changed upstream
WARNING:hf-to-gguf:**          Check your model files and convert-hf-to-gguf-update.py and update them accordingly.
WARNING:hf-to-gguf:** ref:     https://github.com/ggerganov/llama.cpp/pull/6920
WARNING:hf-to-gguf:**
WARNING:hf-to-gguf:** chkhsh:  138464fe047387634a556333c3c5b3e426d010814f99c78f43019b930168b3ee
WARNING:hf-to-gguf:**************************************************************************************
WARNING:hf-to-gguf:

(途中省略)

    raise NotImplementedError("BPE pre-tokenizer was not recognized - update get_vocab_base_pre()")
NotImplementedError: BPE pre-tokenizer was not recognized - update get_vocab_base_pre()

このエラーは、llama.cppがこのモデル固有のpre-tokenization機能(≒前処理)に対応していないので変換できませんよ~、という意味。

どうしてもそのモデルを使いたいのならば、この警告が実装される以前の古いバージョンのconvert-hf-to-gguf.pyを使えばエラーを素通りできる。

ただしその場合でも、推論時に下のような警告が出てしまう。

llm_load_vocab: missing pre-tokenizer type, using: 'default'
llm_load_vocab:                                             
llm_load_vocab: ************************************        
llm_load_vocab: GENERATION QUALITY WILL BE DEGRADED!        
llm_load_vocab: CONSIDER REGENERATING THE MODEL             
llm_load_vocab: ************************************        
llm_load_vocab:

これは、「このモデル固有のpre-tokenization処理がllama.cppに実装されていないので、前処理はテキトーに(他のメジャーなモデルの処理を流用して)やっておきますよ~、なのでもしかしたら精度が落ちてしまっているかもしれません」という警告。これを解決するには実際にそのモデル固有の前処理を実装する必要があるため、完全解決は困難と思われる。
私の調査が正しければ、インターネット上で配布されている少なくない数のGGUFファイルがこの精度劣化の影響を受けている可能性もある

次回予告

GGUFモデルの量子化

Discussion