HuggingFace Model (Llama 3 Youko 8B) を GGUF に変換して、ollama で実行する

May 18, 2024, 12:09 PM

概要

普段、ollama でLLMを使用しています。
ollama は、gguf 形式のモデルに対応しているため、その他の形式の場合は、gguf 形式に変換する必要があります。
今回は、rinna 社さんの Llama 3 Youko 8B を gguf 形式に変換して ollama で実行してみます。

LLMのモデルについて

  • ベースモデル (Base Model)
    これは通常、学習を行うための初期状態のモデルを指します。このモデルは特定のタスクに特化する前の、一般的な知識や機能を学んでいます。たとえば、言語モデルでは広範なテキストデータを用いて事前学習されます。ユーザーが与えた文章の続きを書いてくれるイメージです。
  • インストラクトモデル (Instruct Model)
    インストラクトモデルは、より具体的な指示に従うために調整されたモデルです。これは、ベースモデルをベースにさらに訓練を重ね、特定の指示や要求に基づいて行動するよう最適化されています。例えば、ユーザーからの具体的な要求に答えることができるように訓練されたモデルです。
  • チャットモデル (Chat Model)
    チャットモデルは、テキストベースの対話を生成するために特化されたモデルです。これは、自然な会話を模倣するように設計されており、ユーザーの質問に対する回答を生成することができます。このタイプのモデルは、カスタマーサポートの自動応答や仮想アシスタントなどに使用されます。

現時点において、おおきく、この3つのモデルが存在します。
今回は使用するモデル Llama 3 Youko 8B は、ベースモデルです。

llama.cpp をインストールする

今回は、M1 Mac で行っています。

llama.cpp のインストール

$ cd
$ mkdir convert_gguf
$ cd convert_gguf
$ pipenv shell
$ git clone https://github.com/ggerganov/llama.cpp
Cloning into 'llama.cpp'...
remote: Enumerating objects: 24808, done.
remote: Counting objects: 100% (7812/7812), done.
remote: Compressing objects: 100% (418/418), done.
remote: Total 24808 (delta 7601), reused 7445 (delta 7393), pack-reused 16996
Receiving objects: 100% (24808/24808), 43.73 MiB | 14.52 MiB/s, done.
Resolving deltas: 100% (17620/17620), done.

$ pipenv install -r llama.cpp/requirements.txt
Requirements file provided! Importing into Pipfile...
Pipfile.lock not found, creating...
:
Updated Pipfile.lock (2277a4b95fd870f296e0e79787119e98d55880b284a3aa13a4c670d481cd62a2)!
Installing dependencies from Pipfile.lock (cd62a2)...

$ python llama.cpp/convert.py -h
usage: convert.py [-h] [--dump] [--dump-single] [--vocab-only] [--no-vocab] [--outtype {f32,f16,q8_0}] [--vocab-dir VOCAB_DIR]
[--vocab-type VOCAB_TYPE] [--outfile OUTFILE] [--ctx CTX] [--concurrency CONCURRENCY] [--big-endian] [--pad-vocab]
[--skip-unknown] [--verbose] [--metadata METADATA] [--get-outfile]
model

Convert a LLaMA model to a GGML compatible file

positional arguments:
model directory containing model file, or model file itself (*.pth, *.pt, *.bin)

options:
-h, --help show this help message and exit
--dump don't convert, just show what's in the model
--dump-single don't convert, just show what's in a single model file
--vocab-only extract only the vocab
--no-vocab store model without the vocab
--outtype {f32,f16,q8_0}
output format - note: q8_0 may be very slow (default: f16 or f32 based on input)
--vocab-dir VOCAB_DIR
directory containing tokenizer.model, if separate from model file
--vocab-type VOCAB_TYPE
vocab types to try in order, choose from 'spm', 'bpe', 'hfft' (default: spm,hfft)
--outfile OUTFILE path to write to; default: based on input
--ctx CTX model training context (default: based on input)
--concurrency CONCURRENCY
concurrency used for conversion (default: 8)
--big-endian model is executed on big endian machine
--pad-vocab add pad tokens when model vocab expects more than tokenizer metadata provides
--skip-unknown skip unknown tensor names instead of failing
--verbose increase output verbosity
--metadata METADATA Specify the path for a metadata file
--get-outfile get calculated default outfile name

huggingface-hub のインストール

上記の続き カレントディレクトリ=~/convert_gguf
$ pipenv install huggingface_hub
Installing huggingface_hub...
Resolving huggingface_hub...
Added huggingface-hub to Pipfile's [packages] ...
✔ Installation Succeeded
Pipfile.lock (cd62a2) out of date, updating to (f7d24b)...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success!
Locking [dev-packages] dependencies...
Updated Pipfile.lock (9f3f15e9907882bcdd1381820fddf00cb092400c46dcb0e126213803a2f7d24b)!
Installing dependencies from Pipfile.lock (f7d24b)...

