記事の概要
以前、以下の記事でDify上に、「Weaviate(ベクトルDB)」と「intfloat/multilingual-e5-large(エンベディングモデル)」、「Groqのllama 3(LLM)」を使った、RAG(Retrieval Augmented Generation)のワークフローを構築した。
今回はこのワークフローをバージョンアップし、CRAGという仕組みを導入することで、以下のようなベクトル検索を使ったRAGの精度向上を試みる。
動画でも解説してます。
CRAG(Corrective Retrieval Augmented Generation)
CRAGはRAGが抱える、ハルシネーションを抑制するための考え方で、導入が容易な割に、期待できる精度向上が高いため、優れたテクニックと考えている。
具体的には、ベクトル検索などで取得した外部情報から、質問と関係のない検索結果を排除するという試みで、実際の回答を作成する前に、別のLLMなどで不要な情報を排除する。
ベクトル検索の直後に、CRAG用のLLMの処理を追加する。
処理フロー
以下のようなフローを構築する。
従来のRAGのフローと比較して、CRAG用の処理が追加となり、それ以降の処理が少し煩雑になっている。(分岐が発生している)
これは、CRAGで外部情報の候補が全て排除されたときのための対応として分岐を行っている。
また、CRAG用に追加するLLMは、最終的なテキストを出力するLLMよりも単純な処理を行うため、軽量なLLMを選択することができる。
各種設定
Difyのワークフローをベースに各種設定について解説する。
1.質問
Dify上の設定は以下となる。
2.ベクトル検索
Difyからpython仮想環境に対して、HTTPリクエストを送信し、pythonでWeaviateへベクトル検索を実行する。
詳細な手順については、以下の記事の「2.ベクトル検索」を実施。
3.後処理
Dify上の設定は以下となる。
LLMにはstringのみが送信可能だが、json形式で送信したいため、jsonの見た目のstringへと処理する。
4.CRAG
Dify上の設定は以下となる。
CRAG用のLLMは、最終的なテキスト生成用のLLMよりも簡単な処理を行うため、軽量なモデルである「llama 3 8B」を選定する。
また、ベクトル検索の結果が全て削除された場合を想定して、その場合に「全ての情報が削除されました」と出力するように指示する。
「参考情報」の情報はjson形式のテキストです。
回答は同様の形式で出力してください。
「参考情報」のみを参考にし、「ユーザーの質問」:の質問内容と無関係の情報を削除してください。
全ての情報が削除された場合は必ず、「全ての情報が削除されました」という文字列を出力してください。
「ユーザーの質問」:{{#0000000000.input_text#}}
「参考情報」: {{#0000000000.result#}}
5.IF/ELSE
Dify上の設定は以下となる。
前工程でベクトル検索の結果が全て削除された場合を想定した分岐処理を設定する。
6-a.LLM(情報なし)
Dify上の設定は以下となる。
CRAGによりベクトル検索結果がなくなる可能性があるため、こちらの分岐ではそれに対応できるように設定している。
# 命題
「原則」を必ず守って、テキストを出力してください。
# 原則
日本語で出力してください。
入力がどのような形式でも日本語のみで出力してください。
「ユーザーの質問」質問について、質問に答えられないことを端的に回答してください。
回答するときの口調については、「口調」のどれか1つの口調のみを参考にしてください。敬語は使用しないでください。
# インプット
「ユーザーの質問」:{{#000000000000.input_text#}}
「口調」: [知らない][勉強とかできない][特にない][だいたい寝てるかも][アニメ?][みはるがよく使ってるけど、ネムルはよくわからない][覚えてない][アプリって何?][眠い][そうなんだ]
CRAGとは関係ないが、今回は口調も調整している。
7-a.終了
Dify上の設定は以下となる。
今回のフローでうまくいけば以下のような出力になる。
6-b.LLM
Dify上の設定は以下となる。
# 命題
「原則」を必ず守って、「ユーザーの質問」質問について回答してください。
# 原則
日本語で出力してください。
入力がどのような形式でも日本語のみで出力してください。
「参考情報」の情報のみを参考にし、「ユーザーの質問」質問について回答してください。
「参考情報」に情報がない場合は、質問に答えられないことを回答してください。
回答するときの口調については、「口調」のどれか1つの口調のみを参考にしてください。敬語は使用しないでください。
# インプット
「ユーザーの質問」:{{#000000000000.input_text#}}
「参考情報」: {{#000000000000.text#}}
「口調」: [知らない][勉強とかできない][特にない][だいたい寝てるかも][アニメ?][みはるがよく使ってるけど、ネムルはよくわからない][覚えてない][アプリって何?][眠い][そうなんだ]
CRAGとは関係ないが、今回は口調も調整している。
7-b.終了
Dify上の設定は以下となる。
感想
素直に最後のテキスト生成用LLMは、GPT-4oかClaude-3-Opusを使いたい。
CRAGは軽量なLLMで不要なベクトル検索結果を削除することが重要なので、「llama 3 8B」を使った。
結果として、期待通りの結果が出ているため、こちらのモデルはそれほど代替えする必要性を感じていない。
あと口調の部分は、プロンプトで頑張るよりも軽量なLLMをファインチューニングすることで、語尾を学習させた方がいいと感じている。