中古GPU（RTX 3060/12GB）でローカルLLM検証-4 ～ RakutenAI-7B-chat を試す

前回は、docker+llama.cppの環境で Calm2-7B-chat を導入し、日本語のやり取りを試しました。
[[前回記事] 中古GPU（RTX 3060/12GB）でローカルLLM検証-3](https://qiita.com/nabe2030/items/7a6bbf12e77d6b8ec8c7)
今回は、同様に日本語のやり取りが出来るという RakutenAI-7B-chat を試していきます。
# ステップ 1 — モデルのファイル名を確認
まずは、前回セットアップしたPython仮想環境に入ります。
```
source ~/llm/venv/bin/activate
```
- huggingface_hub[cli] や jq が導入済の環境

そして、ダウンロードするモデルのファイル名は大文字小文字まで一致する必要があるのと、ダウンロードできるモデルを確認するためにリストします。

```
python - <<'PY'
from huggingface_hub import list_repo_files
import os
files = list_repo_files("mmnga/RakutenAI-7B-chat-gguf", token=os.environ["HF_TOKEN"])
print(*files, sep="\n")
PY
```
上記は、`python - <<'PY' … PY` は ヒアドキュメント という Linux シェルの書き方で、改行を含む Python スクリプトをその場で実行できます。1 行にコピペすると崩れるので、上記をそのまま丸ごと貼り付けてください
```
RakutenAI-7B-chat-q2_K.gguf
RakutenAI-7B-chat-q3_K_L.gguf
RakutenAI-7B-chat-q3_K_M.gguf
RakutenAI-7B-chat-q3_K_S.gguf
RakutenAI-7B-chat-q4_0.gguf
RakutenAI-7B-chat-q4_K_M.gguf
RakutenAI-7B-chat-q4_K_S.gguf
RakutenAI-7B-chat-q5_0.gguf
RakutenAI-7B-chat-q5_K_M.gguf
RakutenAI-7B-chat-q5_K_S.gguf
RakutenAI-7B-chat-q6_K.gguf
RakutenAI-7B-chat-q8_0.gguf
```
ダウンロードできるモデルがリストで来たので、この中から品質と速度のバランスが良く、RTX3060/12GBに余裕で載るQ4_K_M版 `RakutenAI-7B-chat-q4_K_M.gguf` にします。
# ステップ 2 — モデルのダウンロード
モデルの保存先ディレクトリを作成
```
mkdir -p ~/llm/models/RakutenAI-7B-chat
```
huggingface-cli でモデルをダウンロードします。
```
huggingface-cli download \
  mmnga/RakutenAI-7B-chat-gguf \
  RakutenAI-7B-chat-q4_K_M.gguf \
  --token $HF_TOKEN \
  --local-dir ~/llm/models/RakutenAI-7B-chat \
  --local-dir-use-symlinks False
```
`ls -l ~/llm/models/RakutenAI-7B-chat/RakutenAI-7B-chat-q4_K_M.gguf`で4.4GB程度のファイルサイズで確認です。途中で止った場合も同じコマンドで続きからダウンロード出来ます。
# ステップ 3 — サーバー起動
llama.cpp サーバーを立ち上げて動作確認していきます。
コンテナ内のポートとホスト側のポート対応を合わせる必要があり、今回はポート：8000 に合わせました。
```
docker run --gpus all --rm -it \
  -v ~/llm/models:/models \
  -p 8000:8000 \
  ghcr.io/ggml-org/llama.cpp:server-cuda \
  --model /models/RakutenAI-7B-chat/RakutenAI-7B-chat-q4_K_M.gguf \
  --n-gpu-layers 35 \
  --ctx-size 4096 \
  --threads $(nproc) \
  --port 8000 
```
- --n-gpu-layers 35 は 32 層を丸ごと GPU に載せる想定
- CUDA OOM が出たら --n-gpu-layers を 32 → 28 → 24… と下げる
- --ctx-size 4096 は 4k トークン保持
- --threads $(nproc) は CPU 補助スレッド
以下のように、待ち受け状態になれば成功です。
```
main: server is listening on http://0.0.0.0:8000 - starting the main loop
srv  update_slots: all slots are idle
```
# ステップ 4 — 推論テスト（動作確認）
別のコンソールから curl で呼び出します。
```
curl -s -X POST http://localhost:8000/completion \
  -H "Content-Type: application/json" \
  -d '{"prompt":"USER: 日本で一番高い山は？\nASSISTANT:","n_predict":128}' \
| jq -r .content
 日本で一番高い山は日本アルプスにある富士山です。富士山の標高は3776mです。
```
正常に動作が確認出来ました。次に各社のLLMで回答が違ってしまう、この質問（笑）
```
curl -s -X POST http://localhost:8000/completion \
  -H "Content-Type: application/json" \
  -d '{"prompt":"USER: 日本で二番目に高い山は？\nASSISTANT:","n_predict":128}' \
| jq -r .content
 奥穂高岳（おっこだけ岳）は、日本第二位の標高を持つ山である。標高は3,190メートル。飛騨山脈（北アルプス）の本脈南部、岐阜県高山市（旧荘川町）と長野県大町市（旧池田町）との境界に位置する。日本三百名山、信濃百名山、ぎふ百山の一つ。
```
残念、不正解。日本で２番目に高い山は「北岳（きただけ）」で、標高は3,193mです。
でもなかなかしっかりした日本語です。
```
curl -s -X POST http://localhost:8000/completion \
  -H "Content-Type: application/json" \
  -d '{"prompt":"USER: 貴方は誰ですか？自己紹介して\nASSISTANT:","n_predict":128}' \
| jq -r .content
 私は楽天のAI開発チームによって作られた人工知能モデルであり、楽天のAIアシスタントサービスに搭載されている人工知能モデルです。ユーザーの質問や要求に対して情報を提供したり、サービスを提供する役割を担っています。
```
今回は、docker+llama.cppの環境で RakutenAI-7B-chat で日本語の受け答えを試しました。内容はともかく（笑）日本語のやり取りが普通に出来ることを確認出来ました。

次回は、vLLM環境を試してみたいと思います。