Ollama x Open WebUI で、IBMが作ったLLM「Granite Code」を動かすまでの備忘録

# 概要
この記事では、学生や企業の従業員、自治体の職員など、Open WebUIを通じて、複数人がWebサービスとして共同利用する生成AIを作成する手順の備忘録です。
LLMとして、IBMが公開している、商用利用が可能な「Granite Code」を使っています。「Granite Code」の代わりに、Meta社の「Llama3」などの他のLLMでも構いません。

LLMを動かすツール「Ollama」を使い、OllamaをAPI経由でLLMを使う仕組みとWebUIを用意し、ユーザー管理機能のある生成AIサービスをIBM Cloud Virtual Serverを使って作ります。

# 必要な作業
1. サーバーの用意（例 IBM Cloud Virtual Server）
1. Dockerのインストール
1. Ollamaのインストール
1. Ollamaの動作確認
1. OllamaのAPIを使うためのリバースプロキシの構築
1. curlを使ったOllamaのAPI接続および動作確認
1. Open WebUI の起動
1. Open WebUI に管理者ユーザーを登録
1. Open WebUI の日本語化
1. Open WebUI の動作確認

# 作業の実施
## サーバーの用意（例 IBM Cloud Virtual Server）
IBM Cloud Virtual Serverを使っており、IBM Cloud Virtual Server for VPCとIBM Cloud Virtual Server for Classic、どちらでも構いません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/94053310-a907-239d-36d1-e0ff88b310ab.png)

IBM Cloudは、商用利用可能なオープンソースソフトウェアを多く使っているとされ、自宅サーバー等で確認した動作を再現しやすく、素直な挙動が特徴とされています。