モデルのダウンロード

上記の続き カレントディレクトリ=~/convert_gguf
$ nano download.py
以下の内容を貼り付ける
from huggingface_hub import snapshot_download
model_id="rinna/llama-3-youko-8b"
snapshot_download(repo_id=model_id, local_dir="rinna-hf",
local_dir_use_symlinks=False, revision="main")

ダウンロード実行
$ python ./download.py
ダウンロードが完了すると、rinna-hf というディレクトリに、モデルがダウンロードされています

確認
$ ls -lash rinna-hf
total 31458992
0 drwxr-xr-x 18 microai staff 576B 5 18 10:17 .
0 drwxr-xr-x 7 microai staff 224B 5 18 10:17 ..
8 -rw-r--r-- 1 microai staff 1.5K 5 18 10:12 .gitattributes
0 drwxr-xr-x 4 microai staff 128B 5 18 10:12 .huggingface
16 -rw-r--r-- 1 microai staff 7.6K 5 18 10:12 LICENSE
16 -rw-r--r-- 1 microai staff 4.0K 5 18 10:12 README.md
16 -rw-r--r-- 1 microai staff 4.6K 5 18 10:12 USE_POLICY.md
8 -rw-r--r-- 1 microai staff 649B 5 18 10:12 config.json
8 -rw-r--r-- 1 microai staff 121B 5 18 10:12 generation_config.json
9744384 -rw-r--r-- 1 microai staff 4.6G 5 18 10:17 model-00001-of-00004.safetensors
9777152 -rw-r--r-- 1 microai staff 4.7G 5 18 10:17 model-00002-of-00004.safetensors
9613312 -rw-r--r-- 1 microai staff 4.6G 5 18 10:17 model-00003-of-00004.safetensors
2306048 -rw-r--r-- 1 microai staff 1.1G 5 18 10:14 model-00004-of-00004.safetensors
48 -rw-r--r-- 1 microai staff 23K 5 18 10:12 model.safetensors.index.json
120 -rw-r--r-- 1 microai staff 59K 5 18 10:12 rinna.png
8 -rw-r--r-- 1 microai staff 73B 5 18 10:12 special_tokens_map.json
17744 -rw-r--r-- 1 microai staff 8.7M 5 18 10:12 tokenizer.json
104 -rw-r--r-- 1 microai staff 49K 5 18 10:12 tokenizer_config.json


モデルの変換(ステップ1)

一度、32ビットで量子化したものを、後に再度量子化します。
ステップを分けたほうが制度の高いモデルができあがるそうです。(ChatGPT 4o談)
$ python llama.cpp/convert.py rinna-hf \
--outfile llama-3-youko-8b-f16.gguf \
--outtype f16 --vocab-type bpe

INFO:convert:Loading model file rinna-hf/model-00001-of-00004.safetensors
INFO:convert:Loading model file rinna-hf/model-00001-of-00004.safetensors
INFO:convert:Loading model file rinna-hf/model-00002-of-00004.safetensors
:
INFO:convert:[290/291] Writing tensor blk.31.ffn_norm.weight | size 4096 | type F32 | T+ 47
INFO:convert:[291/291] Writing tensor output_norm.weight | size 4096 | type F32 | T+ 47
INFO:convert:Wrote llama-3-youko-8b-f16.gguf

outtype

量子化タイプを指定するオプション。以下の3つから指定可能で、今回は、f16を指定しました。

量子化
  • f32: 32ビット浮動小数点数(高精度、モデルサイズが大きい)
    • 30Gのモデルが出力されました
  • f16: 16ビット浮動小数点数(精度とサイズのバランスが良い)
    • 15Gのモデルが出力されました
  • q8_0: 8ビット量子化(サイズが小さく、精度も比較的高い)
    • 8.0Gのモデルが出力されました

vocab-type

llama3 ベースのものは、ボキャブラリ形式が BpeVocab とのこでbpeを指定しました。
なお、指定しない場合は以下のエラーが発生しました。
TypeError: Llama 3 must be converted with BpeVocab


モデルの変換(ステップ2)

llama.cpp のビルド

quantizeは、ビルドしないと使えないのでビルドします。
上記の続き カレントディレクトリ=~/convert_gguf
$ cd llama.cpp
$ make
I ccache not found. Consider installing it for faster compilation.
I llama.cpp build info:
I UNAME_S: Darwin
I UNAME_P: arm
I UNAME_M: arm64
:
% ls -la ./quantize
-rwxr-xr-x 1 microai staff 2446245 5 18 10:41 ./quantize
ビルド成功🍺

