Intel製CPU/GPUで高速にLLMを動かせるipex-llmというのがある。今回はこれをDockerで動かしていきたい(諦めたのでできず)
→ただ単にIntelのドキュメントをなぞる記事になりました
公式手順
これに手順が書いてある。見たところDockerを入れて、公式のDocker Imageをpullして、コンテナ動かせばいいらしい。これだけでできると最初は思ってたけど、書いてないことも色々やらなきゃ動かないっぽかった…
直面した問題
/llm/llama-cpp/run.pyが見つからない
ここまで終わった(Quick Benchmark for llama.cppの直前)のでそのベンチマークを回そうとしたら、以下のエラーが出た。
python: can't open file '/llm/llama-cpp/run.py': [Errno 2] No such file or directory
/llm/scripts/benchmark_llama-cpp.sh: line 24: ./main: No such file or directory
/llm/scripts/benchmark_llama-cpp.sh: line 25: ./main: No such file or directory
/llm/scripts/benchmark_llama-cpp.sh: line 27: ./main: No such file or directory
/llm/llama-cpp/run.py
が見つからないらしい。一応Docker Imageをpullし直してみたけど変わらなかった。確かにこのファイルが見つからないようだ。件のベンチマークをするシェルスクリプトは、途中でこのファイルを呼び出していた。
で、冒頭のipex-llmのGitHubリポジトリを見てみると、ここにファイルがあった。
これをとりあえずDockerコンテナの中にtouch
とかvi
コマンドで作ってみた。するとこのエラーは消えた。っていうか、このチュートリアルのドキュメントには書いてるけど、Dockerfileを見てもこのファイルを取得する部分が無いので、更新漏れとかそういうやつなのかなぁ…
ModuleNotFoundError: No module named 'omegaconf'
次はOmegaconfというPythonパッケージが見つからないというエラーが出た。
File "/llm/llama-cpp/run.py", line 2018, in <module>
from omegaconf import OmegaConf
ModuleNotFoundError: No module named 'omegaconf'
benchmark_llama-cpp.sh: line 24: ./main: No such file or directory
benchmark_llama-cpp.sh: line 25: ./main: No such file or directory
benchmark_llama-cpp.sh: line 27: ./main: No such file or directory
これも、Dockerコンテナの中にpipが入っていたので、それで普通にpip install Omegaconf
で解決した。
FileNotFoundError: No such file or directory: '/llm/llama-cpp/config.yaml'
これもDockerfileで取得されてない系だった。こういうのってローカルLLM界隈では当たり前なのだろうか…言われてみれば当然なんだけど、正直なんでデフォルトで取得されてないのかよく分からない。
Traceback (most recent call last):
File "/llm/llama-cpp/run.py", line 2019, in <module>
conf = OmegaConf.load(f'{current_dir}/config.yaml')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/dist-packages/omegaconf/omegaconf.py", line 189, in load
with io.open(os.path.abspath(file_), "r", encoding="utf-8") as f:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: '/llm/llama-cpp/config.yaml'
benchmark_llama-cpp.sh: line 24: ./main: No such file or directory
benchmark_llama-cpp.sh: line 25: ./main: No such file or directory
benchmark_llama-cpp.sh: line 27: ./main: No such file or directory
root@docker-desktop:/llm/scripts# cd .. && cd /llama-cpp
bash: cd: /llama-cpp: No such file or directory
ここにそのファイルがあるので、コピペしてDockerコンテナの中にtouch
とかvi
コマンドで作ってみた。するとこのエラーは解決した。
local model not exists!
これはまぁ当然なんだけどモデルがねぇよと言われた。うーんしかしどうしよう、正直に言ってDockerだと普通にローカルに置いておくみたいに気軽にファイルを入れたり消したりできないんですよね…
それこそDockerfileを作ってやるとか、マウントをしっかり設定しないとコンテナを消すたびに色々やり直すことになってしまう…
楽に設定できる方法ないかなぁ
2024-09-01 22:47:16,593 - ERROR -
****************************Usage Error************************
path to your local model hub/Llama-2-7b-chat-hf not exists!, Please check your models' folder.
2024-09-01 22:47:16,593 - ERROR -
****************************Call Stack*************************
Traceback (most recent call last):
File "/llm/llama-cpp/run.py", line 2060, in <module>
run_model(model, api, in_out_pairs, conf['local_model_hub'], conf['warm_up'], conf['num_trials'], conf['num_beams'],
File "/llm/llama-cpp/run.py", line 151, in run_model
result = run_transformer_int4_gpu(repo_id, local_model_hub, in_out_pairs, warm_up, num_trials, num_beams, low_bit, batch_size, cpu_embedding, fp16=True, lookahead=lookahead, task=task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/llm/llama-cpp/run.py", line 466, in run_transformer_int4_gpu
model_path = get_model_path(repo_id, local_model_hub)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/llm/llama-cpp/run.py", line 219, in get_model_path
invalidInputError(os.path.isdir(local_model_path),
File "/usr/local/lib/python3.11/dist-packages/ipex_llm/utils/common/log4Error.py", line 32, in invalidInputError
raise RuntimeError(errMsg)
RuntimeError: path to your local model hub/Llama-2-7b-chat-hf not exists!, Please check your models' folder.
WSL2+Dockerを諦める
見ていて思ったけど、やっぱりDockerを使うときれいではあるけどめんどくさそうなので、ローカル(Windows 11)にIPEX-LLMをインストールして使うことにしてみる。その方法が書かれたドキュメントもあるのだが、llama.cppのインストール部分とかが飛ばされていて記述が無い(→記述が無いのではなくそもそもMiniforgeを使うと必要無いっぽい)ので分からなかった
そこで、前も見かけた先人の記事を読むと、別途llama.cppをインストールしていたので、その手順に従うことにする。
公式の手順(1、2)に従いつつ、llama.cppのインストールでは先人の記事を参考にすると、以下の手順でできるはず。
- Pythonの環境を用意してIPEX-LLMのインストール
- IPEX-LLMがインストールされた環境にllama.cppをインストール
- llama.cppがインストールできたら、Ollamaをインストール
だいたいこんな感じのはず。具体的なコマンドとかはこれから説明していきます。
手順
ipex-llmをインストール
公式ではconda(Miniforge?)を使っているが、多分なんでもいいので(→そんなことなかった)今回はuvを使う。
まずはuvで環境を作る。
uv init --name llm-cpp --python 3.11
次に、uv add
コマンドでipex-llmパッケージを追加する。
uv add ipex-llm[xpu]
PS C:\Users\user\dev\python\LLM\ipex-llm> uv add ipex-llm[xpu]
Using Python 3.12.0 interpreter at: C:\Users\user\AppData\Local\Programs\Python\Python312\python.exe
Creating virtualenv at: .venv
× No solution found when resolving dependencies:
╰─▶ Because there is no version of intel-extension-for-pytorch==2.1.10+xpu and ipex-llm[xpu]==2.1.0 depends on
intel-extension-for-pytorch==2.1.10+xpu, we can conclude that ipex-llm[xpu]==2.1.0 cannot be used.
And because only ipex-llm[xpu]==2.1.0 is available and your project depends on ipex-llm[xpu], we can conclude
that your project's requirements are unsatisfiable.
help: If this is intentional, run `uv add --frozen` to skip the lock and sync steps.
No Solution found when resolbing dependencies:
が出た。曰く、ipex-llm[xpu]は
intel-extension-for-pytorchに依存しているとか何とか。
実は公式手順では[cpp]
になっているんだけど、どうやらもう無効なオプションらしいので、とりあえず[xpu]
にしてみたのだった。ちなみに[cpp]
にしてみても同じように依存関係でエラーを吐いた。
先人の記事でもdpcppを別途pipでインストールしているので、いずれにせよ依存先のパッケージを入れなければならないっぽいが…
intel_extension_for_pytorch自体はここのページから落とせる。とりあえず以下のコマンドを実行してみた。410MBくらいあってデカい。
uv add intel-extension-for-pytorch==2.1.40+xpu --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/mtl/us/
これを実行してみたのだけどNumpyが無いとかで蹴られた。ただ、uvを使っているからなのか、Numpyの最新版を追加済みで正しいはずなのに相変わらずこのエラーが出てしまった。Intelのサイトに表示されるコマンドは以下のものだし、
python -m pip install torch==2.1.0.post3 torchvision==0.16.0.post3 torchaudio==2.1.0.post3 intel-extension-for-pytorch==2.1.40+xpu --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/mtl/us/
このコマンドが間違っていなければできるはずなので、原因がuvにあるのかどうかを調べたいけど、今から使いづらいpipとかを使う気になれないので、とりあえず--extra-index-url
で指定されているURL(https://pytorch-extension.intel.com/release-whl/stable/mtl/us/)に飛んで、そこから直接パッケージのURLを確認して、それをuv add {URL}
で指定してパッケージを入れることにした。具体的には以下の通り。
Pytorchとintel_extension_for_pytorchを入れる
uv add 'torch==2.1.0.post3' --extra-index-url https://intel-extension-for-pytorch.s3.amazonaws.com/ipex_stable/mtl/torch-2.1.0.post3%2Bcxx11.abi-cp311-cp311-win_amd64.whl
uv add https://intel-extension-for-pytorch.s3.amazonaws.com/ipex_stable/mtl/intel_extension_for_pytorch-2.1.40%2Bxpu-cp311-cp311-win_amd64.whl
どういうわけかintel_extension_for_pytorchの方は、uv add 'torch==2.1.0.post3' --extra-index-url https://
が使えなかったので仕方なくURLを直で入れた。これでなんとか入ったっぽい…?
init-llama-cpp.batを実行
init-llama-cpp.bat
を実行する、とIntel公式ドキュメントにあるけど、そんなものどこを探しても見つからず。llama.cppのリポジトリはクローンしたけど(→これはMiniforgeを使う方法だと必要ないらしい。pip install --pre --upgrade ipex-llm[cpp]
したらその時点でllama.cppというフォルダができていた)、それっぽいバッチファイルはinstall-oneapi.bat
だが、これは実行しても途中で失敗してしまった。
もう分からなくなってきて、とりあえずIntel oneAPI Base Toolkitを入れることに。ただこれがめちゃくちゃデカくて、Recomended Installationだと全部で15.8GBもある。
よく分からないが多分環境変数を設定するバッチファイルがC:\Program Files (x86)\Intel\oneAPI\setvars.batにあ
るので、これを実行しておいた。
諦めてMiniforgeを使う
何が足りないのかさっぱり分からなかったので、とりあえずもう諦めてMiniforgeを使うことにした。実行したコマンドは以下の通り。これはIntelのドキュメントほぼそのままである。
実行したコマンド
コードとして表示する都合上PowerShellになっているものの、これはMiniforgeのコマンド(Windows PowerShellでもPowerShellでもcmd.exe(コマンドプロンプト)でもない)で実行するものであることに注意が必要。
conda create -n llm-cpp python=3.11
conda activate llm-cpp # Miniforgeの仮想環境に入る
pip install --pre --upgrade ipex-llm[cpp] # ipex-llmパッケージを入れる(ここでllama.cppも入る)
git clone https://github.com/ggerganov/llama.cpp.git
cd llama.cpp
# 以下のコマンドは管理者権限で起動したMiniforge Promptを使う
init-llama-cpp.bat
set SYCL_CACHE_PERSISTENT=1
rem under most circumstances, the following environment variable may improve performance, but sometimes this may also cause performance degradation
set SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1
init-ollama.bat
set OLLAMA_NUM_GPU=999
set no_proxy=localhost,127.0.0.1
set ZES_ENABLE_SYSMAN=1
Miniforgeをインストールした後、Miniforgeを使ってもやっぱりディレクトリにinit-llama-cpp.bat
なんてファイルは無かったのだが、なぜか存在しているらしかった(どこで入った?いや、普通に考えればipex-llmをインストールしたら入ったんだろうけど、ipex-llmのGitHubリポジトリにもこんなファイルは存在しないので謎)。どういう仕組みなのかさっぱり分からないが、Miniforgeで作成した仮想環境に入って、そこでinit-llama-cpp.bat
を実行するとそこには無かったはずのバッチファイルが実行された。バッチファイル実行後にそのディレクトリ(仮想環境の中)でdir
コマンド(Miniforgeはコマンドプロンプトなのでこれ、Linuxでいうls
コマンド)を打ってみても、そもそもバッチファイルすら存在しないにもかかわらず、実行できる。何なんだこれは。
ファイルの実体を調べようと思ってEverythingでファイルの場所を調べてみると、C:\Users\user\miniforge3\envs\llm\Scripts\init-llama-cpp.bat
に存在した。でもこれ自体もシンボリックリンクで、しかも同じ場所のC:\Users\user\miniforge3\envs\llm\Scripts\init-llama-cpp.bat
にリンクしていた。元の場所に戻ってくるシンボリックリンクとか設定できるんだ…何もかも未知すぎる。どういう仕組みなんだ…
これでOllamaがipex-llmで動くようにはなった。Intelの公式手順ではインストール確認のためにMistralを動かしているが、デカいし別に飛ばしてもいいはず。実際に動かすにはもうひと手間、以下の手順が必要。
ollama serve
これでOllamaが起きてくるが、まだAIモデルはロードされない。ここで、もう一つ追加で別のMiniforge Promptのウインドウ(もしくはタブ)を開いて、以下のようにコマンドを実行すれば、晴れてAIモデルと対話できる。
ollama run {OllamaにアップロードされているAIモデル}
# 例
ollama run 7shi/ezo-common-t2-gemma-2:2b-instruct-q8_0
1回→どっちも間違ってる可能性がollama run
で動かせば、(→ollama serve
すれば、かも)/bye
でMiniforge Promptを閉じた後でも、Open WebUIなどからAIモデルを使うことができる。
AIの返答中に、GPUの使用率が100%に近づいていたら成功しているはず。
Open WebUIなんかだと、ollama serve
したら、既にpull済みのモデルを使う場合ollama run
しなくてもモデルを使える(チャットを始めるときに自動でモデルがロードされる)っぽい
メモ
忘れがちなコマンドをまとめた
ipex-llmと関係無いものも含まれます
Open WebUI
Dockerイメージをアップデート
docker pull ghcr.io/open-webui/open-webui:main
docker stop open-webui
docker rm open-webui
docker run -d -p 3000:8080 --add-host=host.docker.internal:host-gateway -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main
アップデートしても、この手順ならDockerコンテナ内のデータは保持される。
ipex-llm
再起動後の起動
# ここまでにllama.cppのフォルダ(ディレクトリ)に移動しておくこと
conda activate llm-cpp # 仮想環境を有効化
ollama serve # ollamaを起動