1. はじめに
いくらセキュリティー的に問題がないと言われていても、ブラックボックスになっているSaaSを使うのはやはり怖い、などの理由で自分だけのAIをローカルで動かしたいという要件はあるものです。
今回は、Open AIから最近リリースされたgpt-ossをIBM Cloud上のVSIで試したいと思います。
前回は、GUI機能が充実している LM Studio をWindows Server上で試しましたが、今回は CLIベースで動かすことが想定されている Ollama を利用します。Ollamaは ollama run llama2 のように、コマンド一発でモデルの取得と実行が可能で、外部からのAPI呼び出しにも対応しているため、Linux環境などでのホスティングに適しています。さらに、Ollama本体はMITライセンスのオープンソースであり、コードの透明性も確保されています。UIは標準では付属していませんが、Open WebUI などと組み合わせることで、ブラウザ経由での利用も可能です。
2. GPU環境のセットアップ
RHEL9 + NVIDIA A100環境にNVIDIA Driver/CUDA Toolkitをインストールするを実行します。
なお、Ollamaはデフォルトでは48 GiB VRAM以上の場合には、256kのcontext lengthが使われます。
https://docs.ollama.com/context-length#context-length
3. Ollamaのインストール
[root@syasuda-ollama ~]# curl -fsSL https://ollama.com/install.sh | sh
>>> Installing ollama to /usr/local
>>> Downloading Linux amd64 bundle
######################################################################## 100.0%
>>> Creating ollama user...
>>> Adding ollama user to render group...
>>> Adding ollama user to video group...
>>> Adding current user to ollama group...
>>> Creating ollama systemd service...
>>> Enabling and starting ollama service...
Created symlink /etc/systemd/system/default.target.wants/ollama.service → /etc/systemd/system/ollama.service.
>>> NVIDIA GPU installed.
[root@syasuda-ollama ~]# ollama --version
ollama version is 0.11.8
[root@syasuda-ollama ~]# ollama list
NAME ID SIZE MODIFIED
ちなみにOllamaのバージョンアップをする際には、同様に上記のコマンドを実行するだけです。
4. Ollama + gpt-oss:20bのテスト
[root@syasuda-ollama ~]# ollama pull gpt-oss:20b
pulling manifest
pulling b112e727c6f1: 100% ▕██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 13 GB
pulling fa6710a93d78: 100% ▕██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 7.2 KB
pulling f60356777647: 100% ▕██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 11 KB
pulling d8ba2f9a17b3: 100% ▕██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 18 B
pulling 55c108d8e936: 100% ▕██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 489 B
verifying sha256 digest
writing manifest
success
[root@syasuda-ollama ~]# ollama ls
NAME ID SIZE MODIFIED
gpt-oss:20b aa4295ac10c3 13 GB 38 seconds ago
[root@syasuda-ollama ~]# ls -l /usr/share/ollama/.ollama/models/blobs/
total 13457216
-rw-r--r--. 1 ollama ollama 489 Aug 27 00:17 sha256-55c108d8e93662a22dcbed5acaa0374c7d740c6aa4e8b7eee7ae77ed7dc72a25
-rw-r--r--. 1 ollama ollama 13780154624 Aug 27 00:17 sha256-b112e727c6f18875636c56a779790a590d705aec9e1c0eb5a97d51fc2a778583
-rw-r--r--. 1 ollama ollama 18 Aug 27 00:17 sha256-d8ba2f9a17b3bbdeb5690efaa409b3fcb0b56296a777c7a69c78aa33bbddf182
-rw-r--r--. 1 ollama ollama 11353 Aug 27 00:17 sha256-f60356777647e927149cbd4c0ec1314a90caba9400ad205ddc4ce47ed001c2d6
-rw-r--r--. 1 ollama ollama 7240 Aug 27 00:17 sha256-fa6710a93d78da62641e192361344be7a8c0a1c3737f139cf89f20ce1626b99c
[root@syasuda-ollama ~]# ollama run gpt-oss:20b
>>> なぜ空は青いの?
Thinking...
We need to answer in Japanese. The question: "なぜ空は青いの?" Explanation: Rayleigh scattering, shorter wavelengths scatter, scattering intensity ~1/λ^4, blue light scattered, longer wavelengths less. Also mention
atmospheric composition, scattering by air molecules, Rayleigh scattering, etc. Also mention that sky appears blue to human eye because of color sensitivity and scattering. Could mention the Sun's light composition,
scattering, difference in daylight, twilight, etc. Provide concise explanation. Also mention the physics formula. Maybe mention other phenomena. Provide explanation that it's due to Rayleigh scattering and the composition of
the atmosphere, scattering by molecules, not due to absorption. Provide reference to Mie scattering for larger particles causing white or orange haze. Also mention that at sunset, the sun's light passes through more
atmosphere, scattering blue out, leaving reds. Provide final answer.
...done thinking.
**空が青い理由は、太陽光が大気中の分子に散乱される「レイリー散乱」が主な原因です。**
---
## 1. 太陽光のスペクトル
太陽から出る光は「可視光」に加えて紫外線や赤外線も含む全光(スペクトル)です。
可視光の中で青〜紫の波長(≈400 – 500 nm)が短く、赤〜黄の波長(≈600 – 700 nm)が長いです。
---
## 2. レイリー散乱とは?
- **散乱**:光が物質(分子や小さな粒子)に衝突して方向を変えること。
- **レイリー散乱**:散乱する粒子(空気分子・水蒸気分子など)が光の波長よりもずっと小さい(≈10⁻⁶ m ≪ 波長)ときに起こる。
- その散乱強度は
\[
I \propto \frac{1}{\lambda^4}
\]
(λ=波長)という関係で決まり、波長が短いほど強く散乱されます。
---
## 3. 青い空が生まれるメカニズム
1. **太陽光が大気に入射**
太陽光は大気を透過しながら、空気分子に衝突します。
2. **波長依存の散乱**
波長が短い青〜紫の光は、λ⁴の逆数に比例して強く散乱されます。
逆に波長が長い赤や黄の光は散乱が弱く、ほぼ直進します。
3. **散乱された光が私たちの目に届く**
散乱された青い光は大気全体に広がり、空のあらゆる方向から見ると「青い光」が主になるため、空全体が青く見えます。
---
## 4. なぜ赤い夕日になるのか?
夕方になると、太陽光は地平線に近い長い経路を通るため、
- 青い光が**大量に散乱**されて大気外へ散去。
- 残った赤〜黄の長波長光だけが到達し、地面や空に赤く映ります。
---
## 5. まとめ
- **空が青い**のは、**大気中の分子が太陽光をレイリー散乱**し、短い波長(青)が強く散乱されるからです。
- その散乱の強度は波長の4乗の逆数に比例するため、青が際立ちます。
- 夕暮れ時は散乱の量が増えるため、青は消えて赤くなるという美しい現象になります。
---
**レイリー散乱**は光と物質の「サイズ差」によって決まる自然の光学現象であり、空の青さはその典型的な例と言えます。
[root@syasuda-ollama ~]# ollama ps
NAME ID SIZE PROCESSOR CONTEXT UNTIL
gpt-oss:20b aa4295ac10c3 14 GB 100% GPU 8192 3 minutes from now
[root@syasuda-ollama ~]# nvidia-smi
Wed Aug 27 00:22:56 2025
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.65.06 Driver Version: 580.65.06 CUDA Version: 13.0 |
+-----------------------------------------+------------------------+----------------------+
| 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 A100 80GB PCIe Off | 00000000:04:01.0 Off | 0 |
| N/A 47C P0 73W / 300W | 13971MiB / 81920MiB | 0% Default |
| | | Disabled |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| 0 N/A N/A 2835 C /usr/local/bin/ollama 13962MiB |
+-----------------------------------------------------------------------------------------+
>>> (Ctrl + D)でターミナルに戻る。
[root@syasuda-ollama ~]# ollama stop gpt-oss:20b
5. 外部へのサービス公開とモデルの配置場所などの変更
将来的にOllamaをAPI経由でアクセスするための準備をします。
5-1. サービス公開: OLLAMA_HOST
デフォルトではlocalhost(127.0.0.1)からのみアクセス可能です。
[root@syasuda-ollama ~]# ss -anpt | grep -e State -e ollama
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.1:11434 0.0.0.0:* users:(("ollama",pid=145875,fd=3))
よって、任意のアドレスからアクセスできるように変更します。
5-2. モデルの配置先: OLLAMA_MODELS
Ollamaはデフォルトで/usr/share/ollama/.ollama/models/にモデルを配置するので、領域を圧迫する可能性があります。このタイミングで変更しておきます。今回はあらかじめ/workにBlock Storageを作成しているので、そちらにモデルを配置するように変更します。
5-3. モデルの自動アンロードの禁止: OLLAMA_KEEP_ALIVE
Ollamaにロードされたモデルは自動的に5分でアンロードされてしまうため、アンロードを防ぐ設定を行います。
5-4. 複数のモデルのロード: OLLAMA_MAX_LOADED_MODELS
デフォルトではロードできるモデルは1つです。今回は3つまでに増やします。
5-5. 複数クエリーの受付: OLLAMA_NUM_PARALLEL
それぞれのモデルが複数のクエリーを受けた場合にデフォルトでは1つの問合せしか受け付けられないため、今回は3つにまで増やすことにします。
5-6. Flash Attension設定: OLLAMA_FLASH_ATTENTIONおよびOLLAMA_KV_CACHE_TYPE
最近のモデルではFLASH_ATENSIONを有効にできるモデルが増えてきているため有効にします。
5-7. モデルの自動ロード: ExecStartPost
systemctl start ollamaをするだけではモデルは自動ロードされません。このままだと初回アクセス時に時間がかかるため、ollamaを起動するタイミングで自動起動しておきます。
5-8. 設定方法
[root@syasuda-ollama ~]# ollama rm gpt-oss:20b
[root@syasuda-ollama ~]# ollama ls
NAME ID SIZE MODIFIED
[root@syasuda-ollama ~]# systemctl stop ollama
[root@syasuda-ollama ~]# mkdir -p /work/ollama
[root@syasuda-ollama ~]# chown -R ollama:ollama /work/ollama
[root@syasuda-ollama ~]# systemctl edit ollama.service
### Editing /etc/systemd/system/ollama.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_MODELS=/work/ollama/models"
Environment="OLLAMA_KEEP_ALIVE=-1"
Environment="OLLAMA_MAX_LOADED_MODELS=3"
Environment="OLLAMA_NUM_PARALLEL=3"
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"
ExecStartPost=/bin/sh -c '(sleep 5; echo "" | ollama run gpt-oss:20b >/dev/null 2>&1) &'
ExecStartPost=/bin/sh -c '(sleep 5; echo "" | ollama run qwen3.5 >/dev/null 2>&1) &'
### Lines below this comment will be discarded
### /etc/systemd/system/ollama.service
# [Unit]
# Description=Ollama Service
# After=network-online.target
#
# [Service]
# ExecStart=/usr/local/bin/ollama serve
# User=ollama
# Group=ollama
# Restart=always
# RestartSec=3
# Environment="PATH=/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
#
# [Install]
# WantedBy=default.target
[root@syasuda-ollama ~]# systemctl cat ollama.service
# /etc/systemd/system/ollama.service
[Unit]
Description=Ollama Service
After=network-online.target
[Service]
ExecStart=/usr/local/bin/ollama serve
User=ollama
Group=ollama
Restart=always
RestartSec=3
Environment="PATH=/usr/local/cuda-13.0/bin:/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
[Install]
WantedBy=default.target
# /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_HOST=0.0.0.0:11434"
Environment="OLLAMA_MODELS=/work/ollama/models"
Environment="OLLAMA_KEEP_ALIVE=-1"
Environment="OLLAMA_MAX_LOADED_MODELS=3"
Environment="OLLAMA_NUM_PARALLEL=3"
Environment="OLLAMA_FLASH_ATTENTION=1"
Environment="OLLAMA_KV_CACHE_TYPE=q8_0"
ExecStartPost=/bin/sh -c '(sleep 5; echo "" | ollama run gpt-oss:20b >/dev/null 2>&1) &'
ExecStartPost=/bin/sh -c '(sleep 5; echo "" | ollama run qwen3.5 >/dev/null 2>&1) &'
[root@syasuda-ollama ~]# systemctl show ollama.service | grep -i -e Environment -e ExecStartPost
ExecStartPost={ path=/bin/sh ; argv[]=/bin/sh -c (sleep 5; echo "" | ollama run gpt-oss:20b >/dev/null 2>&1) & ; ignore_errors=no ; start_time=[Sun 2026-05-17 18:06:36 JST] ; stop_time=[Sun 2026-05-17 18:06:36 JST] ; pid=1180 ; code=exited ; status=0 }
ExecStartPost={ path=/bin/sh ; argv[]=/bin/sh -c (sleep 5; echo "" | ollama run qwen3.5 >/dev/null 2>&1) & ; ignore_errors=no ; start_time=[Sun 2026-05-17 18:06:36 JST] ; stop_time=[Sun 2026-05-17 18:06:36 JST] ; pid=1187 ; code=exited ; status=0 }
ExecStartPostEx={ path=/bin/sh ; argv[]=/bin/sh -c (sleep 5; echo "" | ollama run gpt-oss:20b >/dev/null 2>&1) & ; flags= ; start_time=[Sun 2026-05-17 18:06:36 JST] ; stop_time=[Sun 2026-05-17 18:06:36 JST] ; pid=1180 ; code=exited ; status=0 }
ExecStartPostEx={ path=/bin/sh ; argv[]=/bin/sh -c (sleep 5; echo "" | ollama run qwen3.5 >/dev/null 2>&1) & ; flags= ; start_time=[Sun 2026-05-17 18:06:36 JST] ; stop_time=[Sun 2026-05-17 18:06:36 JST] ; pid=1187 ; code=exited ; status=0 }
Environment=PATH=/usr/local/cuda-13.0/bin:/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin OLLAMA_HOST=0.0.0.0:11434 OLLAMA_MODELS=/work/ollama/models OLLAMA_KEEP_ALIVE=-1 OLLAMA_MAX_LOADED_MODELS=3 OLLAMA_NUM_PARALLEL=3 OLLAMA_FLASH_ATTENTION=1 OLLAMA_KV_CACHE_TYPE=q8_0
[root@syasuda-ollama ~]# systemctl start ollama.service
[root@syasuda-ollama ~]# ss -anpt | grep -e State -e ollama
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.1:40427 0.0.0.0:* users:(("ollama",pid=3060,fd=4))
LISTEN 0 4096 127.0.0.1:45655 0.0.0.0:* users:(("ollama",pid=3116,fd=4))
LISTEN 0 4096 *:11434 *:* users:(("ollama",pid=2934,fd=4))
[root@syasuda-ollama ~]# ollama ps
NAME ID SIZE PROCESSOR CONTEXT UNTIL
gpt-oss:20b 17052f91a42e 21 GB 100% GPU 131072 Forever
qwen3.5:latest 6488c96fa5fa 17 GB 100% GPU 262144 Forever
[root@syasuda-ollama ~]# ls -l /usr/share/ollama/.ollama/models/blobs
total 0
[root@syasuda-ollama ~]# ls -l /work/ollama/models/blobs/
total 13457212
-rw-r--r--. 1 ollama ollama 489 Sep 3 12:35 sha256-55c108d8e93662a22dcbed5acaa0374c7d740c6aa4e8b7eee7ae77ed7dc72a25
-rw-r--r--. 1 ollama ollama 13780154624 Sep 3 12:35 sha256-b112e727c6f18875636c56a779790a590d705aec9e1c0eb5a97d51fc2a778583
-rw-r--r--. 1 ollama ollama 18 Sep 3 12:35 sha256-d8ba2f9a17b3bbdeb5690efaa409b3fcb0b56296a777c7a69c78aa33bbddf182
-rw-r--r--. 1 ollama ollama 11353 Sep 3 12:35 sha256-f60356777647e927149cbd4c0ec1314a90caba9400ad205ddc4ce47ed001c2d6
-rw-r--r--. 1 ollama ollama 7240 Sep 3 12:35 sha256-fa6710a93d78da62641e192361344be7a8c0a1c3737f139cf89f20ce1626b99c
6. API実行例
[root@syasuda-ollama ~]# curl -s http://10.50.0.10:11434/api/version | jq
{
"version": "0.11.8"
}
[root@syasuda-ollama ~]# curl -s http://10.50.0.10:11434/api/tags | jq
{
"models": [
{
"name": "gpt-oss:20b",
"model": "gpt-oss:20b",
"modified_at": "2025-09-03T12:35:46.112234199Z",
"size": 13780173724,
"digest": "aa4295ac10c3afb60e6d711289fc6896f5aef82258997b9efdaed6d0cc4cd8b8",
"details": {
"parent_model": "",
"format": "gguf",
"family": "gptoss",
"families": [
"gptoss"
],
"parameter_size": "20.9B",
"quantization_level": "MXFP4"
}
}
]
}
[root@syasuda-ollama ~]# curl -s http://10.50.0.10:11434/api/chat -d '{
"model": "gpt-oss:20b",
"stream": false,
"messages": [
{ "role": "user", "content": "なぜ空は青いの?" }
]
}' | jq
{
"model": "gpt-oss:20b",
"created_at": "2025-09-03T12:37:34.747717531Z",
"message": {
"role": "assistant",
"content": "### 空が青く見える理由 ― レイリー散乱(Rayleigh scattering)の説明\n\n1. **光の性質** \n 太陽光は可視光(約400 nm〜700 nm)の波長を持つ光の混合です。波長が短いほど光は「青」に見え、波長が長いほど「赤」に見えます。\n\n2. **大気中の分子・微粒子** \n 大気中には空気分子(主に窒素・酸素)や微小な水滴・塵などが散乱しやすいサイズ(約0.01–0.1 µm)で散らばっています。\n\n3. **レイリー散乱の原理** \n - 光が大気分子と衝突すると、波長 λ の逆数の 4 乗に比例して散乱されます。 \n - つまり、波長が短い(青・紫)光は長い(赤・橙)光よりも**約 10 倍以上**強く散乱されます。 \n - そのため、太陽光が地球の大気を通過するとき、青い成分がより多く空間に拡散され、私たちの目に届きます。\n\n4. **観測の仕方** \n - **昼間**:太陽光が短いパスを通るため、青い光が最も強く散乱され、空全体が青く見えます。 \n - **夕方・朝方**:太陽が低くなり光の通過距離が長くなると、青い光は多く散乱・吸収され、赤・オレンジ系の長波長が主に残ります。これが夕日や朝日の赤い色になります。\n\n5. **その他の影響** \n - **大気の汚染**(PM2.5など)や**雲**は散乱パターンを変え、空の色をグレーや白っぽくします。 \n - **高度**が高い場所(山岳地帯など)では空がより深い青に見えるのは、空気が薄くなり散乱が増すためです。\n\n---\n\n#### まとめ \n空が青く見えるのは、**太陽光中の短波長(青・紫)光が大気中の分子によって強く散乱され、私たちの目に届きやすくなる**ためです。この現象を **レイリー散乱** と呼びます。 \n\nもし興味があれば、光学の教科書や科学系YouTubeで「レイリー散乱」の実験を紹介している動画を探してみると、もっと実感が湧くでしょう!",
"thinking": "The user asks in Japanese: \"なぜ空は青いの?\" meaning \"Why is the sky blue?\" So we need to answer. We can explain Rayleigh scattering, wavelengths, etc. Provide concise answer. Maybe also mention that the sky appears blue because molecules scatter shorter wavelengths more. Also mention scattering of sunlight by air molecules. Also mention that at sunset it's red due to longer path. Provide a friendly explanation. Let's answer in Japanese. Provide references."
},
"done_reason": "stop",
"done": true,
"total_duration": 9558760700,
"load_duration": 3325744775,
"prompt_eval_count": 75,
"prompt_eval_duration": 273793816,
"eval_count": 747,
"eval_duration": 5957802062
}
