Closed17

OllamaをUbuntuサーバでセットアップしてLlama-3-ELYZA-JP-8Bを試す

kun432kun432

なかなか手がつけれていなかったOllamaを触ってみる。LAN内のUbuntu 22.04サーバ(RTX4090)にセットアップしてみようと思う。

Ollamaの概要

https://ollama.com/

https://github.com/ollama/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あたりと同じ位置づけに思える。

kun432kun432

インストール

インストール方法は以下の3つがある様子。

  • セットアップスクリプト
  • 手動
  • Docker

あと、MacならHomebrew経由でもインストールできるっぽい。

今回はDockerを使うことにする。

https://hub.docker.com/r/ollama/ollama

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
kun432kun432

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 |
kun432kun432

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だと以下のように多くのタグがある。パラメータサイズやエイリアス、量子化バリエーションなどをタグを使い分けることで指定できる様子。

https://ollama.com/library/phi3/tags

タグ指定して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
``
kun432kun432

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リファレンスを参照。

https://github.com/ollama/ollama/tree/main/docs/api.md

あと、

モデルをロードしておく必要はないが、事前にインストールされている必要はある。

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つだけというように思えるが、このあたりは設定で変えたり出来ないのかなーと思ったら、実験的ステータスだけど設定でできるっぽい。

https://qiita.com/Tadataka_Takahashi/items/68f5e5d1bcab4abe9f47

kun432kun432

カスタムモデル

Ollamaがデフォルトで対応していないモデルをカスタムで使うこともできる。

https://github.com/ollama/ollama#customize-a-model

https://github.com/ollama/ollama/tree/main/docs/modelfile.md

必要なもの

  • モデルのGGUFフォーマット
  • Modelfile

ちょうど Llama-3-ELYZA-JP-8Bがリリースされたところなのでこれを使ってやってみる。Llama-3-ELYZA-JP-8Bは公式からGGUFフォーマット(Q4_K_M)で提供されているので、GGUF変換不要でそのままいけそう。

https://huggingface.co/elyza/Llama-3-ELYZA-JP-8B-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をこんな感じで作成。

modelfile-llama-3-elyza-jp-8b-q4_k_m
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は多分もう不要だと思う。

kun432kun432

Web UI (Open WebUI)

GUIでアクセスできるように、Open WebUIをインストールする。

https://github.com/open-webui/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でチャットしてみた。問題なく動作している。

他にも機能はたくさんあるみたいなので、ドキュメント参照。

https://docs.openwebui.com/

kun432kun432

まとめ

Ollama、全然調べてなくて、なんとなくめんどくさそうなイメージを持っていたのだけど、やってみたら全然簡単で、手軽に使えそう。

kun432kun432

自分は環境維持のしやすさみたいなところでDockerを使ったけども、Ollama、そんな複雑なものでもないので、以下の記事を見てて、直接インストールするほうがいいかもしれないなーと思い出してきた。

https://qiita.com/kiyotaman/items/1aeb098b5ff0d6d5e641

上の記事にあるような、Dockerの管理コストについては、逆に言うと使うことによって得られるメリットもあると思うので(当然デメリットもある)、一概にDockerを否定するものではない。
例えば、Ollamaを1つのコンポーネントとして、それ以外に多数のコンポーネントと連携するようなアプリを作りたい、みたいなケース(K8S使うとか)なら、デメリットを打ち消すだけのメリットが見いだせるケースもあるかなとは思う。

kun432kun432

上記のQiitaの記事、パラメータの説明が豊富。

kun432kun432

ふと気づいたんだけど、いい感じに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
kun432kun432

GUIとしては、Open WebUIやAnythingLLM以外にも以下のようなものがある。

ollamate

参考)
https://www.reddit.com/r/ollama/comments/1dhzffc/ollamate_open_source_ollama_desktop_client_for/

https://github.com/humangems/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で送信されてしまう、あるある問題がある。

参考)

https://www.reddit.com/r/LocalLLaMA/comments/1e0o540/new_release_of_ollama_grid_search_v051/

https://github.com/dezoito/ollama-grid-search

Ollamaグリッド検索とA/Bテストデスクトップアプリ

LLMモデル、プロンプト、モデルパラメータを評価するRustベースのツール。

目的

このプロジェクトは、与えられたユースケースに最適なモデル、プロンプト、推論パラメータを選択するプロセスを自動化する。

Ollamaがインストールされ、localhostまたはリモートサーバーでエンドポイントにサービスを提供していることを前提とする。

機能

  • ローカルまたはリモートのOllamaサーバーからモデルを自動的に取得する;
  • 様々なモデル、プロンプト、パラメータを繰り返し、推論を生成する;
  • 異なるプロンプトを複数のモデルで同時にA/Bテストする;
  • 各パラメータの組み合わせに対して複数の反復を許可する;
  • 限定的な同時実行または同期推論呼び出しを許可する(サーバーへのスパムを防ぐため);
  • 推論パラメータと応答メタデータ(推論時間、トークン、トークン/秒)をオプションで出力できる;
  • 個々の推論コールのリフェッチ;
  • モデル選択は名前でフィルターできる;
  • JSON形式でダウンロード可能な実験リスト;
  • 実験は可読ビューで検査できる;
  • 設定可能な推論タイムアウト;
  • カスタムデフォルトパラメータとシステムプロンプトを設定で定義できる:

復数のモデルを同時にテストできる、みたいなのがウリっぽい。こちらもインストーラが用意されている。

ただし、Apple Siliconの場合、aarch64.dmgからインストールしてアプリを起動すると、アプリが壊れていると言われる。Workaroundは以下。

https://github.com/dezoito/ollama-grid-search/issues/16#issuecomment-2084445890

kun432kun432

Ollama関連の情報はRedditで探すのが良さげな感がある

kun432kun432

サイドバーで見ているページについてチャットができるChrome拡張。

https://github.com/gyopak/sidellama

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。

参考)

https://github.com/ollama/ollama/issues/2425

kun432kun432

Ollamaをワンライナーでインストールした場合

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

アップデートも同じでいいみたいなのだけど、

https://github.com/ollama/ollama/blob/main/docs/linux.md#update

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
このスクラップは5ヶ月前にクローズされました