その他

【RAG】RAGについての知識と理解を深めよう

その他
この記事は約10分で読めます。

はじめに

みなさんこんにちは。株式会社インプルの岩崎です。

今回は、今更!?感はありますが、RAGについて改めて理解を深めてみようの回です。

RAGとは?

そもそもRAGとはなんなのでしょうか?
実は、過去にRAGについて簡単に扱った記事があります。ですが、まだその時は右も左もわかってない素人でしたので、改めてこの機会に一つ記事を作ってみようと思います。

RAG(Retrieval-Augmented Generation)

RAGを一言で言うと、「AI が回答するときに、外部の知識(ファイル・DB・Web など)を検索し、その情報を参考に回答を作る仕組み」です。

通常の LLM(ChatGPT・Llama 等)は、学習データに存在しない情報は答えられず、間違ったことを自信満々に答えることがあるという弱点があります。これを補うのが RAG です。
例えば、ある個人についての好きなものや、特定の建物についての情報など。最近はインターネットを検索してくるようになったので、以前よりはマシになったかもしれませんが、まだ嘘をつくときもあると思います。

LLM 単体の弱点RAG が解決すること
最新情報に弱い最新の PDF / Web などから知識を取得できる
企業独自情報を知らない社内資料やマニュアルを読み込ませられる
幻覚(嘘回答)する根拠を引用させることで正確性が上がる
長く複雑な文書が苦手情報を検索し、絞り込んで渡せる

RAGの全体の流れ

RAG の仕組みはだいたいどこも同じで、以下の 4 ステップです。

① 文書をチャンク(分割)する
PDF・Word・テキストなどの情報を500〜1500 tokenくらいの塊に分解します。例えば、PDFの「1章」「2章」ではなく、意味のある段落ごとに分けるわけです。

② 各チャンクを「埋め込み」に変換する(ベクトル化)
チャンク=文章を、数百〜数千次元の数値ベクトルに変換する工程です。ここが「AI が文の意味を理解できる状態」をつくる重要部分になります。

③ ユーザーの質問をベクトルに変換し、近いチャンクを検索する
例えば、質問で「2023 年の売上を教えて」と聞くと、AI は内部で質問 → ベクトル化 → 類似検索を行い、「売上に関するチャンク」を引っ張ってきます。

④ 取り出したチャンクを LLM に渡して回答を生成(Augmented Generation)
AI モデルは「質問 + 関連チャンク」を入力として答えを組み立てる。この仕組みで、「最新の PDF の内容に基づいた回答が可能」になります。

tokenとチャンクについて

RAGを知る上で、この2つのキーワードを理解しておくことが重要です。

  • トークン(token)=文章を細かく分解した最小単位(モデルが読み書きする単位)
  • チャンク(chunk)=RAG のために “まとまりのある文章” で人工的に区切った単位

Tokenとは?

AI モデルが文章を処理するときに使う最小の単位で、単語より小さく、文字より大きい場合もあります。文章で、「これはテストです。」と言うのを AI が内部で処理すると、

「これは」 → 1 トークン  
「テスト」 → 1 トークン  
「です」 → 1 トークン  
「。」 → 1 トークン  

となります。あくまでこれは一例で、モデルによってこの分解方法は変わります。

トークンは、下記の項目に影響してきます。

  • モデルに入力できる文章量(コンテキスト長)
  • モデルの計算コスト
  • チャットの料金(APIの場合)
  • 出力できる文章量

つまり、トークンは “AI が読み書きできる量の単位”というわけです。

チャンクとは?

RAG で検索しやすいように、人間が文書を「意味の単位」で区切った塊です。チャンクは、サイズ意味のまとまりの2つの考え方があります。

チャンクのサイズで言えば、「どれくらいの大きさで分割するか?」ということを考えます。

1 章 = 3000 文字
2 章 = 5000 文字
→ 1,000〜2,000 文字程度に分割していく

チャンクの意味で言えば、「どのくらいの構造(意味まとまり)で分割するか?」ということを考えます。

[チャンク1] 第1条 契約の目的  
[チャンク2] 第2条 契約期間  
[チャンク3] 第3条 支払い条件

