IPEX-LLMを使ってDockerとIntel GPUでローカルLLMを高速に動かしたかったけど諦めて妥協したメモ

この記事は約19分で読めます。
当サイトには、広告及びアフィリエイトリンクが含まれ、それによって収益を得ています。記事の内容やリンクには、プロモーションが含まれる場合があります。詳細については、プライバシーポリシーをご覧ください。

この記事はほとんどチラ裏と同じです

Intel製CPU/GPUで高速にLLMを動かせるipex-llmというのがある。今回はこれをDockerで動かしていきたい(諦めたのでできず)

→ただ単にIntelのドキュメントをなぞる記事になりました

公式手順

ipex-llm/docs/mddocs/DockerGuides/docker_cpp_xpu_quickstart.md at main · intel-analytics/ipex-llm
Accelerate local LLM inference and finetuning (LLaMA, Mistral, ChatGLM, Qwen, Baichuan, Mixtral, Gemma, Phi, MiniCPM, et...

これに手順が書いてある。見たところDockerを入れて、公式のDocker Imageをpullして、コンテナ動かせばいいらしい。これだけでできると最初は思ってたけど、書いてないことも色々やらなきゃ動かないっぽかった…

直面した問題

/llm/llama-cpp/run.pyが見つからない

ipex-llm/docs/mddocs/DockerGuides/docker_cpp_xpu_quickstart.md at main · intel-analytics/ipex-llm
Accelerate local LLM inference and finetuning (LLaMA, Mistral, ChatGLM, Qwen, Baichuan, Mixtral, Gemma, Phi, MiniCPM, et...

ここまで終わった(Quick Benchmark for llama.cppの直前)のでそのベンチマークを回そうとしたら、以下のエラーが出た。

Bash
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リポジトリを見てみると、ここにファイルがあった。

ipex-llm/python/llm/dev/benchmark/all-in-one/run.py at main · intel-analytics/ipex-llm
Accelerate local LLM inference and finetuning (LLaMA, Mistral, ChatGLM, Qwen, Baichuan, Mixtral, Gemma, Phi, MiniCPM, et...

これをとりあえずDockerコンテナの中にtouchとかviコマンドで作ってみた。するとこのエラーは消えた。っていうか、このチュートリアルのドキュメントには書いてるけど、Dockerfileを見てもこのファイルを取得する部分が無いので、更新漏れとかそういうやつなのかなぁ…

ModuleNotFoundError: No module named 'omegaconf'

次はOmegaconfというPythonパッケージが見つからないというエラーが出た。

Bash
  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界隈では当たり前なのだろうか…言われてみれば当然なんだけど、正直なんでデフォルトで取得されてないのかよく分からない。

Bash
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を作ってやるとか、マウントをしっかり設定しないとコンテナを消すたびに色々やり直すことになってしまう…

楽に設定できる方法ないかなぁ

Bash
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をインストールしていたので、その手順に従うことにする。

公式の手順(12)に従いつつ、llama.cppのインストールでは先人の記事を参考にすると、以下の手順でできるはず。

  • Pythonの環境を用意してIPEX-LLMのインストール
  • IPEX-LLMがインストールされた環境にllama.cppをインストール
  • llama.cppがインストールできたら、Ollamaをインストール

だいたいこんな感じのはず。具体的なコマンドとかはこれから説明していきます。

手順

ipex-llmをインストール

公式ではconda(Miniforge?)を使っているが、多分なんでもいいので(→そんなことなかった)今回はuvを使う。

まずはuvで環境を作る。

PowerShell
 uv init --name llm-cpp --python 3.11

次に、uv addコマンドでipex-llmパッケージを追加する。

PowerShell
uv add ipex-llm[xpu]
PowerShell
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くらいあってデカい。

PowerShell
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のサイトに表示されるコマンドは以下のものだし、

PowerShell
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を入れる

PowerShell
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(コマンドプロンプト)でもない)で実行するものであることに注意が必要。

PowerShell
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を動かしているが、デカいし別に飛ばしてもいいはず。実際に動かすにはもうひと手間、以下の手順が必要。

PowerShell
ollama serve

これでOllamaが起きてくるが、まだAIモデルはロードされない。ここで、もう一つ追加で別のMiniforge Promptのウインドウ(もしくはタブ)を開いて、以下のようにコマンドを実行すれば、晴れてAIモデルと対話できる。

PowerShell
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イメージをアップデート

PowerShell
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コンテナ内のデータは保持される。

Updating | Open WebUI
Updating your Docker Installation

ipex-llm

再起動後の起動

Miniforge Prompt
# ここまでにllama.cppのフォルダ(ディレクトリ)に移動しておくこと
conda activate llm-cpp # 仮想環境を有効化
ollama serve # ollamaを起動

病気療養中のガジェットオタクです。PC、スマホからオーディオ、家電まで、デジモノ・IT系中心に自分の興味のあるものならなんでも記事にします。誤字脱字など、ミスの報告歓迎です。
お問い合わせは、当ブログのお問い合わせフォームにお願いします。レビュー依頼など、各種ご依頼承っています。

でじぃをフォローする↓
プログラミング
スポンサーリンク
でじぃをフォローする↓
タイトルとURLをコピーしました