LLMのローカル環境構築を簡単にするNIMの使用感をレビュー

はじめに

今年NVIDIA NIMが発表され、すでに海外の様々な企業が生成AIの基盤として採用しているなど盛り上がりを見せています。 弊社にもローカルでLLMを構築したいというニーズをいただくことが多いため、今回NVIDIA NIMを試し、NIMでどういったことができるのかや、スクラッチで開発する時と比べてどのような恩恵を受けられるのかをNvidiaが提供しているサンプルプロジェクトをもとに試してみました。 2024年6月に公開された新規のサービスのため、2024年10月時点では、公式以外の関連情報、実際に試してみた系記事などはこれから増えてくるタイミングかと思います。 本記事を通じて、この技術・サービスに興味がある人の役に立てれば幸いです。

目次

NVIDIA NIM とは?

NVIDIA NIM(NVIDIA Inference Microservices)は、生成AIの推論を最適化するマイクロサービスです。 データキュレーションやモデルのファインチューニング・評価などが含まれるNVIDIA NeMo Microservices の中の一つとされています。 次の図はNIMの構造を示しています。CUDA・Kubernetesなどの基盤を除いた緑色の立方体中の要素がNIMであり、複数の要素(APIサーバー、生成AIモデル等)で構成されています。

図 NIMの構造([1]より引用)

それぞれの要素は今まで開発者がユースケースに応じて用意する必要があったものです。例えば、HuggingFaceのモデルをOpenAIと同様のエンドポイントで使う場合は自分でAPIサーバーを開発する必要が有りましたが、NIMでは、Dockerでコンテナを起動するだけで開発が完了します。(個人的には、CUDAとPytochの整合性に今まで散々泣かされてきたので、気にせずにデプロイできることには感涙です。)

生成AIの推論を行うために必要なものが用意されているため、開発者はユースケースに合わせて必要なパーツを選択し、デプロイすることが出来ます。

生成AIの推論に必要だったものが様々な環境でコンテナで簡単に立ち上げることができるため、開発期間の短縮がNIMにより実現されます。

加えて、それぞれのモデルや環境に合わせた最適化はすでにされており、LLMをそのまま使用するより、パフォーマンス(GPUの使用量や、推論速度)を発揮でき、より効率的かつ高速な推論をすることが可能です。

NVDIAの技術ブログには、

3倍の速さでテキストを生成できる

([2]より引用)という記載もありました。

図 速度比較([2]より引用)

今回は、NVIDIAが提供しているサンプルリポジトリを元に複数のユースケースを実施し、NIMについてより詳しく紹介できればと思います。

実際に使用してみる

下記のサンプルリポジトリを使用して、NVIDIA NIMのホスティング環境を構築し、アプリケーションを動かします。

github.com

サンプルリポジトリには、さまざまなユースケースが用意されており、その中でも今回は、① API経由のNIMでの推論、②コンテナでセルフホストしたNIMの推論、③NIMでRAGを試して行きたいと思います。 まずは、上記サンプルリポジトリを試すための準備をしていきます。

事前準備

今回使用するサンプルプロジェクトをクローンします。

git clone https://github.com/nvidia/GenerativeAIExamples.git  

また、リポジトリを使うための必須要件や必要なソフトウェア、今回使用したサーバーを下記に記載します。

必須要件

使用するマシンは以下の要件を満たす必要があります。

必要なソフトウェア

今回使用したサーバー

  • CPU:Xeon 6544Y(3.6GHz/16コア) x 4
  • GPU:A100(80GB) x4
  • OS:Ubuntu22.04LTS

API経由でNIMを試してみる

NVIDIA APIカタログで公開されているLLMをAPI経由で実行してみます。 APIは開発用として公開されており、実際にLLMをローカルマシンにデプロイすることなく、推論できるようになっています。

1. NVIDIA AI Enterprise Lisenceに登録する

下記URLからNVIDIA AI Enterprise Lisenceに登録します。

enterpriseproductregistration.nvidia.com

NVIDIA AI Enterprise Lisenceは有料ですが、90日間の試用期間があり、無料で登録することができます。 支払い情報等入力しなくてもAPIキーを発行・使用できたので、90日以上経過してもサービスが使用できなくなるだけだと想像しております。 料金に関して詳しくは下記URLのドキュメントをご確認ください。

resources.nvidia.com

2. NVIDIA API キー・モデル名を取得する

NVIDIA AI Enterprise Lisenceに登録・ログイン後、Try NVIDIA NIM APIs に アクセスすると、以下のページが表示されます。ここでは、100種類を超える様々な用途のモデルの中から任意のモデルを選択できます。今回はデモとして軽量な"llama-3.1-8b-instruct" を試験的に選びました。

