TT Lab
はじめる
学ぶ 学習パス コース

LLMエンジニアリング

RAGパイプラインと評価

TT Labで続きを見る

目標

文書をチャンクに分けてインデックスし、クエリで検索し、検索品質を指標で測定し、根拠のない回答と答えられない質問を除外する、RAGパイプライン一式を作ります。

なぜ重要なのか

RAGで最もよくある間違いは、検索の失敗と生成の失敗を区別しないことです。回答がおかしいときにプロンプトから直しますが、正解の文書がそもそも検索されなかったなら、プロンプトをどれだけ磨いても無駄です。

そのため、このラボは検索の指標を先に計算します。Recall@3は、正解の文書が上位3個の中に入ったかを、MRRは、何位に出たかを見ます。この数値が低いなら、手を入れる場所はリトリーバーで、ジェネレーターではありません。

次に、根拠の判定と拒否のルールを作ります。検索スコアが低いときに答えないのは、機能不足ではなく安全装置です。関係のない文書を根拠にもっともらしい答えをでっち上げるより、わからないと言うほうがはるかによいです。

モデルは使いません。検索と評価はすべてnumpyで計算でき、その部分がRAGの品質の大部分を決めるからです。

ステップ

作業ディレクトリは/root/llmで、トークン化のルールは前のラボと同じです(小文字に変換してから[가-힣a-z0-9]+。この正規表現にはハングルの範囲が含まれます)。

  1. docsの各bodyをピリオド(.)で分け、前後の空白を削除して空の断片を捨てたチャンクを、/root/llm/chunks.tsvに保存してください。形式はdocs.id<탭>청크번호<탭>본문で(プレースホルダーはタブとチャンク番号、本文です)、チャンク番号は文書ごとに0から始まります。文書の順に書きます。
  2. チャンク単位のTF-IDF行列を/root/llm/chunk_tfidf.npyとして保存してください。形は(チャンク数, 語数)で、語は、チャンク全体から集めた語彙を昇順にソートしたものです。idfのNはチャンク数で、式と正規化は前のラボと同じです。
  3. 下のクエリ8個について、上位3個のチャンクを/root/llm/retrieved.tsvに질의번호<탭>순위<탭>docs.id<탭>청크번호<탭>점수の形式で保存してください(プレースホルダーはクエリ番号、順位、チャンク番号、スコアと、その間のタブです)。合計24行で、スコアは小数点以下6桁、同点なら文書idが小さいほう、その次にチャンク番号が小さいほうが先になります。
    1. 인덱스를 만들었는데 왜 순차 스캔인가(韓国語で「インデックスを作ったのに、なぜシーケンシャルスキャンなのか」という意味です)
    2. 복합 인덱스는 컬럼 순서를 어떻게 정하나(韓国語で「複合インデックスは、列の順序をどう決めるのか」という意味です)
    3. 격리 수준을 올려도 안 잡히는 이상 현상은 무엇인가(韓国語で「分離レベルを上げても防げない異常現象は何か」という意味です)
    4. 페이지 폴트가 잦으면 왜 느려지나(韓国語で「ページフォールトが多いと、なぜ遅くなるのか」という意味です)
    5. 가상 주소를 물리 주소로 어떻게 바꾸나(韓国語で「仮想アドレスを物理アドレスにどう変換するのか」という意味です)
    6. 연결 거부와 타임아웃은 무엇이 다른가(韓国語で「接続拒否とタイムアウトは何が違うのか」という意味です)
    7. 큰 요청만 멈추는 이유는 무엇인가(韓国語で「大きなリクエストだけが止まる理由は何か」という意味です)
    8. GPU 에서 워프란 무엇인가(韓国語で「GPUでワープとは何か」という意味です)
  4. 上のクエリの正解の文書は、順に24, 25, 27, 12, 11, 19, 17, 6です。Recall@3とMRRを計算して、/root/llm/metrics.tsvに2行で保存してください。1列目はrecall_at_3とmrr、2列目は小数点以下3桁の値です。Recall@3は、正解の文書が上位3個の中にあれば1と数えて、クエリ数で割った値で、MRRは、正解が最初に出た順位の逆数を平均した値(なければ0)です。
  5. クエリ1の上位3個のチャンクの本文を、順位の順に1行ずつ/root/llm/context.txtに保存してください。
  6. 下の回答候補3個が、ステップ5のコンテキストに基づいているかを判定して、/root/llm/grounded.tsvに번호<탭>겹침비율<탭>판정の形式で保存してください(プレースホルダーは番号、重なりの割合、判定と、その間のタブです)。重なりの割合は、回答のトークンを重複なしで集め、そのうちコンテキストのトークン集合に入っているものの割合で、小数点以下3桁です。0.6以上ならgrounded、そうでなければhallucinatedです。
    1. 인덱스는 값으로 정렬된 구조라 컬럼에 함수를 씌우면 그 정렬이 쓸모없어진다(韓国語で「インデックスは値でソートされた構造なので、列に関数をかけると、そのソートが役に立たなくなる」という意味です)
    2. 옵티마이저가 인덱스를 쓰지 않는 것은 대개 옳은 판단이다(韓国語で「オプティマイザーがインデックスを使わないのは、たいてい正しい判断だ」という意味です)
    3. 인덱스를 만들면 어떤 쿼리든 언제나 세 배 빨라진다(韓国語で「インデックスを作れば、どんなクエリでもいつも3倍速くなる」という意味です)
  7. コーパスにないクエリ3個について、最高スコアと判定を/root/llm/refusal.tsvに번호<탭>최고점수<탭>판정の形式で保存してください(プレースホルダーは番号、最高スコア、判定と、その間のタブです)。スコアは小数点以下6桁で、0.15未満ならrefuse、そうでなければanswerです。
    1. 김치찌개 맛있게 끓이는 법(韓国語で「キムチチゲをおいしく作る方法」という意味です)
    2. 프리미어리그 이번 주 경기 일정(韓国語で「プレミアリーグの今週の試合日程」という意味です)
    3. 제주도 항공권 최저가 예약(韓国語で「済州島の航空券の最安値予約」という意味です)
  8. /root/llm/rag_report.tsvに3行で要約を残してください。chunks<탭>청크수、queries<탭>질의수、recall_at_3<탭>값の形式です(プレースホルダーはタブとチャンク数、クエリ数、値です)。

参考

文書を文単位のチャンクに分ける

ピリオドで分けたあと、前後の空白を削除して、空の断片は捨てます。チャンク番号は、文書ごとに0からやり直します。

チャンク単位でインデックスを作る

idfを計算するときに、Nが文書数ではなくチャンク数であることに注意してください。

クエリ8個で上位3個のチャンクを検索する

クエリも同じ方式でベクトルを作ります。同点処理のルールを守ってください。

Recall@3とMRRを計算する

正解の文書が上位3個の中にあれば1、なければ0です。MRRは、正解が出た順位の逆数を平均します。

コンテキストを組み立てる

クエリ1の検索結果を、順位の順に1行ずつつなげます。

回答がコンテキストに基づいているかを判定する

回答のトークンを重複なしで集めて、コンテキストにある割合を数えます。基準値を超えるかどうかで判定します。

コーパス外の質問を拒否する

最高スコアがしきい値未満なら、答えないと表示します。スコア自体も記録する必要があります。

要約レポートを作る

チャンク数、クエリ数、Recall@3の3つを、名前と値のペアで残します。