ローカルLLMとRAGで自分の外部記憶を強化しよう

執筆者:佐藤友昭

※ 「ディスアグリゲーテッドコンピューティングとは何か?」連載記事一覧はこちら


はじめに

作業ログや検討メモ、参照した定型論文や書籍、ネット上の記事、視聴した講演やウェビナーのメモ等、日常を記録する情報は日々増えていく。これらの情報はできれば後に役立てたいと思うが、筆者の場合、なかなか上手くいかない。自分の外部記憶を紐解いてみると、記録したことすら忘れてしまっている項目が大半である。本稿では、ローカルLLMとRAGを用いて自分の外部記憶にいろいろと質問できるようにする方法を入門的に紹介する。決してベストプラクティス的な内容ではない。

自宅PC編

まずは、普段自宅で使用しているLinux PCを実験台として使えそうか試してみてから会社のサーバに適用してみることにする。

第一の要件は、ローカル環境で動作することである。情報の性質によってはネット上に置くことができないためである。第二の要件は、既存の環境に追加的に導入できることである。一般的なファイルシステム上に既にある記録情報(ファイル群)に対して質問できるようにしたい。第三の要件は、質問に対してデタラメな返答をしないことである。すべて自分で記録した情報なので、記録にないデタラメな返答には気が付くとは思うが、やはり安心して使用できるものが欲しい。

そこで、ローカルLLMとRAGを使用する。既にある記録情報(ファイル群)からデータベースを作成し、質問に対して近い断片を選択し、ローカルLLMに指定するプロンプトに埋め込むという流れという理解である。ローカルLLMの動作には使用するモデルの大きさに応じたGPUが必要になる。筆者のLinux PCには適当なGPUが搭載されていなかったので、今回 NVIDIA RTX4070 Ti Super という16GBのメモリを搭載したGPUを購入した。正直、どの機種を購入するのが良いのかよく分からなかったが、現時点(2024年6月時点)では RTX4070以上を買っておけばしばらく後悔しないだろうというネット上の意見を参考に、当該 Linux PC を購入したのと同じネット店舗でもっとも売れているGPU製品の中から選択した。

GPU は PCIe Gen4 x16 スロットにインストールする必要がある。当該 Linux PC には Mellanox ConnectX-4 が複数毎刺さっていたが全て取り除く必要があった。電源的にもスペース的にもGPUの搭載は1個が限度という感じ。GPUにはファンが3つ付いている。動作音は気にならないレベルで安心した。

OSは ubuntu 22.04 LTS のまま。
以下のページを参考に、nvidia-driver-550, cuda-11-7, libcudnn8, libcudnn8-dev 等をインストール。

Ubuntu 22.04マシンでGPUを使えるようにする #深層学習 - Qiita
NVIDIA ドライバ,NVIDIA CUDA ツールキット 11.8, NVIDIA cuDNN 8 のインストール(Ubuntu 上)

以下は nvidia-smi の出力。

Fri Jun 21 11:58:27 2024       
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 555.42.02              Driver Version: 555.42.02      CUDA Version: 12.5     |
|-----------------------------------------+------------------------+----------------------+
| 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 4070 ...    Off |   00000000:01:00.0 Off |                  N/A |
|  0%   36C    P8              5W /  285W |      15MiB /  16376MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+

続いてローカルLLMとしてollamaをインストール。0.1.45 がインストールされた。

sudo apt install python3.10-venv curl python3-dev
python3 -m venv .venv
source .venv/bin/activate

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

RAGとしてollama のリポジトリに含まれる langchain-python-rag-privategpt をインストール。

git clone https://github.com/ollama/ollama.git
cd ollama/examples/langchain-python-rag-privategpt/

pip install -r requirements.txt