モデル画面に遷移したら、画面右側にあるBuild with this NIM をクリックしてください。

モーダル画面が表示されるので、 Generate your API Key をクリックしてください。 nvapi-から始まるAPIキーが発行されるので、コピーしてください。

Using LLMs hosted on NVIDIA API Catalog — NVIDIA NeMo Guardrails latest documentation に記載がある通り、発行したAPIキーは選んだモデルだけではなく、NVIDIA API カタログで利用可能なすべてのモデルに使用できます。 ※ APIキーを発行したあとにもう一度APIキーを発行すると、前回発行したAPIキーが有効期限にかかわらず無効になるようです。

この後の手順で環境変数に設定する必要があるので、”model=”の後に記載されているモデル名(ここではmeta/llama-3.1-8b-instruct)もメモしておきます。

3. 環境変数NVIDIA API キー・モデル名をセットする

下記のコマンドを実行し、環境変数NVIDIA API キー・モデル名をセットします。 APIキーは手順2で取得したnvapi-で始まるものに適宜置き換えてください。

export NVIDIA_API_KEY=nvapi-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export APP_LLM_MODELNAME=meta/llama-3.1-8b-instruct

APP_LLM_MODELNAMEの初期値はmeta/llama3-70b-instructが設定されており、環境変数にモデル名をセットしない場合は、初期値のモデルでデプロイされます。

4. RAG サンプルアプリケーションをビルドして実行する

下記のコマンドを実行し、docker-compose.yamlがあるパスまで移動します。 LlamaindexとLangchainのサンプルがあるようですが、今回はLangchainのサンプルを使うことにしました。

cd GenerativeAIExamples/RAG/examples/basic_rag/langchain/

次に下記コマンドでコンテナをビルドします。

docker compose up -d --build

しばらく待つと、下記のコンテナが立ち上がります。

✔ Container chain-server       Started
7.9s 
 ✔ Container milvus-etcd        Started
8.0s 
 ✔ Container milvus-minio       Started
8.0s 
 ✔ Container milvus-standalone  Started
7.6s 
 ✔ Container rag-playground     Started

5. localhost:8090にアクセス

LLM Playground が表示され、動作を確認できました。

なお、モデルを変更する場合は、カタログ(手順2)から別のモデルを選択し、モデル名を取得してAPP_LLM_MODELNAMEを更新してください。APIキーは変更不要です。その後は、手順4および5と同様に進めることで、別のモデルを簡単に試すことができます。

② コンテナでセルフホストしてNIMを試してみる

次は、ローカルマシンでNIMをセルフホスティングしてみます。 ①でアクセスしたモデルページの右側のDockerというタブをクリックするとローカルNIMコンテナの立て方を確認できますが、今回は引き続きサンプルプロジェクトを用いてローカルNIMをセルフホストしてみます。

1. NVIDIA API キーを環境変数にセットする

今回はNVIDIA_API_KEYという環境変数ではなく、NGC_API_KEYという環境変数NVIDIA API キーをセットします。 セルフホスティングでも①で取得したNVIDIA API キーを使うことができます。

export NGC_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

2. NGCコンテナレジストリにログインする

NIMモデルのイメージをpullできるようにするために、NGCコンテナレジストリにログインする必要があります。 NGC CLI または Dockerでログインすることが出来ますが、今回はDockerを使ってログインしました。

docker login nvcr.io

上記コマンドを実行すると、UsernameとPasswordの入力が求められます。 Usernameには $oauthtokenと入力、Passwordは ①で発行したNVIDIA_API_KEY キーを入力してください。

3. docker-compose でイメージを設定する

ローカルマシンで下記ファイルを編集します。

GenerativeAIExamples/RAG/examples/local_deploy/docker-compose-nim-ms.yaml

nemollm-inferenceサービスの下画像の赤線に置き換えます

※ 一部抜粋

services:
  nemollm-inference:
    container_name: nemollm-inference-microservice
    image: nvcr.io/nim/meta/llama-3.1-8b-instruct:latest # ここ
    volumes:
    - ${MODEL_DIRECTORY}:/opt/nim/.cache
    user: "${USERID}"
    ports:
    - "8000:8000"
    expose:
    - "8000"
    ....

4. その他の環境変数を設定する

