• <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • Generative AI

    リランキングモデルによる RAG の日本語検索精度の向上

    Reading Time: 7 minutes

    ChatGPT が登場して以降、多くの企業/組織にて生成 AI の活用が進んでいます。その中でも LLM (Large Language Model、大規模言語モデル) は大量の知識を學習することで幅広い分野の問題を解決することができます。LLM は學習した知識には適切な回答ができるも一方で、社內ナレッジなど學習には含まれていない事がらに関する回答は得意ではありません。LLM が特定の領域の質問にも正確に回答できるようにした手法に RAG (Retrieval Augmented Generations) があります。

    図 1. RAG の構成図。RAG は、レトリーバーとジェネレーターで構成される。

    RAG は、大きく「レトリーバー (Retriever)」と「ジェネレーター (Generator)」の 2 つのパーツで構成されています。レトリーバーは、ユーザーによって入力されたクエリ (例: 質問文) を受け取り、そのクエリに関連した文書 (例: 社內文書) をデータベースなどから取ってきます。ジェネレーターは、レトリーバーによって取得された文書をもとにクエリに対しての回答文を生成します。レトリーバーには、埋め込みモデルやリランキングモデルが用いられます。ジェネレーターには、LLM が用いられます。RAG ではレトリーバーのおかげでジェネレーターである LLM が社內ナレッジなどの外部知識を獲得することができます。裏を返すと、レトリーバーの検索精度が RAG の回答精度に大きく影響を與えることになります。

    そこで本記事ではRAGのレトリーバーに著目し、以下の 3 點について解説します

    • レトリーバーとして用いられる「埋め込みモデル」と「リランキングモデル」
    • リランキングモデルによる検索精度の向上
    • 埋め込みモデルとリランキングモデルを用いた RAG の構築 (LangChain)

    目次:

    埋め込みモデルとリランキングモデル

    本章では RAG のレトリーバーとしてよく用いられる「埋め込みモデル (Embedding Model)」と「リランキングモデル (Reranking Model)」の 2 つについて説明します。いずれもクエリと文書の「類似度」を算出するのに用いられます。ここで類似度とは 2 つの文がどれだけ似ているかをあらわしたスコアのことであり、スカラー値 (例: -1~1 の値) です。埋め込みモデルとリランキングモデルの理解を深めるために、これらのモデルで最も一般的に採用される手法である「Bi-Encoder」と「Cross-Encoder」の概念と特徴について解説します。その後、RAG における埋め込みモデルとリランキングモデルの活用方法について説明します。

    Bi-Encoder と Cross-Encoder

    図 2. Bi-Encoder (左) と Cross-Encoder (右)

    埋め込みモデルとリランキングモデルの理解には、「Bi-Encoder (バイエンコーダー)」と「Cross-Encoder (クロスエンコーダー)」の違いについて理解する必要があります。いずれも任意の 2 つの文の類似度を測るのに用いることができます。Bi-Encoder と Cross-Encoder のアーキテクチャはほぼ同一であり、BERT や GPT が用いられます。主な違いは最終的な類似度の取り方にあります。

    図 3. Bi-Encoder によるクエリと文書の類似度計算

    まずは Bi-Encoder についてです。図の「クエリ」と「文書」はそれぞれテキストで、Transformer への入力となります。「クエリベクトル」と「文書ベクトル」はそれぞれ入力に対応したベクトル (例えば、後述する Llama-3.2-NV-EmbedQA-1B-v2 だと、長さ 2048 のベクトル) で、Transformer の出力となります。Bi-Encoder は入力文をそれぞれベクトル化し、それらのベクトルをもとに最終的な類似度を算出します。

    Bi-Encoder におけるクエリと文書の類似度の算出の流れを説明します。まず、クエリを Bi-Encoder に入力しそのベクトルを得ます。同様に文書を Bi-Encoder に入力しベクトルを得ます。これらのベクトルをもとに類似度を算出します。ベクトルの類似度の計算方法はさまざまありますが、「コサイン類似度」が用いられることが多いです。コサイン類似度とは、 2 つのベクトルを正規化し、內積を取ることで計算され、値は -1 から 1 の範囲をとります。1 に近ければ近いほど 2 つのベクトルは似ており、逆に -1 に近いと 2 つのベクトルは似ていない、ということになります。

    RAG においては、「埋め込みモデル」としてこの Bi-Encoder を用います。埋め込みモデル (Bi-Encoder) の例として、Multilingual-E5Llama-3.2-NV-EmbedQA-1B-v2 などがあります。

    図 4. Cross-Encoder によるクエリと文書の類似度計算

    2 つの文の類似度を測るもう 1 つの手法として Cross-Encoder があります。Bi-Encoder では、2 つの文を別々にベクトル化しコサイン類似度によって類似度を出していました。一方で Cross-Encoder では、2 つの文をはじめに結合します。この結合した文を Transformer に入力することで類似度が直接得られます。こうすることで、Cross-Encoder はクエリと文書の関係を Transformer のアテンションなどの全層を通して獲得します。そのため、検索タスクにおいては一般的に Bi-Encoder よりも Cross-Encoder の方が高い精度を出すとされています。

    RAG においては、「リランキングモデル」としてこの Cross-Encoder を用います。リランキングモデル (Cross-Encoder) の例として、Llama-3.2-NV-RerankQA-1B-v2 などがあります。

    Bi-Encoder と Cross-Encoder の違いはその類似度の出し方にあることについて觸れてきました。RAG においては、埋め込みモデル (Bi-Encoder) とリランキングモデル (Cross-Encoder) を併用することが多いです。これにより、検索速度と検索精度のバランスが取れたレトリーバーを実現することが可能となります。次節では RAG における埋め込みモデルとリランキングモデルの活用方法について見ていきます。

    RAG における埋め込みモデルとリランキングモデル

    前節で、埋め込みモデルは Bi-Encoder を、リランキングモデルは Cross-Encoder を用いていることが分かりました。本節では、これらの埋め込みモデルとリランキングモデルを実際に RAG で用いるケースについて考えていきます。

    RAG では、これらのモデルによってデータベース內の文書をスコアリングし、そのうち類似度が上位となった數件 (Top-k) の文書を後段の LLM のプロンプトに付與します。下記は RAG の LLM で用いられるプロンプトの例で、「## 文脈」以下にはレトリーバーによって取得された文書、「## 質問」以下にはユーザーからのクエリが記載されます。

    あなたは優秀なAIアシスタントです。與えられた情報をもとに、ユーザーの質問に回答してください。
    
    ## 文脈
    - 2025 年 1 月 6 日 – NVIDIA は本日、ゲーマー、クリエイター、開発者向けの最先端のコンシューマー GPU、GeForce RTX? 50 シリーズのデスクトップおよびノート PC の GPU を発表しました。
    - GeForce RTX 5090、RTX 5080、RTX 5070 Ti Laptop GPU を搭載したノート PC は 3 月から、RTX 5070 Laptop GPU は 4 月から、Acer、ASUS、Dell、GIGABYTE、HP、Lenovo、MECHREVO、MSI、Razer など世界の主要メーカーから発売される予定です。\n\nNVIDIA について NVIDIA (NASDAQ: NVDA) はアクセラレーテッド コンピューティングの世界的なリーダーです。
    - GeForce RTX 50シリーズデスクトップおよびノートPC、NVIDIA Blackwellアーキテクチャ、第五世代Tensorコア、第四世代RTコア、GeForce RTX 5090 Founders Edition GPU、NVIDIA DLSS 4、NVIDIA Reflex、DLSSマルチフレーム生成、DLSS 超解像およびレイ再構成モデル、NVIDIA Reflex 2、RTX Neural Shaders、RTX Neural Faces、RTX Mega Geometry、
    
    ## 質問
    NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。

    本節では、レトリーバーとして「埋め込みモデルのみ」、「埋め込みモデル+リランキングモデル」、「リランキングモデルのみ」の 3 つのケースについてその違いや特徴について見ていきます。

    埋め込みモデルのみのレトリーバー

    図 5. レトリーバーとして埋め込みモデルのみを使用した RAG

    まずは最もシンプルな RAG として、レトリーバーに埋め込みモデルのみを用いるケースを考えます。この場合、埋め込みモデル (Bi-Encoder) によって社內文書はあらかじめすべてベクトル化し、ベクトルデータベースに格納しておくことができます。検索時は、ユーザーからのクエリをベクトル化し、ベクトルデータベースにあらかじめ格納しているすべてのベクトルとコサイン類似度を計算します。コサイン類似度に従って上位 k 件 (例えば k=3) の文書を LLM のプロンプトに追加します。これによって LLM はこれらの文書をもとに回答を生成することができます。

    埋め込みモデルによるレトリーバーは「社內文書をあらかじめすべてベクトル化しておける」という點が重要です。これのおかげで、検索時はユーザーからのクエリのみをベクトル化すればよく、素早く検索結果を獲得することができます。ただし、埋め込みモデルによって素早い検索できるものの、適切な文書が獲得できなければ元も子もありません。そこで、レトリーバーの検索精度を向上させるためにリランキングモデル (Cross-Encoder) を併用します。

    埋め込みモデル+リランキングモデルのレトリーバー

    図 6. レトリーバーとして埋め込みモデルとリランキングモデルの両方を使用した RAG

    上の図はレトリーバーとして埋め込みモデルとリランキングモデルを併用した RAG を示しています。この場合、埋め込みモデルでいきなり上位 3 件に絞り込むのではなく、埋め込みモデルでまずは広い範囲の文書 (例えば上位 50 件) を取得します。その 50 件の中から、より高い検索精度を持つリランキングモデルで最終的に上位 3 件に絞り込みます。これによって先ほどのケースよりも正確に上位 3 件の文書を獲得することができます。高速な埋め込みモデルによって大枠のあたりをつけ、検索精度の高いリランキングモデルでより正確に文書を絞り込みます。埋め込みモデルとリランキングモデルを併用することで検索精度がどのくらい上がるのかについては、次章で実験的に示します。

    リランキングモデルのみのレトリーバー

    図 7. レトリーバーとしてリランキングモデル (Cross-Encoder) のみを使用した RAG

    ここで「なぜレトリーバーとしてリランキングモデルのみにしないのか」と疑問を持たれるかもしれません。その疑問は真っ當なものであり、検索精度のみを求めるのであればそうするのが理想的でしょう。ただし、RAG のような実運用を想定したアプリケーションにおいては、「速度性能」も非常に重要となります。

    埋め込みモデルは文書のベクトル化をすべてあらかじめ行うことができます。検索時には、埋め込みモデルへの入力はクエリのみであり、あとは計算済みの文書ベクトルとのコサイン類似度を計算すれば良いです。

    一方リランキングモデルは、検索時に、クエリとすべての文書のペアを入力にとります。つまり、データベース內の文書が 100 件程度の場合は、クエリと文書のペアが 100 件あることになり、その 100 件をリランキングモデルに入力しなければいけません。RAG をもちいるユースケースでは文書 (社內文書など) の數ははるかに多いです。たとえば、文書が 10,000 件にもなればすべてのスコアを出すのに相當量の計算が必要となります。これにより RAG のリアルタイム性が損なわれ、ユーザー エクスペリエンスの観點からその RAG システムは使いづらいものになってしまいます。

    このことからも RAG を構築する際のデータ規模に応じて、適切な実裝方法を選択する必要があることがわかります。特に、大規模な RAG システムを構築する場合は、埋め込みモデルで候補となる文書をある程度絞ったのち、リランキングモデルでより正確な文書に絞り込む、という、埋め込みモデルとリランキングモデルを併用した検索方法が用いられます。次章では、埋め込みモデルとリランキングモデルを組み合わせることで検索精度が向上することを実験的に見ていきます。

    日本語における検索精度の評価結果

    前章では、埋め込みモデルとリランキングモデルの仕組みについて説明してきました。本章では、埋め込みモデル+リランキングモデルによる検索精度の向上を定量的に示します。評価スクリプトとして MTEB (Massive Text Embedding Benchmark) を用い、評価データは日本語の検索評価データセット (= JMTEB に含まれる検索データセット 6 つ) を用います。

    モデルには、オープンソースでありかつ日本語で高い検索精度を誇る multilingual-E5-large (以下、mE5-large) および Ruri-largeに加えて、 NVIDIA の Llama-3.2-NV-EmbedQA-1B-v2 (以下、NV-EmbedQA とも表記) を比較します。また、リランキングモデルは Llama-3.2-NV-RerankQA-1B-v2 (以下、NV-RerankQA とも表記) を用います。リランキングモデルは埋め込みモデルによって取得された上位 50 件を並べ替えます。評価指標にはいずれも nDCG@10 を用います。nDCG@10 とは、「上位 10 件に正解文書が入っており、さらにそのなかでもどれだけ上位に入っているか」というのを測った値です。nDCG についてはさまざまな解説記事があるため、詳しくはそちらをご參照ください。

    図 8. 埋め込みモデルとリランキングモデルによる検索精度

    上の図は、検索データセットの評価の平均値を示しています。左 3 つはそれぞれ mE5-large、 Ruri-large、 NV-EmbedQA の検索精度です。一番右は NV-EmbedQA にさらに NV-RerankQA を組み合わせた場合の検索精度を示しています。埋め込みモデルのみで比較した場合、Llama-3.2-NV-EmbedQA-1B-v2が最も高い検索精度となっています。NV-RerankQA を組み合わせることでさらに 3.7 ポイントの向上が見られます。

    図 9. 埋め込みモデルに NV-RerankQA を組み合わせたことによる検索精度の変化

    上の図は、各埋め込みモデルに NV-RerankQA を組み合わせた場合の評価結果を示しています。いずれの埋め込みモデルにおいても NV-RerankQA を用いることでさらなる検索精度の向上を確認することができます。つまり、すでに使用している埋め込みモデルに NV-RerankQA を組み合わせるだけでさらなる検索精度の向上が期待されます。

    Llama-3.2-NV-EmbedQA-1B-v2 は、高い検索精度だけでなくコンテキスト長が 8,192 トークン (mE5-large および Ruri-large は 512 トークン) と長いため、長い文書などもそのままベクトル化することが可能です。さらに、Matryoshka Embedding を採用しているため、埋め込みベクトルの長さを 384 まで小さくすることができ、格納するベクトルの容量を大幅に削減することができます (mE5-large および Ruri-large は 1,024)。次の章ではこの埋め込みモデルとリランキングモデルを用いた RAG を実裝します。

    リランキングモデルを用いた RAG の実裝

    検証環境は以下の條件で行っています。ローカルに NVIDIA GPU を準備する必要はありません。 (ローカルでモデルを起動する場合についても後述します。)

    ハードウェア

    • AMD Ryzen 9 7950X 16-Core Processor
    • メインメモリ: 124GB
    • (ローカルでモデルを起動する場合のみ) NVIDIA RTX 6000 Ada 

    ソフトウェア

    • Debian GNU/Linux 11 (bullseye)
    • Python 3.11
    • (ローカルでモデルを起動する場合のみ) NVIDIA GPU Driver version 550.142

    モデルの準備

    埋め込みモデルとリランキングモデルとして、前章で高い検索精度を示した、Llama-3.2-NV-EmbedQA-1B-v2 および Llama-3.2-NV-RerankQA-1B-v2 を用います。これらは NIM (読み仮名: ニム) というコンテナーで提供されています。NIM とはいわば、LLM などのモデルをサーバーとして簡単に立ち上げることができるコンテナーです。NIMコンテナーはダウンロード可能な形でも提供されているため、docker run コマンドのみで、さまざまなモデルをローカルの環境で利用することができます。そのほか NIM の詳細はこちらの記事をご參照ください。

    NIM コンテナーの使用方法は「API カタログ上にホストされた NIM の使用」または「ローカルでの NIM の使用」の 2 通りあります。本章では、CPU のみで動くようにするため、前者の API カタログ上のモデルを優先して説明します。後者のコンテナーの使用方法も後述しておりますので、ご自身の GPU 環境で NIM を利用する場合はそちらをご利用ください。

    API カタログでは様々なモデルを用意しており、DeepSeek-R1Llama-3.1-405B などの大きなモデルも無料で簡単に試すことが可能です。利用にはまず API キーが必要となるため、その取得手順を示します。

    1. https://build.nvidia.com/ にアクセス
    2. 右上の Login ボタンを押下
    3. メール アドレスを入力し、手順に従って會員登録。(※メール アドレスは個人用/會社用を問いません。)
    4. 手順に従い會員登録後、ログイン
    5. ログイン後、使用するモデルのページ (例: Llama-3.2-NV-EmbedQA-1b-v2) において Input の「Shell」タブを開き、「Get API Key」を押下
    6. 「Generate Key」を押下し、API キーを生成
    7. 表示された API キーをコピーし、任意の場所に保存

    上記の API キーを用いて、Llama-3.2-NV-EmbedQA-1B-v2 によるベクトル化を試します。以下のコマンドで動かします。(<PASTE_API_KEY_HERE>の箇所を取得した API キーに置き換えてください。)

    curl -X POST https://integrate.api.nvidia.com/v1/embeddings \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer <PASTE_API_KEY_HERE>" \
      -d '{
        "input": ["NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。"],
        "model": "nvidia/llama-3.2-nv-embedqa-1b-v2",
        "input_type": "query",
        "encoding_format": "float",
        "truncate": "END"
      }'

    これにより、テキストの埋め込みベクトルが返ってきます。これにより、API カタログ上のモデルを利用できるようになりました。

    {
      "object": "list",
      "data": [
        {
          "index": 0,
          "embedding": [
            -0.006717681884765625,
            -0.0035381317138671875,
            0.002155303955078125,
    ...
    
            0.00251007080078125,
            -0.024017333984375
          ],
          "object": "embedding"
        }
      ],
      "model": "nvidia/llama-3.2-nv-embedqa-1b-v2",
      "usage": {
        "prompt_tokens": 22,
        "total_tokens": 22
      }
    }

    補足: NVIDIA NIM コンテナーをローカルで起動する

    ここではリランキングモデル Llama-3.2-NV-RerankQA-1B-v2 の NIM コンテナーをローカルで動作させる手順をご紹介します。NIM の起動自體は非常にシンプルであり、docker run コマンドでコンテナーを起動するのみです。

    NIM コンテナーを利用する際には、Developer Program (開発者プログラム) に參加 (無料) する必要があります。Developer Program への參加方法ですが、まずは Llama-3.2-NV-RerankQA-1B-v2 のページにアクセスし、アカウントにログイン (新規作成する場合は前述の API カタログの手順を參照) します。その後、モデルのページの「Build with this NIM」を押下してください。

    表示された畫面で「Self-Hosted API」を押下し、必要な情報を入力することで Developer Program に參加することが可能です。

    作成したアカウントの API キーを用いて、ローカルの docker で nvcr.io にログインします。Username には $oauthtoken、Password には API キー (= API カタログ上から取得した API キー) を入力してください。

    $ docker login nvcr.io
    Username: $oauthtoken
    Password: <PASTE_API_KEY_HERE>

    あとは以下のコマンドをシェルで動かすことで、Llama-3.2-NV-RerankQA-1B-v2 の NIM コンテナーがローカルで起動できます。ポート番號は 8200 とします。(初めて動かす場合はコンテナーおよびモデルのダウンロードがおこなわれるため、起動までにしばらく時間がかかります。)

    export NGC_API_KEY=<PASTE_API_KEY_HERE>
    export LOCAL_NIM_CACHE=~/.cache/nim
    mkdir -p "$LOCAL_NIM_CACHE"
    docker run -it --rm \
        --gpus all \
        --shm-size=16GB \
        -e NGC_API_KEY \
        -v "$LOCAL_NIM_CACHE:/opt/nim/.cache" \
        -u $(id -u) \
        -p 8200:8000 \
        nvcr.io/nim/nvidia/llama-3.2-nv-rerankqa-1b-v2:latest

    ポート番號 8200 で起動した NIM コンテナーに対して、以下のコマンドでリクエストを送ります。

    curl -X "POST" \
      "http://localhost:8200/v1/ranking" \
      -H 'accept: application/json' \
      -H 'Content-Type: application/json' \
      -d '{
      "model": "nvidia/llama-3.2-nv-rerankqa-1b-v2",
      "query": {"text": "NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。"},
      "passages": [
        {"text": "エヌビディアはアクセラレーテッドカンパニーです。"},
        {"text": "日本の首都は東京です。"},
        {"text": "2025年のCESでRTX 50シリーズが発表された。"}
      ],
      "truncate": "END"
    }'

    以下のように passage のインデックスがスコアの降順で返ってきます。

    {
      "rankings": [
        {
          "index": 2,
          "logit": -6.828125
        },
        {
          "index": 0,
          "logit": -15.9296875
        },
        {
          "index": 1,
          "logit": -17.0625
        }
      ],
      "usage": {
        "prompt_tokens": 123,
        "total_tokens": 123
      }
    }

    他の NIM を動かす場合は、下記の畫像のように API カタログ上で「RUN ANYWHERE」のタグがついているモデル (一覧) がダウンロード可能です。起動する際には、先ほどの起動コマンドのコンテナーの名前を変更するだけで利用することができます。

    RAG を実裝する

    モデルの準備が完了したので、ここからは LangChain を用いて RAG を実裝していきます。必要なライブラリをインストールします。

    pip install langchain==0.3.16 \
      langchain-nvidia-ai-endpoints==0.3.8 \
      langchain-community==0.3.16 \
      faiss-cpu==1.9.0.post1 \
      unstructured==0.16.17

    モデルの定義

    各モデルを Python から動かします。API カタログから取得した API キーを環境変數に設定します。

    import getpass
    import os
     
    if not os.environ.get("NVIDIA_API_KEY", "").startswith("nvapi-"):
        nvidia_api_key = getpass.getpass("NVIDIA API keyを入力してください: ")
        os.environ["NVIDIA_API_KEY"] = nvidia_api_key

    LLM として、日本語に特化した LLM である Llama-3.1-Swallow-70B-instruct-v0.1 を使います。

    from langchain_nvidia_ai_endpoints import ChatNVIDIA
     
    llm_name = "institute-of-science-tokyo/llama-3.1-swallow-70b-instruct-v0.1"
    llm = ChatNVIDIA(
      # セルフホストのNIMコンテナを使用している場合はURLの指定が必要。
      # base_url="http://localhost:8000/v1", # port: 8000
      model=llm_name,
      temperature=0.7,
      top_p=0.1
    )

    LLM にプロンプトを送って返答を受け取ります。

    print(llm.invoke("NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。").content)

    下記の出力を見ると、NVIDIA の GPU として 2022 年に発売された GeForce RTX 40 シリーズをあげています。

    NVIDIAの新しいGPUには、GeForce RTX 40シリーズがあります。具體的には、GeForce RTX 4090、GeForce RTX 4080、GeForce RTX 4070 Ti、GeForce RTX 4070、GeForce RTX 4060 Ti、GeForce RTX 4060などがあります。

    続いて、埋め込みモデルとリランキングモデルを定義します。それぞれ日本語での性能が高い Llama-3.2-NV-EmbedQA-1b-v2 および Llama-3.2-NV-RerankQA-1b-v2 を用います。

    from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings, NVIDIARerank
     
    # LLMに渡すドキュメントの數
    TOP_N = 10
     
    embedder = NVIDIAEmbeddings(
      # セルフホストのNIMコンテナを使用している場合はURLの指定が必要
      # base_url="http://localhost:8100/v1", # port: 8100
      model="nvidia/llama-3.2-nv-embedqa-1b-v2",
      truncate="END",
    )
    reranker = NVIDIARerank(
      # セルフホストのNIMコンテナを使用している場合はURLの指定が必要
      # base_url="http://localhost:8200/v1", # port: 8200
      model="nvidia/llama-3.2-nv-rerankqa-1b-v2",
      top_n=TOP_N,
    )

    まずは embedder によって文をベクトル化できることを確認します。

    print(embedder.embed_query("NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。"))

    下記の実行結果を見ると、ベクトルが返ってきていることがわかります。

    [-0.006717681884765625, -0.0035381317138671875, 0.002155303955078125, 0.02886962890625, ...]

    続いて reranker によって文の並べ替えができることを確認します。下の例だと、ドキュメントのインデックスが 2 → 0 → 1 の順番に並べ替えられていることが理想です。

    docs = [
      "エヌビディアはアクセラレーテッドカンパニーです。",
      "日本の首都は東京です。",
      "2025年のCESでRTX 50シリーズが発表された。"
    ]
    print(reranker._rank(documents=docs, query="NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。"))

    返り値は、以下のように Ranking オブジェクトのリストで返ってきています。Ranking オブジェクトは「ドキュメントのインデックス」と「スコア (logit)」を持っています。このリストの順番はスコアの降順となっており、インデックスが 2 → 0 → 1 の順番となっていることがわかります。次は文書を格納したベクトルデータベースを準備しましょう。

    [Ranking(index=2, logit=-6.828125), Ranking(index=0, logit=-15.9296875), Ranking(index=1, logit=-17.0625)]

    ベクトルデータベース

    さきほどまでで各モデルの挙動を確認することができました。ここからは RAG に必要なベクトルデータベースを用意します。今回は、NVIDIA Japan のブログ記事のうち 2025 年 1 月に公開された記事をいくつか用いることにします。該當記事のテキストを抽出するために、LangChain のUnstructuredURLLoader を使用します。

    from langchain_community.document_loaders import UnstructuredURLLoader
     
    urls = [
    ]
     
    loader = UnstructuredURLLoader(urls=urls)
    # データを読み取る
    articles = loader.load()
     
    # 読み取った記事を1つ見る
    print(articles[0].page_content)

    以下の出力のように、文章が該當の記事 (リンク) から抽出されていることがわかります。

    NVIDIA が生成フィジカル AI で Omniverse を拡張
    
    2025 年 01 月 07 日 投稿者: NVIDIA Japan
    
    Share
    
    Email0
    
    Cosmos 世界基盤モデル、Omniverse Mega Factory、ロボティクス向けのデジタルツイン ブループリントなどの新モデルが産業用AIの基盤を築く
    
    ...
    
    
    フィジカル AI シミュレーション用の 3D 世界を作成するには、世界の構築、物理屬性による世界のラベル付け、フォトリアル化という 3 つのステップが必要です。
    ...

    続いてこれらをベクトル化してベクトルデータベースに格納します。すべての記事をそのまま用いるとトークン數が LLM の最大入力トークン數を超えてしまうため、テキストを 256 文字毎に分割します。この分割されたテキストはチャンクと呼ばれます。また、分割によって文の意味が欠落しないように、チャンク間は 100 文字のオーバーラップを設けます。

    from langchain.text_splitter import RecursiveCharacterTextSplitter
     
    splitter = RecursiveCharacterTextSplitter(
      chunk_size=256,
      chunk_overlap=100,
      separators=[
          "\n\n",
          "\n",
          "。",
          "、",
          "",
      ],
      keep_separator='end',
    )
    # チャンクに分割する
    chunks = splitter.split_documents(documents=articles)
    # チャンクを1つ見る
    print(chunks[0].page_content)

    チャンクの中身を 1 つ見ると、以下の出力のように分割されたテキストが入っていることがわかります。

    NVIDIA が生成フィジカル AI で Omniverse を拡張
    
    2025 年 01 月 07 日 投稿者: NVIDIA Japan
    
    Share
    
    Email0
    
    Cosmos 世界基盤モデル、Omniverse Mega Factory、ロボティクス向けのデジタルツイン ブループリントなどの新モデルが産業用AIの基盤を築く
    
    Accenture、 Altair、 Ansys、 Cadence、 Microsoft、Siemensなどの大手開発企業がプラットフォーム ライブラリを最初に採用

    続いて、これらのチャンクをベクトルデータベースに格納します。ベクトルデータベースとして FAISS を使用します。埋め込みモデル (embedder) で各チャンクをベクトル化しています。これによりベクトルデータベースの準備も完了しました。次は RAG を実裝していきましょう。

    from langchain.vectorstores import FAISS
     
    # チャンクと埋め込みモデルを用いてFAISSのベクトルデータベースを作成
    vectorstore = FAISS.from_documents(
        documents=chunks,
        embedding=embedder,   
    )
    # (任意) ベクトルデータをローカルに保存
    vectorstore.save_local("faiss_index")

    RAG

    前項までで、モデル (LLM、埋め込みモデル、リランキングモデル) とベクトルデータベースの準備をしてきました。最後に RAG を実裝していきます。レトリーバーとして埋め込みモデルとリランキングモデルの両方を用います。

    from langchain.retrievers.contextual_compression import ContextualCompressionRetriever
     
    # 埋め込みモデルで取得するドキュメントの數
    #(リランキングモデルは、TOP_K個のチャンクから上位TOP_N個のチャンクを絞り込む)
    TOP_K = 50
     
    # 埋め込みモデルのみのレトリーバーを定義する
    base_retriever = vectorstore.as_retriever(search_kwargs={'k': TOP_K})
     
    # 埋め込みモデルとリランキングモデルの両方を用いたレトリーバーを定義する
    retriever = ContextualCompressionRetriever(
      base_retriever=base_retriever,
      base_compressor=reranker
    )
     
    # クエリに関連するチャンクを検索する
    retrieved_chunks = retriever.invoke("NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。")
    from pprint import pprint
    pprint(retrieved_chunks[0])

    検索結果の上位 1 位を見ると、2025 年に発表したばかりの「GeForce RTX 50 シリーズ」を言及したチャンク (page_content) が取れています。このことからも Llama-3.2-NV-EmbedQA-1b-v2 および Llama-NV-RerankQA-1b-v2 の性能の高さが伺えます。また、metadata にはソース (source) や関連度スコア (relevance_score) が格納されています。

    Document(id='1c56ac64-5c96-4000-b7b5-b9a5edca2549', metadata={'source': 'https://blogs.nvidia.co.jp/blog/nvidia-blackwell-geforce-rtx-50-series-opens-new-world-of-ai-computer-graphics/', 'relevance_score': 4.265625}, page_content='2025 年 01 月 08 日 投稿者: NVIDIA Japan\n\nShare\n\nEmail0\n\n【プレス リリース】ラスベガス – CES – 2025 年 1 月 6 日 – NVIDIA は本日、ゲーマー、クリエイター、開発者向けの最先端のコンシューマー GPU、GeForce RTX? 50 シリーズのデスクトップおよびノート PC の GPU を発表しました。')

    それではこの埋め込みモデルとリランキングモデルを併用したレトリーバーを用いて RAG を組み立てます。レトリーバーによって検索されたチャンクを LLM が參照しながら回答するようにプロンプトで指定します。

    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.output_parsers import StrOutputParser
    from langchain_core.runnables import RunnablePassthrough
     
    # プロンプトを定義
    template = """あなたは優秀なAIアシスタントです。與えられた情報をもとに、ユーザーの質問に回答してください。
    ## 文脈
    {context}
     
    ## 質問
    {input}
    """
    prompt = ChatPromptTemplate.from_template(template)
     
    # RAGのチェーンを定義
    rag_chain = (
      {"context": retriever, "input":RunnablePassthrough()}
      | prompt
      | llm
      | StrOutputParser()
    )

    上記の rag_chain が RAG になります。再掲になりますが、LLM を単體で用いた時は NVIDIA の新しい GPU として「GeForce RTX 40 シリーズ」を答えていました。

    print(llm.invoke("NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。"))
    # 出力:NVIDIAの新しいGPUには、GeForce RTX 40シリーズがあります。具體的には、GeForce RTX 4090、GeForce RTX 4080、GeForce RTX 4070 Ti、GeForce RTX 4070、GeForce RTX 4060 Ti、GeForce RTX 4060などがあります。

    続いて RAG の出力です。こちらは、2025 年に NVIDIA から新たに発表された GeForce RTX 50 シリーズについて回答しています。RAG を用いることで、LLM がより正確な回答を生成できていることがわかります。

    print(rag_chain.invoke("NVIDIAの新しく出たGPUには何がありますか?名前を教えてください。"))
    # 出力:NVIDIAの新しく出たGPUには、GeForce RTX 5090、GeForce RTX 5080、GeForce RTX 5070 Ti、およびGeForce RTX 5070があります。

    まとめ

    本記事では、埋め込みモデルおよびリランキングモデルについて解説しました。また、検索タスクでのベンチマークの結果から、埋め込みモデルの Llama-3.2-NV-EmbedQA-1B-v2 およびリランキングモデルの Llama-3.2-NV-RerankQA-1B-v2 の日本語における有効性を示しました。RAG の実裝を通してリランキングモデルや NIM の使い方をご紹介しました。RAG についてさらに學びたい方は、NVIDIAで RAG のオンライン コースを無料 (※ 2025 年 3 月現在) で提供しているのでそちらもご覧ください。


    関連情報

    +5

    Tags

    人人超碰97caoporen国产