Ollamaを動かしてみる

Ollama

最近はLLMもローカルで簡単に動かせるらしい。

やりかたはgithubに全部書いてありますね。

curl -fsSL https://ollama.com/install.sh | sh
ollama run llama3

簡単に完了。

とりあえず使用

まずは動作確認でOllama3を起動。

$ ollama run llama3
>>> こんにちは。
こんにちは!お元気ですか?
>>> hello.
Konnichiwa! It's nice to meet you. How are you today? 😊
>>> 熱いですね。
夏は熱いですね!水やエアコンが欲しいですね!😊
>>> /bye

/byeで会話終了。初回はモデルのダウンロードが走るけど、一回ダウンロードおよびロードが終わればなかなかの速度で起動してくれますね。
生意気にも絵文字を使ってきます。どこで学んだんでしょうね。日本語も返してくれます。

使い方とオプション確認

とりあえすhelpしましたが、いくつか需要がありそうなコマンドがありますね。

Available Commands:
  show        Show information for a model
  run         Run a model
  list        List models
  ps          List running models

ollama show は指定モデルのパラメータ数とかcontextの長さとか、いろいろ情報を教えてくれます。
ollama runは言わずもがな指定モデルを走らせてくれます。
ollama listはローカルの方にダウンロードされているモデルのリストアップ。
ollama psは、現在走っているモデルのリスト。デフォルトだと、コマンドで対話セッションを起動後に終了しても、それだけでは実はモデルはGPUのメモリに読み込まれたままになっています。一定時間モデルが使用されていないアイドルな時間があれば勝手にアンロードされてくれるようです。

Ollamaのモデルのロード・アンロード周りの設定

さすがにGPUが解放されるまで五分待てというのは少し嫌なので、少し解決策を探してみたところ、githubのissueにとりあえずの解決法が記載されていました。

まず、Ollamaはポート11434で待っているらしいです。次のようにすれば直接APIをたたけます。

$ curl -X POST http://localhost:11434/api/generate -d '{
  "model": "mistral",
  "prompt":"こんにちは!"
 }'
{"model":"mistral","created_at":"XXXX","response":" ","done":false}
{"model":"mistral","created_at":"XXXX","response":"こ","done":false}
{"model":"mistral","created_at":"XXXX","response":"ん","done":false}
{"model":"mistral","created_at":"XXXX","response":"に","done":false}
...

で、モデルをどうすればロード/アンロードできるかというと、次のいずれかのようにAPIをたたけばいいみたいです。

# Unload immediately!
curl http://localhost:11434/api/generate -d '{"model": "mistral", "keep_alive": 0}'
# Keep Alive!
curl http://localhost:11434/api/generate -d '{"model": "mistral", "keep_alive": -1}' 

モデル名は操作したいモデルで、keep_aliveを0にすれば即座に現在ロードされているモデルがアンロードされます。少し実際に確認してみましょう。

まず、現在ollama psで次のように表示されている状態から、keep_alive=-1としてクエリを送ってみましょう。

$ ollama ps
NAME            ID              SIZE    PROCESSOR       UNTIL
mistral:latest  2ae6f6dd7a3d    6.3 GB  100% GPU        4 minutes from now
curl http://localhost:11434/api/generate -d '{"model": "mistral", "keep_alive": -1}'

すると次のようになりました。

$ ollama ps
NAME            ID              SIZE    PROCESSOR       UNTIL
mistral:latest  2ae6f6dd7a3d    6.3 GB  100% GPU        Forever

UntilがForeverになっていますね。放っておくといつまでもロードされ続けます。ollama serveで立て続けたりするなら便利そうですね。ちなみに現在モデルがロードされていない状態からこのクエリを送ってやってもUntil Foreverで読み込まれてくれます。
で、ここからkeep_alive=0でやってみると、次のようになります。

{"model":"mistral","created_at":"XXXX","response":"","done":true,"done_reason":"load"}
$ ollama ps
NAME    ID      SIZE    PROCESSOR       UNTIL