その他必要な環境変数を設定します。 MODEL_DIRECTORYに指定するディレクトリは何でもいいですが、存在しない場合はビルド時に自動でroot権限で作られてしまい、サービスの起動に失敗してしまうおそれがあるため、事前に作っておくことをおすすめします。 ※今回はAPP_LLM_MODELNAMEは設定しなくても手順3で設定したイメージのLLMが使用されますが、設定しない場合はPlaygroundの表示が初期値のmeta/llama3-70b-instructになります。

APP_LLM_MODELNAME=meta/llama-3.1-8b-instruct
MODEL_DIRECTORY=~/.cache/model-cache
APP_LLM_SERVERURL="nemollm-inference:8000"
APP_EMBEDDINGS_SERVERURL="nemollm-embedding:8000"

5. RAG サンプルアプリケーションをビルドして実行する

下記のコマンドを実行し、docker-compose.yamlがあるパスまで移動します。 今回もLangchainを使ってみます。

cd GenerativeAIExamples/RAG/examples/basic_rag/langchain/

次に下記コマンドでコンテナをビルドします。 USERID変数が無いと、permissionエラーでうまく動きませんでした。 また、--profile local-nimをつけると、手順3で変更したdocker-compose-nim-ms.yamlが読み込まれます。 profileをlocal-nimに設定すると、API経由で試したときにはデフォルトで起動していたmilvusが起動しないため、--profile milvusもつけます。

USERID=$(id -u) docker compose --profile local-nim   --profile milvus up -d --build

初回はモデルのダウンロード等があり、かなり時間がかかると思います。 気長に待ちましょう。

起動が完了すると下記のようにコンテナが立ち上がります。

 ✔ Network nvidia-rag                               Created                                                                                                                                         0.1s 
 ✔ Container milvus-etcd                            Started                                                                                                                                         0.7s 
 ✔ Container nemollm-inference-microservice         Healthy                                                                                                                                        51.9s 
 ✔ Container milvus-minio                           Started                                                                                                                                         0.7s 
 ✔ Container nemo-retriever-embedding-microservice  Healthy                                                                                                                                        26.4s 
 ✔ Container milvus-standalone                      Started                                                                                                                                         0.9s 
 ✔ Container chain-server                           Started                                                                                                                                        52.0s 
 ✔ Container rag-playground                         Started                                                                                                                                        52.2s

nvidia-smiコマンドでもGPUが使用されているのが確認できました。

6. localhost:8090にアクセス

LLM Playground が表示され、動作を確認できました。

③RAGを試してみる

サンプルプロジェクトのRAGの機能を試してみます。 API経由・コンテナでセルフホストどちらでも試せるのでお好みでお試しください。

1. localhost:8090/kbにアクセスし、PDFまたはテキストファイルをアップロードする

RAGを試してみたいと思います。 会話画面の右上の Knowledge Baseをクリックしてlocalhost:8090/kbに遷移します。

今回はRidge-iの2024年7月期通期決算説明資料を使います。

https://contents.xj-storage.jp/xcontents/AS09155/539ae638/f2ab/441e/bed5/515e39331162/140120240911583501.pdf

Add Fileをクリックするとダイアログが出るので、読み込ませるファイルを選択します。 読み込みできるファイル形式は、テキスト、PDF、Markdown形式です。

多少時間がかかりますが読み込みが完了するとNo Files uploadedだった箇所にファイル名が表示されます。

2. localhost:8090にアクセスし、質問する

ヘッダーのConverseボタンをクリックし、会話画面(localhost:8090)に戻ります。

Use knowledge baseにチェックを入れ、「Ridge-iについて教えて」と入力しました。

アップロードしたPDFの情報を踏まえてそれっぽく回答してくれました!! 2024年7月の報告書についても言及があり、RAGの機能が使用されていることがわかります。

RAGを使わなかった場合と比較してみました。 Ridge-iは中国で使われているスマートフォンのOSだと返ってきましたが、事実と異なります。

トラブルシューティング

services.chain-server.depends_on.nemollm-embedding Additional property required is not allowed

docker compose up 時にこのエラーが発生する場合、docker composeのバージョンが古い可能性があります。 私の場合はIssuesに従って最新バージョンにアップグレードすることで解決しました。

github.com

RuntimeError: The number of CUDA devices has changed since the first call to torch.cuda.device_count().

セルフホスティング時に発生しました。 複数のGPUを使用する場合、動的にGPUが割り当てられる状況で発生することがあるようです。

下記ファイルで推論コンテナのGPU割り当てが動的になっていたため、GPUのIDを指定することで解決しました。 GenerativeAIExamples/RAG/examples/local_deploy/docker-compose-nim-ms.yaml

