【Dify】RAGチャットボットのワークフローとナレッジを作る|
前回の記事では、ブラックボックスだったチャットボットを、処理を工程ごとに確認できる「ワークフロー型」に切り替えたい、という話を書きました。
今回は、実際にDifyでワークフローとナレッジをどう作ったか、工夫した点とつまずいた点をまとめます。
まずは最小構成のワークフローを作った
ひとまず、次の流れで作りました。
- 質問を受け取る
- 挨拶だった場合は、再度質問を聞き直す
- 質問が、このチャットの対応範囲内かどうかを判定する
- 範囲内なら、ナレッジを検索して回答する
前の仕組みでは、これらをすべて1つのプロンプトに詰め込んでいました。今回は工程ごとに分けたので、それぞれの工程が何を出力したかを個別に確認できます。
RAGに入れたデータ
ナレッジに登録しているのは、次の2つです。
- 過去の質問と回答をMarkdown形式で書いたFAQ
- 用語集
【用語集を入れた理由。例:略語や専門用語の揺れに対応するため、など】
工夫した点:1つのQ&Aを「1ファイル=1チャンク」にする
FAQは1件1ファイルで登録する
FAQは、1件の質問と回答につき1ファイル で登録しています。書式は次のように統一しました。
## 質問
(質問の内容)
## 回答
(回答の内容)
識別子は「絶対に出てこない文字列」にする
Difyのナレッジには、チャンクを分割する位置を決める 識別子 を設定できます。ここで、1つ注意点があります。識別子に指定した文字は、分割のときにチャンクから取り除かれます。
そのため、たとえば識別子を ## にすると、## 質問 と ## 回答 の位置でも分割されてしまい、質問と回答が別々のチャンクになってしまいます。
一般モードでは、検索でヒットしたチャンクが、そのままLLMに渡されます。質問だけがヒットして、回答を含まないチャンクが渡されてしまうと、AIは答えを受け取れません。
そこで、識別子には abababababababa のような、データの中に絶対に出てこない文字列 を指定しました。識別子では分割されないので、質問と回答が必ずセットで検索結果に出てきます。
最大チャンク長は4000文字にする
識別子で分割しない代わりに、最大チャンク長を超えた部分は強制的に分割されます。そこで、最大チャンク長を 4000文字 にしました。1件のFAQがこの長さに収まっていれば、1ファイルが、そのまま1つのチャンクになります。
つまり、「ファイルの単位」を、そのまま「検索の単位」にしたわけです。
つまずいた点:Top-kの設定が2か所ある
精度検証をしているときに、ハマったことがあります。
知識検索のTop-kの設定箇所が、2つあった のです。
私は精度検証のとき、ワークフロー内のTop-kを変更して、結果を見比べていました。ところが、変更したのに、その通りに反映されないことが何度かありました。
原因はまだ断定できていませんが、ナレッジ登録側の設定が優先されている可能性が高い と考えています(要確認)。
同じようにTop-kを調整して「変えたのに挙動が変わらない」場合は、ナレッジ側の設定も確認してみてください。
まとめ
- ワークフローは、まず最小構成で作り、工程ごとに確認できる形にした
- FAQは1件1ファイルにし、識別子にはデータに出てこない文字列を指定して、質問と回答が分割されないようにした
- 識別子に使った文字はチャンクから取り除かれ、最大チャンク長を超えると強制分割される点に注意する
- Top-kは、ワークフロー内とナレッジ登録側の2か所にある。変更が反映されないときは、両方を確認する