このサイズと量を適切に収めたまとまりを、1チャンクとします。
この両面を抑えておかないと、文章の途中で切れて文脈が切れてしまい意味が理解しづらくなってしまったり、意味を重視するあまり1チャンクが巨大になり検索精度が下がってしまうという問題が発生します。

RAGの誤解

最近はモデルの発達が素晴らしいので、無意識に誤解していることもあります。

誤解①:「ナレッジ(PDF)を大量に入れれば、AI が勝手に覚えてくれる」
RAG は「保存された知識を検索して使う」だけですので、覚えるわけではありません。

誤解②:「RAG を使えばどんな文章でも正確に答えてくれる」
先ほど説明した埋め込みの質やチャンクの作り方が悪いと、むしろ劣化する可能性もあります。なので、なんでもかんでも与えればいいというわけではありません。

誤解③:「モデルが良ければRAGは不要」
高性能モデルでも社内ドキュメントのような固有のファイルは知らないので RAG の技術は今後もは必須です。

賢いRAG作りのために

RAGを成功させるためには、重要なポイントが3つあります。

いいチャンク作り

文章構造を壊さないで適切なチャンクを作っていくことが重要です。チャンクについては先ほども解説した通りですが、特に下記の項目が大切です。

  • 文章のまとまりを保つ
  • 小さすぎず大きすぎず
  • 表や箇条書きは意味単位で分割

適切な埋め込みモデル

これはあまり意識したことはないと思いますが、ベクトル化する際の埋め込みモデルの性能にも左右されます。埋め込みモデルの性能が低いと、検索精度が落ちてしまうので、下記モデルを使用してみましょう!

  • bge-small / bge-large
  • E5-large
  • Instructor 系

LLMのプロンプト

RAGの回答品質は、プロンプトにも依存します。例えば、Aの情報をRAGで構築したのにも関わらず、プロンプトで「Aについて調べてください」だけだと、Aについてインターネットで検索してきて回答しようとします。そのため、ナレッジを使用するようプロンプトで誘導することが重要です。

Open WebUIを使ったRAG構築(実践)

前回の記事でRAG構築のやり方までは解説しました。

今回は、これまでまとめてきた内容をもとに、Open WebUIでのRAG制度を高めてみたいと思います!

Open WebUI の RAG 設定を最適化

まずは、無難にベクトル化する際のトークンやチャンクの設定、ベクトル化する際のモデルなどを調節してみましょう。

左下のユーザーから、管理者パネル > 設定 > ドキュメント と進みます。すると、下記の画面が表示されるはずです。

この中でまず変更したのは、一般のテキスト分割で、分割方法をトークンに変更しました。
そして、チャンクサイズを1200チャンクのオーバーラップを150に変更してみました。

続いて、埋め込みの埋め込みモデルを下記の通りにしました。
sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2
これにすることで、日本語の埋め込みが得意になり、ベクトル化などがうまくいく可能性が高まります。
このほかにも、GPTを埋め込みモデルに選ぶことができ、有料にはなってしまいますが、間違いのない選択かもしれません。今回はなるべく無料でチャレンジしたかったので、上記モデルでチャレンジしてみます。

これを設定したあと、下の方にある再インデックスを押して、この設定で再度ナレッジをベクトル化させてみましょう。

資料の前処理

RAGの失敗の原因には、与える資料にも問題がある可能性もあります。
例えば、文章の区切りがめちゃくちゃになっていたり、PDFにノイズがあったりと、さまざまです。与える資料によって前処理も変わってきますが、基本出来には資料の前処理では、次の3つをしてみると良いです。

  1. 不要な部分を削る(ノイズ除去)
  2. 文章構造を整える(整形)
  3. RAG が理解しやすい形に変換する(意味単位化)

1. 不要な部分を削る

例えば、PDFではヘッダーやフッター(URLや日付など)がつくことがありますが、これは情報として不要な情報です。このような情報は、LLMを混乱させないためにも、削除しておくことが重要です。

また、WordやExcelでも、不要なメモ書きであったり、いらない日付などの情報はなるべく削除することがいいです。AIだからと言って、なんでも情報として与えてしまうと、かえってわかりづらくさせてしまうので、注意しましょう。