※一部抜粋

services:
  nemollm-inference:
    container_name: nemollm-inference-microservice
    image: nvcr.io/nim/meta/llama-3.1-8b-instruct:latest
    volumes:
    - ${MODEL_DIRECTORY}:/opt/nim/.cache
    user: "${USERID}"
    ports:
    - "8000:8000"
    expose:
    - "8000"
    environment:
      NGC_API_KEY: ${NGC_API_KEY}
    shm_size: 20gb
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
#              count: ${INFERENCE_GPU_COUNT:-all}  # コメントアウト
              device_ids: ['${LLM_MS_GPU_ID:-0,1,2,3}']  # コメントアウトを外し、使用するGPUのIDを指定
              capabilities: [gpu]

感想

サンプルプロジェクトが非常によくできていて使いやすかった

サンプルプロジェクトが良く出来ていて、ドキュメントも充実しており、アプリケーション周りは非常に簡単に試すことができました。 ソースコードもわかりやすく作られているため、このプロジェクトを少し変えるだけでも、独自のアプリケーションを作ることができるのではと思いました。

API Catalog の仕様で少し躓いたが一度発行すると全てのモデルが使え利便性を感じた

API Catalogの名前とUIから、公開されている各モデルそれぞれでAPIキーを発行して使用できると思っていました。 APIキーは一つ発行するだけですべてのモデルを試せたり、直近で発行したAPIキーしか利用できなかったりと想像と違ったため若干躓いてしまいましたが、一度発行すれば全てのモデルが使え、切り替えも用意であったことから、仕様さえ理解すればスピーディーに開発ができると感じました。

勢いがあり未来があると感じた

この記事を書いている間にも、Llama3.2がPreview(APIだけ利用できる状態)として公開されていました。 一般公開されたばかりで注目されているサービスでもあり、かなり勢いを感じ、この先の発展が楽しみです。

また、カタログに掲載されているモデルを使うだけでなく、Nemo Microservicesを利用してカスタムしたLLMを使うことができるため [1]、今後より独自の戦略をもってサービス展開をしていく企業が増えてくるのではないかと思います。

おわりに

今回はNVIDIA NIMを、API経由・セルフホスティングで試してみました。 今後、このブログの中でNIMを含めたローカルLLMについてい色々発信していきたいと考えています。現在、Ridge-iの生成AI関係事業が大きく拡大しつつあり、一緒に開発・研究してくださる仲間を募集しています。 カジュアル面談から可能なので、ぜひお気軽にご連絡ください!

ridge-i.com

引用文献

[1] NVIDIA NIM for Developers, 閲覧日時:2024年10月29日 developer.nvidia.com

[2] C. Patel and N. K. Juluru, Customize Generative AI Models for Enterprise Applications with Llama 3.1, 24 Jul. 2024, 閲覧日時:2024年10月29日 developer.nvidia.com

参考文献

  • 最適化された AI 推論を実現するマイクロサービス NVIDIA NIM : NVIDIA JAPAN によるGTC 2024での発表です。NVIDIA NIMがどういうサービスなのか大体の概要について理解できました。 www.youtube.com

  • NVIDIA NIM がモデル展開に革命をもたらし、世界中の何百万人もの開発者を生成 AI 開発者に変える : NVIDIA NIMのプレスリリースです。実際に企業が今までの生成AI開発でどのような問題を抱えていて、NVIDIA NIMを使って解決しているのかが紹介されています。 prtimes.jp

  • NVIDIA AI Enterprise Licensing and Packaging Guide : NVIDIA AI Enterprise License に関する公式のドキュメントです。 料金について確認しました。執筆時点では2024年3月更新となっていました。 resources.nvidia.com

  • NIM(NVIDIA Inference Microservices)を使ってみました : 日本語で書かれた中で見つけた唯一のセルフホスティングの記事で、大変参考になりました。 GenerativeAIExamples と NVIDIA API カタログを用いて Retrieval Augmented Generation を活用した LLM チャットボットを作成 : NVIDIA JAPAN の公式ブログです。セルフホスティングではなく、API Catalogについてのみ書かれています。 docs.nvidia.com

  • Using LLMs hosted on NVIDIA API Catalog : APIキーはすべての発行したモデルだけでなくすべてのモデルで使用できる旨が書かれていました。 NVIDIA と Hugging Face のコラボレーションで生成 AI モデルのデプロイが簡単に:NVIDIA JAPAN の公式ブログです。NIMはスループットに優れ、企業は三倍の速さでテキストを生成できると記載がありました。

developer.nvidia.com