即座にアンロードされていますね。よかった。
ちょっとcurlで直接たたかなくちゃいけないってのはスマートではない気もしますが、解決できてよかったです。重いモデルとかだとGPUのVRAMはみ出して普通のメモリまで使ってくるので、即座にインスタンス落とせないと不便ですからね。

こんな感じでbashファイルでも作ればいいんじゃないでしょうか。

#!/bin/bash

MODEL_NAME=$1

if [ -z "$MODEL_NAME" ]; then
  echo "Usage: $0 <model_name>"
  exit 1
fi

curl http://localhost:11434/api/generate -d "{\"model\": \"$MODEL_NAME\", \"keep_alive\": 0}"

トークン出力速度など確認 : –verboseオプション!

人によってはモデルごとに入出力の速度計測をしたくなるはずです。
githubのreadmeにはなぜか書いていませんが、ollama run model --verboseというように、verboseオプションを指定することで、各種メトリクスの表示をすることができます。

$ ollama run mistral --verbose
>>> Hello!
 Hello there! How can I assist you today? Let's make this day a little brighter together.
 What do you need help with? 😊

total duration:       2.233837717s
load duration:        3.400044ms
prompt eval count:    7 token(s)
prompt eval duration: 25.713ms
prompt eval rate:     272.24 tokens/s
eval count:           87 token(s)
eval duration:        2.10466s
eval rate:            41.34 tokens/s

各出力の末尾に各種数値が出てきますね。

  • かかった時間
  • 入力プロンプトのトークン数
  • 入力プロンプトのEmbedding時間?
  • 入力プロンプトの処理トークン/s
  • モデル出力のトークン数
  • モデル出力にかかった時間
  • モデル出力の処理トークン/s

ほしい情報はそろっていそうです。そもそも私みたいなモデルをただ使用する側のユーザーが見たいところなんて処理時間とトークンの出力速度くらいですからね。

性能比較

速度が出るならモデル間の比較をするのが道理というもの。
とりあえずそこそこメジャーそうなものなどいくつか使って、せっかくなので各モデルの性能を比べてみました。
ちなみにgemma2という最近出たモデルの大きいものを使ってみたりしていますが、GPUのVRAMに収まらないものについては速度が段違いに落ちるようですね。

環境

  • CPU : 13th Gen Intel(R) Core(TM) i5-13400F
  • GPU : NVIDIA GeForce RTX 4060 Ti (8GB)
  • メモリ : 32GB
  • プロンプト入力: What is your recommendation for Curry?

計測結果

とりあえず普通の言語モデル4つほどを例示しています。
項目についての補足ですが、Processorはollama psで表示されるもので、GPUのVRAMに収まらないときはCPUの方にもはみ出しています。Output Length、Duration、Eval rateは出力の長さと出力にかかる時間、そして単位時間当たりのトークン出力数ですね。この中だとEval rateが一番大事なのかと思います。出力文字列の長さはプロンプトにもよりますしね。

NameSize [GB]Processor [CPU/GPU]Output Length [tokens]Duration [s]Eval rate [tokens/s]
llama3:latest4.70%/100%34912.627.7
mistral:latest4.10%/100%73118.040.6
gemma2:9b5.49%/91%15817.88.9
gemma2:27b1561%/39%13758.22.4

ここでSizeとしたのはollama listで表示されるサイズですが、実際にはメモリに展開されると1.5倍くらいは大きなサイズになります。gemma2:9bは文字通り9GB必要なので、案の定私のGPUだけでは処理できません。残念。
GPUで処理しきれるモデルなら数十トークン/sくらいはいけるということで、思ったよりかなり高速で動くみたいですね。参考までに、ChatGPT4oに同じ質問をしたところ、20.8秒で396トークン、19tokens/sでした。もちろん動作環境とかレイテンシ、あと回答の質に違いはあるんでしょうが、レスポンスの速さという意味ではかなり魅力的なんじゃないでしょうか。

感想

ふつうのGPUでも結構サクサクLLMは動作してくれるものなんですね。
最初はCopilotとかCodeWhisperer的なものを試したくてローカルでのLLM動作を試してみたんですが、思ったよりいろいろ使える余地がありそうです。

コメント

タイトルとURLをコピーしました