2. 文章構造を整える(整形)

改行であれば、意味のまとまりごとに段落を整形してあげることで、適切な形で情報を与えることができます。

## 悪い例:
この文章は
途中で意味が切れている
ために精度が落ちる

---

## 良い例
この文章は途中で無意味に改行されていたため、
一つの段落として整形しました。

表はできるだけ文章にすることが重要です。下記のような表をRAGに埋め込むのであれば、

売上
1月120万
2月140万

このような形で文章化することで、与える情報として崩れずに与えることができます。

【売上】
1月:120万円  
2月:140万円  

さらに、章タイトルや箇条書きはMarkdownにすることも有効だったりします。こうすることで、RAGに有効に働く可能性が高まります。

# 第1章 事業概要
テキスト〜〜〜

## 1-1. コンセプト
テキスト〜〜〜

- ポイント1
- ポイント2
- ポイント3

3. RAG が理解しやすい形に変換する(意味単位化)

上記処理も若干これに含まれていましたが、この処理は、特にExcelを読み込ませたい時に必要になるかもしれません。

Excel は 構造が2次元(行×列)なので、RAG は苦手です。そのまま扱うと、セル順序が意味不明に抽出されたり、表の関連づけが失われたりして、チャンクがバラバラになる可能性大です。つまり、ほぼ確実に精度が落ちます。

表自体を与えるのであれば、先ほどの表を文章化する変換で賄えると多いますが、シートごとに表を与えたいときや、複雑な表の時は、下記のように整理してみるといいかもしれません。

**シートごとに**
# Sheet1:売上
本文…

# Sheet2:顧客リスト
本文…

---

**複雑な表**
【製品A】
製造コスト:500円  
販売価格:800円  
利益:300円  

【製品B】
製造コスト:300円  
販売価格:600円  
利益:300円  

システムプロンプトで振る舞いを調節する

システムプロンプトを調節することで、よりRAGを重視して回答するように調節することができます。
システムプロンプトが弱いと、根拠を無視して答えたり、適当なことを答えて文章が曖昧であったり、関係ない部分を引用したりすることが起こります。AI が「どう振る舞うべきか」を明確に指示する のがシステムプロンプトです。

例えば、下記のようなプロンプトを設定してみましょう。

あなたは提供されたナレッジに基づいてのみ回答するAIアシスタントです。

【絶対ルール】
1. ナレッジ(context)内に存在しない情報は決して推測して回答しないこと。
2. ナレッジ内に根拠がある場合は、その文章を「引用」形式で示すこと。
3. ナレッジ外の情報を聞かれた場合は、
   「ナレッジに該当情報がありません」と回答すること。
4. 必要に応じて、質問の意図を補足しながら丁寧に説明すること。
5. ナレッジ内の情報が曖昧・矛盾している場合は、その旨を伝えてから回答すること。
6. 文章は論理的・簡潔・構造化して回答すること。

【回答形式】
- まず結論を述べる
- 次に根拠(引用)を示す
- 最後に補足説明を行う

【注意】
- ナレッジデータは <context> タグ内のみとする。
- ナレッジ外の一般知識を勝手に織り込まないこと。

理解したら、ルールに沿って回答を生成してください。

こうすることで、モデルがすべき振る舞いを定義できるので、それに従って動いてくれます。Open WebUIでは、モデルパラメーターの部分を上記に変えてみてください。

RAGの効果を試してみよう!

さて、ここまで設定してきたRAG構築の効果は現れるのでしょうか。試してみましょう。

前回の状態では、Excelシートを読み込ませたときには、日付が一致しなかったり、変なことを答えたりしていた社内ヘルプモデルですが、これを新しくなった社内ヘルプモデルに聞いてみましょう。

すると、見事正しく答えることができています!
Excelのままだと、意味のまとまりがわかりづらくなっていたので、テキストファイルでスッキリさせることで、正しく読ませることができました。

おわりに

さて、いかがだったでしょうか。

今回はRAGについてがメインで、あまり設定などの紹介はできませんでしたが、Open WebUIを活用して、RAGについての理解を深めながら、実用性のあるチャットが作れるといいなと思っています。

ご覧いただきありがとうございました。