【Dify】Contextual Retrievalを使用したアプリケーションをDifyで実装してみた

# はじめに
今回はContextual Retrievalという手法を使用したアプリケーションを、Difyで実装してみました。

**●Contextual Retrievalについて**
・Contextual Retrievalとは
従来のRAGの手法に加えて、分割された文章(チャンク)ごとに文脈を記載することにより、精度を上げることができる手法で、2024年の10月下旬にAnthropicから発表されました。

詳しくは以下のサイトをご参照ください。

https://www.anthropic.com/news/contextual-retrieval

**●Difyについて**
Difyは独自のアプリケーションを作成できる、生成型AIツールの開発プラットフォームです。

https://dify.ai/jp

また、今回の実装にあたって、以下の動画を参考にしました。

https://youtu.be/STMLX_UrK9E?si=Uhm1P8hTFIHYRnip


# 導入

アプリケーションの全体像は以下のようになっています。
今回は、「チャットボット」のChatflow機能で作成しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/edf7033a-42eb-0150-8898-150150b5d933.png)

**①質問の入力**
**②ナレッジの取得**
**③LLMでの回答**
**④回答の出力**

という流れになっています。

また、今回ナレッジとして、以下の文章を使用しています。
指示語が多い文章を、生成AIに作成してもらいました。
```
それはある晴れた日のことだった。私はその日、友人の佐藤と一緒に公園へ行くことにした。あの公園は私たちのお気に入りの場所で、いつもそこでリラックスして過ごすのが楽しみだった。この公園には大きな池があり、その周りには美しい花々が咲いている。あれを見ると、いつも心が和むのだ。

その日は特に天気が良く、青空が広がっていた。私たちはまず、あの池のほとりに座っておしゃべりを始めた。池の水面には鴨が泳いでいて、その姿を見ているだけで心が癒された。それから、あの大きな木の下でピクニックをすることにした。この木はとても古く、何年も前からこの場所に立っている。その木陰はとても涼しく、私たちはそこでゆっくりと時間を過ごした。

ピクニックの準備をしていると、佐藤が「あれを見て」と指差した。そこには小さなリスがいて、木の実を一生懸命に集めていた。その姿がとても可愛らしく、私たちはしばらくの間、そのリスの動きを見守っていた。リスが去った後、私たちは持ってきたサンドイッチやフルーツを広げて、楽しいピクニックを始めた。

その後、私たちは公園内を散策することにした。あの小道を歩いていると、突然、あれが目に入った。それは小さなカフェで、私たちはそのカフェに入ってみることにした。カフェの中はとても落ち着いた雰囲気で、木製の家具や暖かい照明が心地よさを感じさせた。私たちはそこでコーヒーを飲みながら、さらにおしゃべりを楽しんだ。佐藤は新しい仕事の話をしてくれて、その話を聞くのがとても興味深かった。

そのカフェを出た後、私たちは再び公園内を歩き回った。この公園にはたくさんのベンチがあり、どのベンチも座り心地が良さそうだった。私たちはその中の一つに座り、しばらくの間、ただ風景を眺めていた。あの瞬間、私は本当に幸せだと感じた。風が心地よく吹き、木々の葉がささやく音が耳に心地よかった。

その後、私たちは公園の奥にある展望台に向かった。展望台からは公園全体が見渡せ、その景色は本当に素晴らしかった。佐藤と一緒にその景色を眺めながら、これからの計画や夢について語り合った。あの時間は本当に特別で、私たちの友情がさらに深まったように感じた。

その日が終わる頃、私たちは公園を後にした。あれほど楽しい一日を過ごせたのは久しぶりだった。友人と一緒に過ごす時間は本当に貴重で、これからも大切にしていきたいと思った。あの公園での思い出は、私にとって一生忘れられないものになるだろう。帰り道、佐藤と一緒に笑いながら話したこと、そしてその日の出来事すべてが、私の心に深く刻まれた。

その夜、家に帰ってからも、あの公園での一日を思い返していた。あの瞬間、あの場所、あの友人との時間が、私にとってどれほど大切なものかを改めて感じた。これからも、あの公園での楽しい時間をたくさん作っていきたいと思った。
```

今回はテキストをWordに入力し、PDFにしていますが、テキストファイルでのアップロードも可能です。

文脈がないものは、サンプル文書.pdfという名前で登録しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/728201ad-75ff-6d5f-e7ff-87252a59011a.png)


また、今回Contextual Retrievalの手法を使用するにあたって、チャンクごとに生成AIを用いて文脈を追加しています。
文脈を追加したものは、サンプル文書2.pdfという名前で登録しています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/8f221545-e077-3c2f-887c-15b5f9d0de8f.png)


それではアプリケーションの詳細について説明します。

**①質問の入力**
「開始」ノードでは、ユーザからの質問を入力します。

**②ナレッジの取得**
「知識取得」ノードでは、ナレッジから情報を取得し、参照します。
上の部分は文脈なし、下の部分は文脈ありのナレッジを登録しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/79f00647-2aad-8c91-0ace-db2ee7b61335.png)

また、検索設定では、トップKは1に設定します。
これは、登録したナレッジから回答文を生成する際に、チャンクを1つだけ取り出すという意味です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/2711cde0-c329-bd06-9819-da2fedfe6f5f.png)


**③LLMでの回答**
文脈なしの場合も、文脈ありの場合でも、プロンプトは同じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/acdac65c-7b00-6696-eb2f-0cedb47b7eb5.png)

**④回答の出力**
回答の出力は以下のようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/f72c327f-fd9d-3638-ef42-ea38901aa4ab.png)


# 実行結果
今回文章の中で取り扱った部分について説明します。
チャンク002では、佐藤が何かを指差している場面が書かれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/9a0fa9e1-fc64-94ba-c3de-c7b828b96063.png)


その答えは、チャンク003を見ればリスであると分かるのですが、もしチャンク002を抜き出した場合、何を指差したのか分かりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/f871e7a0-87b0-c809-ec80-a4f9ef64d62c.png)

今回の手法では、**文脈:池のほとりでおしゃべりをした後、大きな木の下でピクニックを始める準備をしているときに、佐藤がリスを見つける場面。:** という文脈を追加しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/1e8f3c68-646e-f928-53f9-2ac62839ab55.png)


今回文脈を追加したおかげで、佐藤が指差したものは何ですかという質問に対して、リスであると回答することができました。

![画像 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/dd2824c3-59d3-6ba1-ab8d-d5b517f297a3.png)


# まとめ
今回は、DifyでSelf-Routeの技術を使用した、数学の回答解説生成のアプリケーションを作成してみました。
今回の例が約1000文字の文章であったこと、文脈を手動で入力したこともあり、あまり効果を感じにくかったですが、10000文字の文章を取り扱った場合や、仮にその文章のチャンクごとに文脈を自動で生成することができれば、かなり効果を感じるだろうと思います。

今後もDifyの新機能の検証など、様々なことに取り組んでいけたらなと考えています。