2026年5月1日金曜日

.safetensorsのggufへの変換

一般的なllmであれば、llama.cppのconvert_hf_to_gguf.pyが一番なのは間違いなさそうですが、実際にやりたいのはstable-diffusionで使用するclipなんとかとか、t5なんとかの.safetensorsで正直中身がどうなってるのか良く分かってない。

gguf形式になった原因は単独で.safetensorsファイルだけでは実際に使用することができないために、付随情報もひとまとめにしたものということは認識している。逆に付加情報を正確に付加させなければ、目的のggufが作れないという事でもあるわけで…その付加情報があったとしても、実際に.safetensorsにどのように結合させてggufにするんだ?という…なんかもう先が見えない状態が結構続きました。 

で、いろいろ調べてみたり試した結果、行き着いたのがstable-diffusion.cppのcliでconvertをかける方法。

確かに、stable-diffusion.cppは.safetensorsだろうがggufだろうがそれなりに読み込んでいる感じで動いてくれている。なので、読み込んだ状態を書き出すだけなので、確かにこれならうまくいきそう。

決め手だったのが、使用していたstablediffusion3.5の.gguf群のreadme.mdファイルの最後に

「**Quantized with stable-diffusion.cpp `master-ac54e00`.**」

と、記載されていたのが決定打となりました。

なので、さっそくmakeしました。特に速度は気にしないのでcpuビルドで。

さっそく変換をしてみようと思いましたが、ここからまた上手く検索で引っかからない。ドキュメントを見るとパラメータの説明があるもののこれまた良く分からない。何となくもう少しでいけそうなので…ソースをちょっと追っかけてみることに。

sd-cli側のmain.cppではパラメータを取り込んで、本体のconvertを呼び出しています。 

bool success = convert(ctx_params.model_path.c_str(),
                       ctx_params.vae_path.c_str(),
                       cli_params.output_path.c_str(),
                       ctx_params.wtype,
                       ctx_params.tensor_type_rules.c_str(),
                       cli_params.convert_name);

必要なパラメータは大体なんとなくわかっていたわけですが、なんかちらほらとconvert_nameと言うのがbool値ってなってるのが意味不明(笑)名前指定じゃないんかいw

bool convert(const char* input_path,
             const char* vae_path,
             const char* output_path,
             sd_type_t output_type,
             const char* tensor_type_rules,
             bool convert_name) { 

で、本体側の受ける口はこんな感じ。はぁ…bool値確定…wまぁほかのはそれなりに行けそうなのと、vaeはとりあえず関係なさそうなので無視する方向で…こんな感じで実行してみました。

~/stable-diffusion.cpp/build/bin$ ./sd-cli --mode convert --model /usr/share/local-ai/models/image/input.safetensors --convert-name --type q8_0 --output /usr/share/local-ai/models/image/output_Q8_0.gguf

ディレクトリがちょっと深いので長いですが、入力の.safetensorsのファイル名と、出力のファイル名、あとconvert-nameのフラグとtype q8_0の指定のみですね…結果としてconvert-nameはいらないんじゃないかとか、出力の指定も…まぁ良く分かりませんが、試したところいい感じで動いてはくれるようになりました。

これだけで何も考えずにclipなんとかとか、t5なんとかの.safetensorsのファイルが見事ggufになってくれました。

ちなみに、ふつう量子化は個別に行うのが一般的で、最初はBF16とかFP16にしておくのがよろしいようです。

.safetensorsファイルが分割されている場合、stable-diffusion.cppでは扱えないので、別途結合させる必要があります。最初バイナリファイルよろしく、catで結合させましたがダメでした(笑)順番を入れ替えれば行けたかもとか感じたりしなくもないですが、

  https://note.com/gentle_murre488/n/n25c3088ae1b3

にザックリとpythonで結合させるスクリプトを載せてくれているので参考にするといいかもしれません。上記は2つですが3つでも同様に一気にいけました。まぁパイトーチとか必要になりますが…cpuで動かす環境なら無理なく作れるでしょう…。

そしてなんかできたものが…

いつものfish画像ですが、なんかちょっと画像がざらついてる気がするなぁ…

そもそも何でこんなことをやったかと言うと、メモリ16GBだとぎりぎり動きそうだったのですが、swapファイルをSSDに乗せたくないので、どうしてもなぁ…ということでやり始めたのがきっかけだったりします(笑) 

0 件のコメント:

コメントを投稿