- [IBM Cloud Virtual Server for VPC](https://www.ibm.com/jp-ja/products/virtual-servers)
- [IBM Cloud Virtual Server for Classic](https://www.ibm.com/jp-ja/products/virtual-servers-classic)

検証などで短期間の使用は、IBM Cloud Virtual Server for ClassicのTransient ServerでVMを作成にすることで、運用コストを低く抑えることができます。

### 使用したサーバーのスペック
本資料は、以下のスペックのVM（仮想サーバー）を用意しました。
- OSは、Ubuntu Server 22.04(2024年5月現在)
- vCPUは、4つ以上
- メモリは、32GB以上
- パブリックIPとして、169.45.xxxx.xxx を使用
- 80番と3000番ポートでアクセス可能にする

今回使う「Granite Code」は20Bを使うので、メモリ多めで処理するようにします。個人的には、外部GPUは予算があれば使う方針です。ノートパソコンで20B以上のLLMを使うには、メモリ32GB以上が必要です。

### 作業用ユーザの作成
用意したVMは、rootユーザーしかないので、作業用のユーザーを作成します。
```
adduser workuser1
```
sudo権限を追加します。
```
usermod -aG sudo workuser1
```
exitコマンドを実行し、ログアウトします。作成したユーザーでログインします。
```
exit
```
作成した作業用ユーザーで、SSH接続して作業を再開します。

### タイムゾーン設定

時刻設定を日本時間に合わせるため、次のコマンドを実行します。
```
sudo apt update -y
sudo apt upgrade -y
sudo timedatectl set-timezone Asia/Tokyo
```

## Dockerのインストール
パソコンやサーバー上でLLMを動かすツールの「Ollama」を使うためのWebUIは、Dockerを使い、アプリケーションコンテナとして動作するので、Dockerをインストールします。
```
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
VMの作業用ユーザーでDockerを実行できるように、次のコマンドを実行します。
```
getent group docker
sudo gpasswd -a $USER docker
```
ログアウトして、再度SSH接続します。
```
exit
```
ログアウト後、SSHで接続してください。

## Ollamaのインストール
次のコマンドを実行します。
```
curl -fsSL https://ollama.com/install.sh | sh
```
## OllamaによるLLMの動作確認
### Llama3 の場合
次のコマンドを実行します。
```
ollama run llama3
```
LLM「Llama3」のダウンロードとOllamaによるLLMの起動が行われます。
実行結果として、以下が表示されれば成功です。
```
>>> Send a message (/? for help)
```
次のプロンプトを入れて、動作を見てみましょう。
```
新潟県の県庁所在地はどこですか？日本語で答えてください。
```
結果表示後、ctrl + D キーで、プロンプト入力待ちの状態が止まります。

### Granite Code 20Bの場合
次のコマンドを実行します。
```
ollama run granite-code:20b
```
LLM「Granite Code:20B」のダウンロードとOllamaによるLLMの起動が行われます。
実行結果として、以下が表示されれば成功です。
```
>>> Send a message (/? for help)
```
次のプロンプトを入れて、動作を見てみましょう。
```
Please create code of "print hello world" in Python
```
結果表示後、ctrl + D キーで、プロンプト入力待ちの状態が止まります。

## OllamaのAPIを使うためのリバースプロキシの構築
OllamaをAPIとして利用できるように、リバースプロキシ環境を用意します。
次のコマンドを実行します。
### nginxのインストール
nginx.listの作成
```
sudo nano /etc/apt/sources.list.d/nginx.list
```
nginx.listに、下記を記述します。
```
deb https://nginx.org/packages/ubuntu/ jammy nginx 
deb-src https://nginx.org/packages/ubuntu/ jammy nginx
```
次のコマンドを実行します。
```
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ABF5BD827BD9BF62 
sudo apt update
```
コマンドを実行し、nginxをインストールし、起動します。
```
sudo apt install nginx
sudo systemctl start nginx
```
### OllamaをAPI利用するためのリバースプロキシ設定ファイルの作成
リバースプロキシ用の設定ファイルを作成するため、次のコマンドを実行します。
```
sudo nano /etc/nginx/conf.d/ollama.conf
```
以下を記述します。動作確認のため server_name にIPアドレスを記述しています。独自ドメインにするかは各自で判断しましょう。
```
server {
    listen 80;
    server_name 169.45.xxxx.xxx;  # Replace with your domain or IP
    location / {
        proxy_pass http://localhost:11434;
        proxy_set_header Host localhost:11434;
    }
}
```
OllamaのAPIは、localhost:11434を使うので、リバースプロキシ経由でアクセスできるようにします。リバースプロキシ用の設定ファイルを読み込み、nginxを再起動します。
```
sudo systemctl daemon-reload
sudo systemctl restart nginx
```
### curlを使ったOllamaのAPI接続および動作確認
次のコマンドを実行します。
```
curl http://169.45.xxxx.xxx/api/generate -d '{ "model": "llama3", "prompt": "新潟県の県庁所在地はどこですか？日本語で答えてください。", "stream": false }'
```
http://169.45.xxxx.xxx/api/generate に接続し、LLM名を指定、プロンプトを指定することで結果を得ることができます。

## Open WebUI の起動
次のコマンドを実行します。OLLAMA_BASE_URLに、先ほどインストールしたnginxを指定します。
```
docker run -d -p 3000:8080 -e OLLAMA_BASE_URL=http://169.45.xxx.xxx -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:main
```
実行後、Webブラウザで、VMの3000番ポートにアクセスします。
アクセス先 http://169.45.xxx.xxx:3000
以下が表示されれば、正常に動作していることを示します。Open WebUIが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/ecd2cc34-9e01-1acc-fcb2-1bef06a03f40.png)

## Open WebUI に管理者ユーザーを登録
最初の作業として、管理者ユーザーを登録します。「Sing up」をクリックします。
「Name」「Email」「Password」の各項目を入れ、「Create Account」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/9832cfb4-4d86-4ed9-dea5-f352f2c118b7.png)

「What's New in Open WebUI」が表示されるので、「Okay, Let's Go!」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/138b2204-836c-7235-235f-bc144daeee8d.png)

登録したユーザーで使用可能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/47d12818-92cf-ca38-c021-8a6248504366.png)

画面左下のユーザー名をクリックすることで、「Settings（設定画面）」やユーザー管理を行う「Admin Panel」が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/e48ffef6-6a4a-8b52-65b9-d4a93aac8a76.png)

## Open WebUI の日本語化
Open WebUIの表示を日本語化しましょう。
画面左下のユーザー名をクリックし、「Settings（設定画面）」をクリックします。
「Settings」の画面で、「Language」で「Japanese」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/7b65801b-e11a-162b-4103-bd40b3771d81.png)
「保存」をクリックします。「設定」画面の右上の「X」をクリックし、「設定」画面を閉じます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/32de7959-a4de-8deb-466d-ae328af99cda.png)

## Open WebUI の動作確認
「Ollamaのインストール」で使用したLLMを使って、Open WebUIの動作確認を行います。
### モデルの選択
Open WebUIの中央左上あたりで、「モデルの選択」から、「granite-code:20b」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/a9f62688-633c-666d-ae9b-289e10b54a59.png)
これで、「Granite Code」を使い、入力されたプロンプトに対して、コードを生成するようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/3125ee67-4353-4937-4ab9-53d9bac8c1c4.png)

### Granite Codeを使ったコード生成の動作確認
プロンプトを入力し、送信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/3e9f7128-3fc3-5105-08cf-2e9f6db3d9a1.png)
下図のように表示されます。コードが生成されたら「Run」をクリックすることで、コードの実行結果を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41414/83379632-d052-3c11-ab90-78c0bc16c1a8.png)

# まとめ
本記事では、LLM実行ツールの「Ollama」と「Ollama」のUIである「Open WebUI」、IBMが提供するLLMの「Granite Code」を使い、複数人で利用できる生成AIサービスとして仕立てるまでの手順をまとめました。
LLMを「Llama3」などの他のLLMを使うことで、コード生成以外に文章生成ができます。