変換実行

$ cd ~/convert_gguf
$ llama.cpp/quantize llama-3-youko-8b-f16.gguf llama-3-youko-8b-f16-q4_K_M.gguf q4_K_M

main: build = 2918 (05834841)
main: built with Apple clang version 14.0.0 (clang-1400.0.29.202) for arm64-apple-darwin22.3.0
main: quantizing 'llama-3-youko-8b-f16.gguf' to 'llama-3-youko-8b-f16-q4_K_M.gguf' as Q4_K_M
:
main: quantize time = 114686.01 ms
main: total time = 114686.01 ms
問題なく変換できました🍺

指定できる量子化オプション

  • f32: 32ビット浮動小数点数。最高の精度を提供しますが、モデルサイズが非常に大きくなります。
    • おそらく意味がないので、実施せず
  • f16: 16ビット浮動小数点数。精度とメモリ使用量のバランスが取れています。
    • 15Gのモデルが出来上がりました
  • q8_0: 8ビット量子化。精度が高く、リソース使用量も多いですが、ほぼ f16 と同等の品質です。
    • 8.0Gのモデルが出来上がりました
  • q4_0: 4ビット量子化。メモリ効率が高いが、精度が低下します。
    • 4.3Gのモデルが出来上がりました
  • q4_1: 改良された 4 ビット量子化。q4_0 よりも精度が高いです。
    • 4.8Gのモデルが出来上がりました
  • q5_0: 5ビット量子化。q4_1 よりも高い精度とリソース使用量。
    • 5.2Gのモデルが出来上がりました
  • q5_1: より高精度な 5 ビット量子化。リソース使用量も増加します。
  • q4_k_s: 全てのテンソルに Q4_K を使用する量子化。
  • q4_k_m: バランスの取れた精度とメモリ効率を提供する Q4_K 量子化。多くのユーザーに推奨されます。
    • 4.6Gのモデルが出来上がりました
  • q5_k_s: 全てのテンソルに Q5_K を使用する量子化。
  • q5_k_m: Attention と Feed Forward テンソルの半分に Q6_K、残りに Q5_K を使用する量子化。高い精度を提供します。
    • 5.3Gのモデルが出来上がりました
  • q6_k: 全てのテンソルに Q6_K を使用する量子化。非常に高い精度とリソース使用量。

量子化のステップを分けるメリット・デメリット

  • ステップを分けた量子化:
    • メリット: 量子化の前に高精度な f32 フォーマットに変換することで、量子化の品質が向上する可能性があります。
    • デメリット: 手順が複雑で、変換時間が長くなる可能性があります。
  • 直接量子化:
    • メリット: 手順が簡略化され、時間が短縮されます。
    • デメリット: f32 フォーマットを経由する場合よりも量子化の品質が低くなる可能性があります。

ollama で使用するために ModelFile を作る

今回変換したモデルについて ollama が使えるように使い方等を教えてあげてつつ、ollama に食べさせます。
モデルの名前は・・・ollama-youko にします。

上記の続き カレントディレクトリ=~/convert_gguf
$ nano YoukoModelFile
以下を貼り付けて保存
FROM ./llama-3-youko-8b-f16-q4_K_M.gguf

TEMPLATE """[INST] {{ .System }}
{{ .Prompt }} [/INST]
"""
PARAMETER stop "[INST]"
PARAMETER stop "[/INST]"

$ ollama create ollama-youko -f YoukoModelFile

transferring model data
using existing layer sha256:d032948567857f311e2a31fd2cfdf49585c254459c3fbf13ceecece30ebf0f08
using existing layer sha256:eab35310d23a0d21382369b0f47613e8b2fdb83b694c266c1ecc7782df33e0c7
using existing layer sha256:ed11eda7790d05b49395598a42b155812b17e263214292f7b87d15e14003d337
using existing layer sha256:60758a3ab5acf3d166ff4db16cb7a6f99c27f43f9cc23e254df27016f1ebd0e8
writing manifest
success

ollama で使ってみる

$ ollama run ollama-youko
>>> おはよう
#今日も1日頑張るぞ!
このような文章作ってくれます🍺


メモ

ただのメモです。気にしないでください。
ollama show llama3 --modelfile
https://huggingface.co/docs/hub/en/gguf

Kubernetes から ワーカーノードを削除して、再度、JOINさせるKubernetes から ワーカーノードを削除して、再度、JOINさせる
Google Colab で、Base model を Instruct model へとチューニングする