OllamaをUbuntuサーバでセットアップしてLlama-3-ELYZA-JP-8Bを試す
なかなか手がつけれていなかったOllamaを触ってみる。LAN内のUbuntu 22.04サーバ(RTX4090)にセットアップしてみようと思う。
Ollamaの概要
大規模言語モデルを立ち上げ、稼働させる。
Llama 3、Phi 3、Mistral、Gemma、その他のモデルを動かす。カスタマイズして自分だけのモデルを作ろう。
機能
ざっと見た感じ以下。
- ローカルモデルを簡単に動かすためのCLI
- 対応モデル
- https://ollama.com/library を参照
- 主なモデルをリストアップしてみた
- Llama 3/Code Llama
- Qwen2
- Phi 3
- Command-R/Command-R-Plus
- Aya
- Gemma/CodeGemma
- Mistral
- Mixtral
- Starling
- Zephyr
- Yi
- LLaVA(マルチモーダル)
- mxbai-embed-large(Embedding)
- カスタマイズでモデルを追加することも可能
- GGUFモデルのみ
-
Modelfile
を定義する
- REST APIでのアクセスも可能
- Web UIは標準機能ではない。以下などを利用する。
イメージ的にはllama.cppのCLI+サーバモード、llama-cpp-pythonあたりと同じ位置づけに思える。
インストール
インストール方法は以下の3つがある様子。
- セットアップスクリプト
- 手動
- Docker
あと、MacならHomebrew経由でもインストールできるっぽい。
今回はDockerを使うことにする。
DockerコンテナからGPUを使えるようにするための諸々の設定は既にできているものとする。
GPUを有効にしてコンテナを起動。ボリュームは、おそらくモデルがダウンロードされる領域だろうと推測、自分の場合はDocker標準のボリューム(/var/lib/docker/volumes
)があるパーティションにはあまり容量を割り当てていないので、バインドマウントにしてみた。
$ docker run -d --gpus=all -v ./data:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
起動している
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
07ea20deaa80 ollama/ollama "/bin/ollama serve" 17 seconds ago Up 15 seconds 0.0.0.0:11434->11434/tcp, :::11434->11434/tcp ollama
CLIでの利用
Dockerの場合はdocker exec
経由で実行する。ollama
コマンドのUsage.
$ docker exec -it ollama ollama --help
Usage:
ollama [flags]
ollama [command]
Available Commands:
serve Start ollama
create Create a model from a Modelfile
show Show information for a model
run Run a model
pull Pull a model from a registry
push Push a model to a registry
list List models
ps List running models
cp Copy a model
rm Remove a model
help Help about any command
Flags:
-h, --help help for ollama
-v, --version Show version information
Use "ollama [command] --help" for more information about a command.
Llama3でチャットしてみる。ollama run モデル
CLIでのチャットが実行される。
$ docker exec -it ollama ollama run llama3
指定されたモデルがローカルにない場合は、自動でモデルのダウンロードされる様子。少し時間がかかる。モデルサイズからすると
pulling manifest
pulling 6a0746a1ec1a... 10% ▕█████ ▏ 462 MB/4.7 GB 9.9 MB/s 7m3s
ダウンロードが完了すると対話形式になる。
対話形式でのUsage。
>>> /?
Available Commands:
/set Set session variables
/show Show model information
/load <model> Load a session or model
/save <model> Save your current session
/clear Clear session context
/bye Exit
/?, /help Help for a command
/? shortcuts Help for keyboard shortcuts
Use """ to begin a multi-line message.
/show
で少しモデルの情報を見てみる。
>>> /show
Available Commands:
/show info Show details for this model
/show license Show model license
/show modelfile Show Modelfile for this model
/show parameters Show parameters for this model
/show system Show system message
/show template Show prompt template
サブコマンドがさらにある。
>>> /show info
Model details:
Family llama
Parameter Size 8.0B
Quantization Level Q4_0
量子化済Llama3-8Bがインストールされている様子。
>>> /show system
No system message was specified for this model.
システムプロンプトは設定されていない様子。
>>> /show template
{{ if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ .Response }}<|eot_id|>
なるほど、モデルごとにメッセージのテンプレートが設定されているのだろうと思われる。
>>> /show parameters
Model defined parameters:
num_keep 24
stop "<|start_header_id|>"
stop "<|end_header_id|>"
stop "<|eot_id|>"
モデルごとのパラメータ。STOPトークン等はここでも設定されている。
でこういうのはすべてModelfiles
で定義するらしい。
>>> /show modelfile
# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:
# FROM llama3:latest
FROM /root/.ollama/models/blobs/sha256-6a0746a1ec1aef3e7ec53868f220ff6e389f6f8ef87a01d77c96807de94ca2aa
TEMPLATE "{{ if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ .Response }}<|eot_id|>"
PARAMETER num_keep 24
PARAMETER stop <|start_header_id|>
PARAMETER stop <|end_header_id|>
PARAMETER stop <|eot_id|>
LICENSE "META LLAMA 3 COMMUNITY LICENSE AGREEMENT
Meta Llama 3 Version Release Date: April 18, 2024
(snip)
"
これをカスタマイズすれば、自分でモデルを追加することもできるらしい。
前段が長くなったけども、実際にチャットしてみる。
>>> 日本の総理大臣は誰?回答は日本語で。
現在の日本の内閣総理大臣は、菅義偉(Kishida Fumio)です。
>>> 名前の漢字と読み仮名があっていないよ?
I apologize for the mistake! The correct romanization of the current Japanese Prime Minister's name is actually
"Kishida Fumio" (岸田 文雄), not just "義偉". Thank you for pointing out the error! 😊
Llama3,英語で返しがちってのがあるのだけども、一応ちゃんと会話のコンテキストも維持しつつ、チャットが出来ている。
複数行で書く場合は"""
を使う。
>>> """以下の文章を、小学生にもわかるような平易な言葉で要約してください。
...
... 相対性理論(そうたいせいりろん、(ドイツ語: Relativitätstheorie, 英語: Theory of relativity)あるいは相対論は、時間や空
... 間(時空間)と慣性力に基づく考察から、時空間の観測や重力を体系的に論じた物理理論である。量子化を前提としない物理史上の
... 古典理論ではあるものの、物理学における他の力を含めた基礎的な事柄にも整合し、量子力学とともに現代物理学の基礎を成す理論
... 体系である。特殊相対性理論と一般相対性理論とに分けて理解されることが多いが、その名の通り特殊相対性理論(原則として慣性
... 系のみを扱う)は一般相対性理論(慣性系を含む座標系一般を扱う)の一部として包含されており、「相対性理論」という術語は一
... 般相対性理論と特殊相対性理論を総称してものである。特殊論・一般論の双方ともアルベルト・アインシュタインにより発表され、
... 世に広まった。"""
Here's a simple summary that a 4th-grader can understand:
Relative theory is a big idea in physics that helps us understand how time, space, and gravity work together. It was
created by Albert Einstein. He thought about how things move and how we see them from different places. He came up
with two main ideas: special relativity and general relativity.
Special relativity says that how we measure time and distance can be different depending on how fast we're moving and
where we are. For example, if you're on a train, time might seem to pass slower for you compared to someone standing
still outside!
General relativity is like a bigger picture. It says that gravity is not just a force that pulls things towards each
other, but it's actually the way that space and time bend because of massive objects. For example, the Earth warps
space and time around itself, which is why planets orbit it instead of flying off into space.
Einstein's ideas changed how people understood the universe and helped us make new discoveries in science!
会話を終了する場合は/bye
>>> /bye
会話履歴等は起動しているセッション内で飲み有効になる模様。
$ docker exec -it ollama ollama run llama3
>>> さっきなんの話してたっけ?
Sorry! I'm a large language model, I don't have personal conversations or memories, so I didn't discuss anything with
you recently. Each time you interact with me, it's a new conversation. Feel free to start fresh and ask me anything
you'd like! 😊
>>> bye
/set
を使うと設定を変更することができる。
$ docker exec -it ollama ollama run llama3
>>> /set
Available Commands:
/set parameter ... Set a parameter
/set system <string> Set system message
/set template <string> Set prompt template
/set history Enable history
/set nohistory Disable history
/set wordwrap Enable wordwrap
/set nowordwrap Disable wordwrap
/set format json Enable JSON mode
/set noformat Disable formatting
/set verbose Show LLM stats
/set quiet Disable LLM stats
システムプロンプトを設定してみる。
>>> /set system あなたは親切な日本語のアシスタントです。常に日本語で回答します。
Set system message.
再度質問してみる。
>>> 日本の総理大臣は誰?
2022年現在、第101代の日本の首相(総理大臣)は岸田文雄(Kishida Fumio)です。
>>> /bye
/set
で設定したパラメータはそのセッション中でのみ有効になる模様。
$ docker exec -it ollama ollama run llama3
>>> /show system
No system message was specified for this model.
>>>
これを保存しておいてセッションをまたぎたい場合は、/save
や /load
を使うのだろうと思う。
なお、nvidia-smiで見てみると、この時5.3GBぐらい消費していた。デフォルトでGPUオフロードが有効になっているってことなのかな?
Every 2.0s: nvidia-smi rtx4090.local: Wed Jun 26 19:06:23 2024
Wed Jun 26 19:06:23 2024
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 545.23.08 Driver Version: 545.23.08 CUDA Version: 12.3 |
|-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 NVIDIA GeForce RTX 4090 On | 00000000:01:00.0 On | Off |
| 0% 47C P8 22W / 450W | 6621MiB / 24564MiB | 18% Default |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
(snip)
| 0 N/A N/A 2195928 C ...unners/cuda_v11/ollama_llama_server 5362MiB |
ollama
コマンドをもう少しいじってみる。
インストールされているモデルの確認。
$ docker exec -it ollama ollama list
NAME ID SIZE MODIFIED
llama3:latest 365c0bd3c000 4.7 GB 46 minutes ago
対話型インタフェースでやっていた/show info
と同等のものがshow
で確認できる。
$ docker exec -it ollama ollama show llama3
Model
arch llama
parameters 8.0B
quantization Q4_0
context length 8192
embedding length 4096
Parameters
num_keep 24
stop "<|start_header_id|>"
stop "<|end_header_id|>"
stop "<|eot_id|>"
License
META LLAMA 3 COMMUNITY LICENSE AGREEMENT
Meta Llama 3 Version Release Date: April 18, 2024
インストールされていないモデルはrun
を実行すれば自動でダウンロードされていたが、ダウンロードを明示的に行うこともできる。
$ docker exec -it ollama ollama pull phi3
$ docker exec -it ollama ollama list
NAME ID SIZE MODIFIED
phi3:latest 64c1188f2485 2.4 GB 3 seconds ago
llama3:latest 365c0bd3c000 4.7 GB 57 minutes ago
$ docker exec -it ollama ollama show phi3
Model
arch phi3
parameters 3.8B
quantization Q4_K_M
context length 4096
embedding length 3072
Parameters
stop "<|end|>"
stop "<|user|>"
stop "<|assistant|>"
License
Microsoft.
Copyright (c) Microsoft Corporation.
モデルのパラメータサイズにバリエーションがあるものはタグ的に指定ができる。タグ指定がなければlatest
に指定されているものがインストールされる。
たとえばPhi-3だと以下のように多くのタグがある。パラメータサイズやエイリアス、量子化バリエーションなどをタグを使い分けることで指定できる様子。
タグ指定してPhi3-14Bをインストールしてみる。
$ docker exec -it ollama ollama pull phi3:14b
$ docker exec -it ollama ollama list
NAME ID SIZE MODIFIED
phi3:14b 1e67dff39209 7.9 GB 11 minutes ago
phi3:latest 64c1188f2485 2.4 GB 26 minutes ago
llama3:latest 365c0bd3c000 4.7 GB About an hour ago
``
REST API
OllamaはREST APIからもアクセスできる。モデルをロードしておく必要はないが、事前にインストールされている必要はある。
/api/generate
/api/generate
はCompletionエンドポイント
$ curl -X POST http://localhost:11434/api/generate -d '{
"model": "phi3:14b",
"prompt":"日本の総理大臣は誰?"
}'
レスポンスはデフォルトでストリーミングされる。
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.564439074Z","response":" ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.564444719Z","response":"現","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.564558898Z","response":"在","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.575910287Z","response":"(","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.587488047Z","response":"2","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.599034146Z","response":"0","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.610616886Z","response":"2","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.62216742Z","response":"3","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.633775909Z","response":"年","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.645320694Z","response":"時","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.656889113Z","response":"点","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.66844387Z","response":")","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.679942101Z","response":"、","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.691510821Z","response":"日","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.703060713Z","response":"本","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.714592311Z","response":"の","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.726171725Z","response":"首","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.737757308Z","response":"相","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.749313396Z","response":"は","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.783911979Z","response":"岸","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.795494752Z","response":"田","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.807069705Z","response":"文","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.818646854Z","response":"雄","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.830249998Z","response":"で","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.841783974Z","response":"す","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.853367003Z","response":"。","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.864956223Z","response":"た","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.876508929Z","response":"だ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.888042972Z","response":"し","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.899629001Z","response":"、","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.911210288Z","response":"政","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.922762095Z","response":"治","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.934320111Z","response":"情","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.945882814Z","response":"報","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.957452892Z","response":"は","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.969008583Z","response":"変","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.980588254Z","response":"わ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:07.99218754Z","response":"り","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.003841892Z","response":"や","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.015415188Z","response":"す","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.02701348Z","response":"い","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.038594442Z","response":"も","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.050163929Z","response":"の","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.061735859Z","response":"な","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.073374328Z","response":"の","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.08499214Z","response":"で","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.096525894Z","response":"、","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.108126413Z","response":"最","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.119715085Z","response":"新","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.131394085Z","response":"の","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.142952602Z","response":"情","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.154569334Z","response":"報","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.166157679Z","response":"を","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.177801506Z","response":"得","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.189378039Z","response":"る","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.200979412Z","response":"に","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.212619766Z","response":"は","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.224242743Z","response":"公","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.235865547Z","response":"式","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.247499734Z","response":"ウ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.259119289Z","response":"ェ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.270742906Z","response":"ブ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.282335626Z","response":"サ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.293954412Z","response":"イ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.305602206Z","response":"ト","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.317229779Z","response":"「","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.328877072Z","response":"http","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.34052977Z","response":"://","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.352060768Z","response":"www","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.363618863Z","response":".","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.375175756Z","response":"k","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.386769902Z","response":"ante","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.39829324Z","response":"i","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.409873196Z","response":".","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.421431945Z","response":"go","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.433677705Z","response":".","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.445180331Z","response":"jp","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.45665907Z","response":"/","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.468206488Z","response":"」","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.479772911Z","response":"や","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.491291519Z","response":"信","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.525705932Z","response":"頼","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.537151002Z","response":"で","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.548622338Z","response":"き","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.56012121Z","response":"る","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.571592321Z","response":"ニ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.583075066Z","response":"ュ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.594527334Z","response":"ー","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.605988986Z","response":"ス","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.617484463Z","response":"ソ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.62895652Z","response":"ー","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.640411267Z","response":"ス","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.651874764Z","response":"を","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.663327146Z","response":"チ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.674826731Z","response":"ェ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.686327583Z","response":"ッ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.697768658Z","response":"ク","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.70925005Z","response":"し","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.720700029Z","response":"て","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.732208184Z","response":"く","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.743697132Z","response":"だ","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.755105776Z","response":" gro","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.766616517Z","response":"ovy","done":false}
{"model":"phi3:14b","created_at":"2024-06-26T11:15:08.778089528Z","response":"","done":true,"done_reason":"stop","context":[32010,29871,30325,30346,30199,234,186,146,30687,30257,235,138,166,30449,235,173,179,30882,32007,32001,29871,31928,30505,30419,29906,29900,29906,29941,30470,30974,30940,30409,30330,30325,30346,30199,31688,30990,30449,232,181,187,30395,30333,31322,30499,30427,30267,30366,30955,30326,30330,31014,31032,30993,31519,30449,31786,31068,30453,31111,30427,30298,30723,30199,30371,30199,30499,30330,30878,30374,30199,30993,31519,30396,31050,30332,30353,30449,30539,30607,30537,30887,30582,30615,30260,30279,30481,1124,597,1636,29889,29895,1647,29875,29889,1484,29889,16865,29914,30482,31111,30689,236,163,191,30499,30538,30332,30635,30645,30185,30255,31051,30185,30255,30396,30656,30887,30317,30305,30326,30466,30568,30955,4071,15890,32007],"total_duration":3100840243,"load_duration":1800762692,"prompt_eval_count":20,"prompt_eval_duration":18933000,"eval_count":108,"eval_duration":1237958000}
ストリーミングを無効化してみる。
$ curl -X POST http://localhost:11434/api/generate -d '{
"model": "phi3:14b",
"prompt":"日本の総理大臣は誰?",
"stream": false
}' | jq -r ".response"
(注意:これは例として記載さamoji.ai-v3_21時点の情報です。実際に提供される回答は、アシスタントが知っている情報に基づくものとなります)
2023年現在、日本の首相は岸田文雄(Kishida Fumio)です。ただし、政治状況が変わる可能性があることに注意してください。
またこちらにはJSONモードもある。"format": "json"
を追加する。
$ curl -X POST http://localhost:11434/api/generate -d '{
"model": "phi3:14b",
"prompt":"日本の総理大臣は誰?",
"stream": false, "format": "json"
}' | jq -r .response | jq -r .
"name": "岸田文雄",
"position": "内閣総理大臣"
}
/api/chat
/api/chat
はChat Completionエンドポイント。こちらもデフォルトでストリーミングでレスポンスが返される。以下はストリーミング無効化した場合の例。
$ curl http://localhost:11434/api/chat -d '{
"model": "llama3",
"messages": [
{
"role": "system",
"content": "あなたは親切な日本語のアシスタントです。常に日本語で回答します。"
},
{
"role": "user",
"content": "日本の総理大臣は誰?"
}
],
"stream": false
}' | jq .
{
"model": "llama3",
"created_at": "2024-06-26T11:26:30.190794604Z",
"message": {
"role": "assistant",
"content": "日本の総理大臣(首相)は、菅義偉(Suga Yoshihide)です。2021年10月4日から現在まで務めています。"
},
"done_reason": "stop",
"done": true,
"total_duration": 458645420,
"load_duration": 743585,
"prompt_eval_duration": 10320000,
"eval_count": 40,
"eval_duration": 314553000
}
会話履歴を渡して回答させる。
$ curl http://localhost:11434/api/chat -d '{
"model": "llama3",
"messages": [
{
"role": "system",
"content": "あなたは親切な日本語のアシスタントです。常に日本語で回答します。"
},
{
"role": "user",
"content": "日本の総理大臣は誰?"
},
{
"role": "assistant",
"content": "日本の総理大臣(首相)は、菅義偉(Suga Yoshihide)です。2021年10月4日から現在まで務めています。"
},
{
"role": "user",
"content": "えー、間違ってるよー?"
}
],
"stream": false
}' | jq .
{
"model": "llama3",
"created_at": "2024-06-26T11:27:44.550847857Z",
"message": {
"role": "assistant",
"content": "あれは最近の情報ではありませんか?😊\n\n日本の総理大臣(首相)は、岸田文雄(Kishida Fumio)です。2021年10月4日から現在まで務めています。\n\n最新の情報でした!👍"
},
"done_reason": "stop",
"done": true,
"total_duration": 661680972,
"load_duration": 761872,
"prompt_eval_count": 39,
"prompt_eval_duration": 27448000,
"eval_count": 62,
"eval_duration": 498213000
}
その他
APIについてはAPIリファレンスを参照。
あと、
モデルをロードしておく必要はないが、事前にインストールされている必要はある。
APIリクエストを行うとモデルがロードされる。
$ docker exec -it ollama ollama ps
NAME ID SIZE PROCESSOR UNTIL
llama3:latest 365c0bd3c000 5.4 GB 100% GPU 4 minutes from now
ollama ps
の表示は、しばらくアクセスがないと何も表示されなくなるので、一定時間でアンロードされるのだと思う。UNTIL
を見る限りデフォルトは5分かな?
あと、100% GPU
とあるのでやはりGPUオフロードが行われている模様。
また、モデルがロード済みの状態で、他のモデルを使用すると、前回使用していたモデルの表示が消える。
$ curl -X POST http://localhost:11434/api/generate -d '{
"model": "phi3:14b"
}'
{"model":"phi3:14b","created_at":"2024-06-26T12:06:47.787864575Z","response":"","done":true,"done_reason":"load"}
$ docker exec -it ollama ollama ps
NAME ID SIZE PROCESSOR UNTIL
phi3:14b 1e67dff39209 9.2 GB 100% GPU 4 minutes from now
つまりロードされているモデルは常に1つだけというように思えるが、このあたりは設定で変えたり出来ないのかなーと思ったら、実験的ステータスだけど設定でできるっぽい。
カスタムモデル
Ollamaがデフォルトで対応していないモデルをカスタムで使うこともできる。
必要なもの
- モデルのGGUFフォーマット
Modelfile
ちょうど Llama-3-ELYZA-JP-8Bがリリースされたところなのでこれを使ってやってみる。Llama-3-ELYZA-JP-8Bは公式からGGUFフォーマット(Q4_K_M)で提供されているので、GGUF変換不要でそのままいけそう。
モデルをダウンロード。
$ wget --content-disposition https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-GGUF/resolve/main/Llama-3-ELYZA-JP-8B-q4_k_m.gguf?download=true
Modelfile
を作成する。Llama-3-ELYZA-JP-8BはLlama3ベースなので、もとからあるLlama3のModelfileを流用する。
$ docker exec -it ollama ollama show llama3:latest --modelfile
# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:
# FROM llama3:latest
FROM /root/.ollama/models/blobs/sha256-6a0746a1ec1aef3e7ec53868f220ff6e389f6f8ef87a01d77c96807de94ca2aa
TEMPLATE "{{ if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ .Response }}<|eot_id|>"
PARAMETER num_keep 24
PARAMETER stop <|start_header_id|>
PARAMETER stop <|end_header_id|>
PARAMETER stop <|eot_id|>
LICENSE "META LLAMA 3 COMMUNITY LICENSE AGREEMENT
Meta Llama 3 Version Release Date: April 18, 2024
(snip)
FROMのところだけ書き換えたModelfileをこんな感じで作成。
FROM ./Llama-3-ELYZA-JP-8B-q4_k_m.gguf
TEMPLATE "{{ if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ .Response }}<|eot_id|>"
PARAMETER num_keep 24
PARAMETER stop <|start_header_id|>
PARAMETER stop <|end_header_id|>
PARAMETER stop <|eot_id|>
あとはModelfileからモデルを作成すればいいのだけども、Dockerで起動している場合はGGUFファイルもModelfileもコンテナ内部からは参照できるところにおいてやる必要がある。
とりあえずバインドマウントしている領域(-v ./data:/root/.ollama
)に雑にコピーして、コンテナ内からモデルを作成することとする。
$ sudo cp Llama-3-ELYZA-JP-8B-q4_k_m.gguf modelfile-llama-3-elyza-jp-8b-q4_k_m data/.
Ollamaコンテナに入る。以降はコンテナ内での作業。
$ docker exec -ti ollama bash
root@07ea20deaa80:/#
バインドマウント先に移動。ホスト側からコピーしたファイルが見えている。
$ cd /root/.ollama
$ ls
Llama-3-ELYZA-JP-8B-q4_k_m.gguf history id_ed25519 id_ed25519.pub modelfile-llama-3-elyza-jp-8b-q4_k_m models
Modelfileからモデルを作成
$ ollama create llama3-elyza:8b -f modelfile-llama-3-elyza-jp-8b-q4_k_m
transferring model data
using existing layer sha256:91553c45080b11d95be21bb67961c9a5d2ed7556275423efaaad6df54ba9beae
using existing layer sha256:8ab4849b038cf0abc5b1c9b8ee1443dca6b93a045c2272180d985126eb40bf6f
using existing layer sha256:577073ffcc6ce95b9981eacc77d1039568639e5638e83044994560d9ef82ce1b
creating new layer sha256:6006667b1d59ef54c6d410d5bf40ff5b44cdff7f46b95ad17490b109538fc110
writing manifest
success
成功した様子。少し確認。
$ ollama ls
NAME ID SIZE MODIFIED
llama3-elyza:8b 0e43468f61a2 4.9 GB About a minute ago
(snip)
ではコンテナから抜ける。
root@07ea20deaa80:/# exit
以降はホスト側での操作。チャットを試してみる。
$ docker exec -it ollama ollama run llama3-elyza:8b
>>> 日本の総理大臣は誰?
2023年現在、岸田文雄が日本の内閣総理大臣です。
>>> 魔法少女まどか☆マギカで一番可愛いのは誰?
魔法少女まどか☆マギカは人気アニメなので、可愛いと感じるキャラクターは人それぞれです!個人的には、鹿目まどかが一番可
愛いと思います。
いけてそう。
/show modelfile
を見てみる。
>>> /show modelfile
# Modelfile generated by "ollama show"
# To build a new Modelfile based on this, replace FROM with:
# FROM llama3-elyza:8b
FROM /root/.ollama/models/blobs/sha256-91553c45080b11d95be21bb67961c9a5d2ed7556275423efaaad6df54ba9beae
TEMPLATE "{{ if .System }}<|start_header_id|>system<|end_header_id|>
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
{{ .Response }}<|eot_id|>"
PARAMETER stop <|start_header_id|>
PARAMETER stop <|end_header_id|>
PARAMETER stop <|eot_id|>
PARAMETER num_keep 24
上記を見る限り、モデルは所定のパスにコピーされて管理される、Modelfileもそれに合わせて管理される、ようなので、作成時に使用したモデルのGGUFファイルやModelfileは多分もう不要だと思う。
Web UI (Open WebUI)
GUIでアクセスできるように、Open WebUIをインストールする。
ドキュメントでは複数のインストール方法が記載されていて、最初からOpen WebUIを使う前提ならば、Ollamaも含めてDockerでコマンド一発でセットアップできたりするっぽいのだけど。
$ docker run -d \
-p 3000:8080 \
--gpus=all \
-v ollama:/root/.ollama \
-v open-webui:/app/backend/data \
--name open-webui \
--restart always \
ghcr.io/open-webui/open-webui:ollama
自分の場合はOllama単体を既にDockerで動かしているので、いろいろやってみて以下のようになった。READMEのTroubleShootingに記載されているものとほぼ同じ。この場合はブラウザでアクセスする際のポートが3000番から8080番に変わる。なお、こちらもボリュームはバインドマウントにした。
$ docker run -d \
--network=host \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
-v ./data:/app/backend/data \
--name open-webui \
--restart always \
ghcr.io/open-webui/open-webui:main
起動したらブラウザで8080番ポートにアクセス、こんな画面が表示される。
最初にアカウントを作成する。sign up
をクリック。
必要事項を入力してアカウントを作成。
ログインできた。
モデルはこちらから選択。Ollamaでインストールしたものが表示されているのがわかる。
OllamaのLlama-3-ELYZA-JP-8Bでチャットしてみた。問題なく動作している。
他にも機能はたくさんあるみたいなので、ドキュメント参照。
まとめ
Ollama、全然調べてなくて、なんとなくめんどくさそうなイメージを持っていたのだけど、やってみたら全然簡単で、手軽に使えそう。
試してないけど、PythonやJSのクライアント向けライブラリもある。
あとはLangChainやLlamaIndexなどでもインテグレーションされている。
自分は環境維持のしやすさみたいなところでDockerを使ったけども、Ollama、そんな複雑なものでもないので、以下の記事を見てて、直接インストールするほうがいいかもしれないなーと思い出してきた。
上の記事にあるような、Dockerの管理コストについては、逆に言うと使うことによって得られるメリットもあると思うので(当然デメリットもある)、一概にDockerを否定するものではない。
例えば、Ollamaを1つのコンポーネントとして、それ以外に多数のコンポーネントと連携するようなアプリを作りたい、みたいなケース(K8S使うとか)なら、デメリットを打ち消すだけのメリットが見いだせるケースもあるかなとは思う。
上記のQiitaの記事、パラメータの説明が豊富。
ふと気づいたんだけど、いい感じにGPUオフロード調整してくれるっぽい。すごいな。
$ ollama ps
NAME ID SIZE PROCESSOR UNTIL
karakuri-lm-8x7b-instruct:q4_k_m 0053fa858528 31 GB 25%/75% CPU/GPU 4 minutes from now
GUIとしては、Open WebUIやAnythingLLM以外にも以下のようなものがある。
ollamate
参考)
Ollamate: 普段使いのOllamaデスクトップクライアント
Ollamateは、Ollamaを中心に構築されたオープンソースのChatGPTライクなデスクトップクライアントで、同様の機能を提供するが、完全にローカルである。Ollamaを介してLlama 3、Qwen2、Phi3などのローカルLLMモデルを活用し、プライバシーとオフライン機能を保証する。
特徴
- ローカルLLMモデル: Llama 3、Qwen2、Phi3などのオープンソースLLMをローカルで使用できる。
- ユーザーフレンドリー:Ollamaをインストールしたエンドユーザー向けに、シンプルなバイナリをダウンロード(現在はApple Silicon Mac、WindowsとLinuxは後日)。
- 開発者に優しい: オープンソースで、GitHubでコントリビュートできる。
Macのみ。Electronで作られているっぽくて、バイナリをインストールすればよいだけ。
ブラウザじゃなくてローカルアプリってのがいいのかもね。
ただ試してみた感じだと日本語IMEの変換確定のENTERで送信されてしまう、あるある問題がある。
Ollama Grid Search
参考)
Ollamaグリッド検索とA/Bテストデスクトップアプリ
LLMモデル、プロンプト、モデルパラメータを評価するRustベースのツール。
目的
このプロジェクトは、与えられたユースケースに最適なモデル、プロンプト、推論パラメータを選択するプロセスを自動化する。
Ollamaがインストールされ、localhostまたはリモートサーバーでエンドポイントにサービスを提供していることを前提とする。
機能
- ローカルまたはリモートのOllamaサーバーからモデルを自動的に取得する;
- 様々なモデル、プロンプト、パラメータを繰り返し、推論を生成する;
- 異なるプロンプトを複数のモデルで同時にA/Bテストする;
- 各パラメータの組み合わせに対して複数の反復を許可する;
- 限定的な同時実行または同期推論呼び出しを許可する(サーバーへのスパムを防ぐため);
- 推論パラメータと応答メタデータ(推論時間、トークン、トークン/秒)をオプションで出力できる;
- 個々の推論コールのリフェッチ;
- モデル選択は名前でフィルターできる;
- JSON形式でダウンロード可能な実験リスト;
- 実験は可読ビューで検査できる;
- 設定可能な推論タイムアウト;
- カスタムデフォルトパラメータとシステムプロンプトを設定で定義できる:
復数のモデルを同時にテストできる、みたいなのがウリっぽい。こちらもインストーラが用意されている。
ただし、Apple Siliconの場合、aarch64.dmgからインストールしてアプリを起動すると、アプリが壊れていると言われる。Workaroundは以下。
Ollama関連の情報はRedditで探すのが良さげな感がある
Ollama専用ではないけどこんなのもある
- Dockerでインストールするのが楽→手順
- バックエンドにOllamaを使うことができる
- その場合はChat CompletionでOllamaのOpenAI互換APIを使うと良い
- 接続先は
http://host.docker.internal:11434/v1
とかにすれば良い
諸々の設定はこのあたりが参考になる
サイドバーで見ているページについてチャットができるChrome拡張。
Ollamaがlocalhostで動いている場合は気にしなくてよいが、例えばLAN内のリモートサーバで動いている場合には以下の設定が必要。
- Chrome拡張をダウンロードしてmanfiest.jsonの以下の箇所にリモートサーバのURLを追記する。例えばリモートサーバが192.168.0.1だったら以下のような感じ。
(snip)
"content_security_policy": {
"extension_pages": " default-src 'self' 'unsafe-eval' http://localhost:* http://127.0.0.1:* http://192.168.1.0:* https://api.groq.com https://html.duckduckgo.com https://generativelanguage.googleapis.com https://search.brave.com; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://fonts.gstatic.com; font-src 'self' https://fonts.googleapis.com https://fonts.gstatic.com; img-src 'unsafe-inline' 'self' data: https://upload.wikimedia.org; "
}
(snip)
- リモートサーバのOllamaで以下の環境変数を与えて起動。
# リモートからの接続を許可
OLLAMA_HOST=0.0.0.0
# OriginヘッダにChrome拡張のURIスキーマを追加。URIは拡張を読み込んだあとで表示されるものを参考に。
OLLAMA_ORIGINS=chrome-extension://abcdefghtijklmnopqrstuvwxyz
あとは、sidellamaの設定からリモートサーバのURLを追加すればOK。
参考)
Ollamaをワンライナーでインストールした場合
$ curl -fsSL https://ollama.com/install.sh | sh
アップデートも同じでいいみたいなのだけど、
Update
Update ollama by running the install script again:
curl -fsSL https://ollama.com/install.sh | sh
Or by downloading the ollama binary:
sudo curl -L https://ollama.com/download/ollama-linux-amd64 -o /usr/bin/ollama sudo chmod +x /usr/bin/ollama
例えば、systemdのsystem-unit-fileで環境変数したりというようなカスタマイズをしている場合、前者だとまるっと上書きされてしまう模様。
別の記事でも書いたけど、自分はもうDocker使うまでもない・カスタムモデルの組み込みがひと手間かかると感じたので(とはいえ、ほんとはDockerは使って環境を隔離化してアップデートも楽にしたい、何するかわからないインストールスクリプトをいちいち中身確認したくない、という思いは今でもある)、今は上記のワンライナーを使ってインストールしたのだが、環境変数いろいろ設定しているので、後者のやり方でアップデートするようにしている。
$ sudo systemctl stop ollama
$ sudo curl -L https://ollama.com/download/ollama-linux-amd64 -o /usr/local/bin/ollama
$ sudo chmod +x /usr/local/bin/ollama
$ sudo systemctl start ollama