言語モデルを ollama pull <モデル名> でインストール。
言語モデルに何を使用するかは実際に使い比べてみて判断することにして、 llama3, llama2-uncensored, llama2:13b, gemma2 などをインストールした。
なお、gemma2 をインストールする際に ollama を最新化(curl -fsSL https://ollama.com/install.sh | shを再実行)し 0.1.48 とした。

ollama pull llama3
ollama pull llama2-uncensored
ollama pull llama2:13b
ollama pull gemma2

記録情報(ファイル群)のカテゴリー毎にRAGのデータベースを作成する。カテゴリー毎に入力用のディレクトリ(SOURCE_DIRECTORY)とデータベース用のディレクトリ(PERSIST_DIRECTORY)を作成し、必要に応じてファイル群を再配置し、 ollama/example/langchain-python-rag-privategpt/ingest.py を実行する。

SOURCE_DIRECTORY=<入力用のディレクトリ>  PERSIST_DIRECTORY=<データベース用のディレクトリ> python ingest.py

質問(クエリ)の実行は、上記で作成したデータベース用のディレクトリを指定して ollama/example/langchain-python-rag-privategpt/privateGPT.py を実行する。

PERSIST_DIRECTORY=<データベース用のディレクトリ> MODEL=<言語モデル> python privateGPT.py

言語モデルの他に、EMBEDDINGS_MODEL_NAME環境変数で Sentence Transformers モデルも選択できる。ingest.py と privateGPT.py とで同じモデルを指定する必要がある。 チューニングポイントとして、ingest.py の chunk_size と chunk_overlap の値や privateGPT.py の TARGET_SOURCE_CHUNKS環境変数の値等もあるようだが、筆者は理解に至っていない。chunk_size と chunk_overlap については以下の記事が参考となりそうである。 

techcommunity.microsoft.com

動作確認の様子は前回ご紹介した以下の記事を参照されたい。GitHub - vaj/CDI-Infoで公開しているCDI関連講演の文字起こしテキストファイル群に対していくつか質問している。正しい問いを立てることさえできれば便利に使うことができそうである。

valinux.hatenablog.com

会社サーバ編

会社で使用している Dell EMC PowerEdge R450 サーバ(以降、R450と呼ぶ)にも適用してみる。

要件は自宅PC編と同じ。
さらに、R450は内蔵GPUをサポートしていないのでCDIソリューション(いわゆるPCIeボックス)を利用する必要がある。今回はELSAジャパン様からお借りした H3 Falcon 4005 (以降、4005と呼ぶ)を使用する。

(コンフィグレーションの詳細についてはGitHub - vaj/CDI-Labs対応する記事を参照されたい。以下では概要のみ紹介する。)

GPUは同じくELSAジャパン様からお借りしたNVIDIA RTX A4000を使用する。16GBのメモリを搭載している。NVLink ブリッジには対応していない。
GPUを 4005 の4つある PCIe Gen4 x16 スロットの1つに搭載する。

R450 の PCIe Gen4 x16 スロットで使用中のMellanox ConnectX-6を一旦取り外し、替わってホストカードをインストールする。

4005には最初からターゲットカードが1枚インストールされている。

R450 のホストカードの4つのポートと 4005 のターゲットカードの4つのポートを接続する。同じポート番号同士をSFF-8644ケーブル4本で接続する。

この状態で4005, R450を起動すると lspci コマンドで GPU が表示されるようになる。

27:00.0 VGA compatible controller: NVIDIA Corporation Device 24b0 (rev a1)
27:00.1 Audio device: NVIDIA Corporation Device 228b (rev a1)

今回使用した 4005 はスタンダードモードと呼ばれる状態で、接続するホストが1台に限定される。
アドバンスドモードのライセンスとターゲットカード1枚を増設することで2台のホストと接続することができるようになる。
アドバンスドモードでは、4つあるPCIe Gen4 x16スロットに搭載されたリソース毎に接続するホストを選択するオペレーションが必要となる。
PCIe Gen4 x16スロットに搭載可能なリソースとしては GPU の他にストレージ(NVMe)やネットワークカード(RNIC)が使用できる。
(R450から取り外したMellanox ConnectX-6もサポート対象のリストに記載されているのでリソースとして使用可能である。)

H3 Falcon シリーズには4005の他に4010, 4105, 4205がある。それぞれ搭載可能なリソース数、接続可能なホスト数、電源容量の上限が異なる。 詳細は製品ページを参照されたい。

感想等

情報を記録する際に「正しい問い」も一緒に記録することで情報の再利用の可能性が広がりそうである。
選択する言語モデル等の設定で同じ質問に対しても回答の傾向に違いが生じるようである。最適な設定を見出すには時間を要するかもしれない。
既存のノートアプリ等においてもローカル環境に蓄積した情報資産に対して柔軟な問いかけができるような機能が追加される日もそう遠くはなさそうである。
Falcon 4005(スタンダードモード)は1UサーバからGPUを使用可能にしたCDIソリューションの第1世代であり、今後CXL対応等が進められていくことで動的に可能な構成の範囲が徐々に広がっていくものと予想される。今後も継続的にCDI製品動向をウォッチしGitHub - vaj/CDI-Labs等で発信していきたい。