はじめてのDify × RAG：試してわかった便利さ

# はじめに

こんにちは。普段はエンジニアとして **[FutureVuls](https://vuls.biz/lp/)** を担当しております。

昨年のアドカレ（[フューチャー Advent Calendar 2023](https://qiita.com/advent-calendar/2023/future)）以来、Qiita には1年ぶりの投稿となりました。昨年に2本投稿したうちの1つ（[asdf で開発言語と利用ツールのバージョン管理](https://qiita.com/RuyPKG/items/d4ea8baab1e0a17ae927)）には

> 今年は大規模言語モデル(LLM)が「ビジネスや日常生活で多用されるようになった年」であり、OpenAI の ChatGPT、GitHub の Copilot、Google の Bard などは、多くの開発エンジニアが「アシストツール」として多用していると思います。

と執筆した点からの差分を振り返ると、「ビジネスや日常生活で多用されるようになった年」から「もはや AI なしでは競争に勝てない年」になったと感じております。

ちなみに、私は趣味のリサーチやプログラミングでは、以下の AI サブスクに課金しております。

* [ChatGPT](https://openai.com/ja-JP/chatgpt/overview/)
* [Gemini Advanced](https://gemini.google/advanced/?hl=ja)
* [Felo](https://felo.ai/ja/search)
* [Perprexity](https://www.perplexity.ai/)
* [Mapify](https://mapify.so/ja/app)

これらのツールと使うと「情報収集」や「思考」にかかる時間が大幅に削減され、かつ、自己スキルの「即時拡張」が可能です。まさに、AI が体の一部になった時代として、各サービスから日々発信される Release Note を楽しんでいる最中です。

ただ、AI ツールを使い倒しながら日々のニュースを吸収していると、いつの間にか「知るだけで満足」してしまい、実際に手を動かして動作検証する機会が大幅に減少していました。なので、この度のアドカレ枠を利用して、以前から気になっていた **[Dify](https://dify.ai/jp)** と **RAG** を動かしてみました。

以下、久しぶりの「やってみた系」記事です。
スクショ多めのため、スクロールしながら画像を見ていただくだけでも雰囲気は十分掴めます。

また、事前インプットとして以下の Youtube 動画を参考にさせていただきました。

* [OpenAIのGPTsより凄い！無料で使えるDifyを徹底解説してみた](https://www.youtube.com/watch?v=O_bmmDWIjTc)
* [仕事で使えそう？DifyでRAGを行う時の設定について解説してみた](https://www.youtube.com/watch?v=IVTtR8MmgDs)

# Dify × RAG

[Dify](https://dify.ai/jp) はプログラミングの知識がなくても誰でも簡単に AI アプリケーションを開発できるオープンソースのプラットフォームです。大規模言語モデル（LLM）を活用し、ノーコードで直感的に AI アプリを構築することができます。

![スクリーンショット 2024-12-24 23.56.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/b67840d9-7cda-0b36-1b43-771b7e941b8c.png)

2024年12月中旬時点では、以下4つのプランが用意されております。

| Plan | Price |
| --- | --- |
| SANDBOX | Free |
| PROFESSIONAL | $59/month |
| TEAM | $159/month |
| ENTERPRISE | (Talk to Sales) |

無料の SANDBOX でも **200 times GPT free trial** が可能なため、今回は SANDBOX にて動作検証を行いました。

![スクリーンショット 2024-12-24 23.56.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/713d1dbf-3591-ad11-d0aa-4a73bbe20744.png)

`Start for free` を選択すると、GitHub アカウン・Google アカウント・メールアドレス のいずれかでのログインが求められます。

![スクリーンショット 2024-12-24 23.56.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/1c635b1a-cb8c-606b-0729-969a776120e7.png)

ログイン直後は、以下の画面が表示されます。

![スクリーンショット 2024-12-24 23.57.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/83a8b7ad-cc2f-c95b-a427-9c26e473fdd8.png)

右上の `Dify（デフォルトのアカウント名）` を選択すると、各種設定が確認できます。ワークスペース > モデルプロバイダーでは **OpenAI クォータ 200クレジット** と記載されています。このクレジットは、Dify 内で作成するアプリから LLM モデルをコールするごとに消費されます。使ってみた体感では、アプリからコール > モデルプロバイダーへの反映まで、若干のラグがありました。

![スクリーンショット 2024-12-24 23.58.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/ec5d0d72-eea4-e3c3-c05c-730d25f9f39f.png)

以下のように、アプリから LLM モデルを呼び出すごとに「クレジット」が減少していきます。

![スクリーンショット 2024-12-25 0.50.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/9e97f7b6-e997-e33f-13ec-a5da96446fb9.png)

ワークスペース > 請求の画面では、サブスクの購読状況や各種リミット値が確認できます。サンドボックス（SANDBOX）プランは個人利用（チームメンバー: 1）が上限です。

![スクリーンショット 2024-12-25 0.01.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/7c43ea46-578a-c0a4-7917-9b558847a7d8.png)

まずは、まっさらな状況からアプリを作成してみます。

トップ画面の「チャットボット」> 「最初から作成」を選択します。

![スクリーンショット 2024-12-25 0.02.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/f33c3850-e6a5-fde7-ae7c-533478c71448.png)

以下のような「最初から作成」が表示されますので

* アプリの種類を選択
    * 「チャットボット」を選択
* アプリのアイコンと名前
* 説明

を入力して「作成する」を選択します。

![スクリーンショット 2024-12-25 0.03.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/8393dfbe-362c-fbaf-d6d7-bd14e5c0ee5d.png)

アプリを作成すると「オーケストレーション」の設定画面が表示されます。
この画面でプロンプトや RAG の設定、Bot の動作チェックを行います。

![スクリーンショット 2024-12-25 0.04.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/39f3918b-d2c9-e4c7-bb13-374090126eaa.png)

「手順」>「自動」のアイコンを選択すると、「プロンプト生成器」が設定できます。今回はシステムプロンプトの無い状態で RAG を動かしたいので、ここは未設定のままで作業を進めます。

画面右下にある「ボットと話す」に以下のテキストを入力して、デフォルトでのボットの反応を確認してみます。

> Linuxでまず初めに習得すべき基礎的なコマンドをリストアップしてください。

![スクリーンショット 2024-12-25 0.09.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/6fcef952-b613-ff27-cdab-8a1d74114fa7.png)

ボットからの回答として、こちらの質問内容に対して適切な回答が返ってくることが確認できました。

![スクリーンショット 2024-12-25 0.12.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/fabe8d43-e45e-3fb6-9698-9a119307a888.png)

また、ボットとの会話履歴は「ログ&アナウンス」の画面からも確認できます。

![スクリーンショット 2024-12-25 0.13.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/36113c2f-e9d5-cb0e-f886-69776ca11927.png)

![スクリーンショット 2024-12-25 0.14.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/4461b4a8-cac0-ca30-a5aa-5423e2117305.png)

続いて、Dify へアプリに学習させる「ナレッジ」を登録して RAG を利用してみます。

「オーケストレーション」>「ナレッジ」>「追加」を選択すると **参照する知識を選択** が表示されますので、「作成に進む」を選択します。

![スクリーンショット 2024-12-25 0.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/5b0898d2-cb09-e8e8-047d-f21e9b37f562.png)

今回の動作検証では **Web に公開された情報** をボットに学習して欲しいので、ウェブクローラーとして [Jina Reader](https://jina.ai/reader/) を利用します。

**Jina** のサイドへ移動後、「**< > API**」選択すると、リーダーAPI 配下の表に以下の情報が表示されます。

* 鍵と請求
* 使用法
* もっと

「鍵と請求」から **トークン値** と **トークン残量** をそれぞれ確認できます。

![スクリーンショット 2024-12-25 0.19.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/e266bf38-9bde-fb6e-9752-1d1617c69089.png)

トークン値を取得して、Dify の「データソース」>「ウェブサイト Jina Reader」>「Jina Readerの設定」>「API Key」に貼り付けて保存します。

![スクリーンショット 2024-12-25 0.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/9372e61b-b9e0-08ed-aae4-32d565cdb119.png)

API Key の登録後に

* スクレイピングするURL（今回は `https://help.vuls.biz/` を指定）
* スクレイピングするページ数（今回は `10` を指定）

を指定すると、Jina Reader 経由によるページの取得が始まります。

![スクリーンショット 2024-12-25 0.24.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/6b383f71-7d75-e9da-96a0-74416fc46f8a.png)

指定ページ数分の取得が完了すると、「テキストの前処理とクリーニング」が表示されます。

この設定画面では、Web ページから取得したテキスト情報を「ナレッジ化」する際のパラメータ制御を行います。どのようにテキスト情報を分割して、LLM が有益な回答を返せるようにするか、が AI/機械学習エンジニアの力の見せ所だと思います。今回は、検索設定を「ベクトル検索」>「ハイブリッド検索」に変更する点以外はデフォルトのままで、ナレッジの作成と保存を行います。

![screencapture-cloud-dify-ai-datasets-create-2024-12-25-00_27_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/d284d58c-a873-3e75-9d9f-f9c8281e235f.png)

各ページごとのナレッジ化の進捗状況を画面から確認できます。

![スクリーンショット 2024-12-25 0.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/426d6ea8-f00e-7e07-232a-6a9ec28ae304.png)

Jina で取得した各ページのナレッジ化が完了すると、トップページの「ナレッジ」に新しいパネルが追加されます。この「ナレッジ」が、アプリに渡す「コンテキスト」として使えるものになります。

![スクリーンショット 2024-12-25 0.29.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/ba1e39f7-b3ac-689c-359a-14ab5b1eebb6.png)

パネルを選択すると

* ファイル名（Jina でスクレイピングしたページのURL）
* 単語数
* 検索回数（アプリからの参照回数）

の一覧が表示され、個別のファイル名を選択すると「どのように分割されたのか？」も確認できます。

![スクリーンショット 2024-12-25 0.29.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/d17082a6-eb07-3dd0-6da0-97d6e769aa06.png)

アプリに学習させる「ナレッジ」が用意できましたので、早速取り込んでみます。

Dify の「オーケストレーション」画面へと移動して「コンテキスト」を選択します。

![スクリーンショット 2024-12-25 0.04.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/39f3918b-d2c9-e4c7-bb13-374090126eaa.png)

「参照する知識を選択」に、先ほど取り込んだ「ナレッジ」が表示されます。

![スクリーンショット 2024-12-25 0.30.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/f097b758-0e42-27c3-0ce2-7c1aed4e3814.png)

取り込みたい「ナレッジ」をクリックして「追加」を選択します。

![スクリーンショット 2024-12-25 0.30.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/df5ee0af-544d-a632-c124-7b2c7581e037.png)

以上で、チャット会話可能な LLM アプリに RAG（Dify の「ナレッジ」）を取り込めました。

それでは、取り込んだ RAG に関連する質問を投げてみます。

Jina 経由で取り込んだページ（`https://help.vuls.biz/manual/csirt_option/ssvc/config/`）の内容を参照しながら回答できるかを確認するために、「デバッグとプレビュー」で以下の質問を投げてみました。

> FutureVuls での SSVCPriority の設定方法

![スクリーンショット 2024-12-25 0.36.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/c7f7e5d5-890c-5ff8-6834-0978e4baee4a.png)

Bot が生成した情報は、オリジナルの Web ページ内容を正しく踏襲しており、かつ、**引用** に「どの内容を参照したのか？」が付与されていることが確認できます。回答に付随している **引用** の表示有無は、「オーケストレーション」右下の「有効な機能」>「引用と帰属」で変更可能です。

「オーケストレーション」右上から「公開する」>「更新」を選択すると、アプリのコンテキストに登録した「ナレッジ」が保存されます。続いて、「アプリを実行」をクリックすると、URL から今回作成した Bot に質問を投げられるようになります。

![スクリーンショット 2024-12-25 0.38.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/7132619e-12db-cf68-f4c4-e7af86d92bc3.png)

RAG で取り込んだページ内容を踏まえて、以下の質問を投げてみました。

> FutureVulsの画面ではどのような内容を確認できますか？

![スクリーンショット 2024-12-25 0.42.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/b680d7ef-6939-c2f7-6db6-a260c4194b77.png)

bot への質問状況は、すべて「ログ&アナウンス」の画面からも確認可能です。RAG を乗せた LLM Bot を作成後、URL を共有する方法で公開することも十分可能です。（課金請求にはご注意ください）

![target_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/0b2b0589-006f-2114-1731-bcfb45c6379f.png)

これまでの動作検証により、GUI 操作のみで「RAG を取り込んだ LLM Bot アプリ」が作成できることを確認できました。

## RAG 有無の差分検証

最後に、特定の「ナレッジ」を アプリに与えた場合と与えていない場合で、Bot の回答がどのように変わるのかを実際に試して、RAG の凄さを実感してみます。

動作検証用に **最近公開された、FutureVulsブログの内容** を「ナレッジ」として Dify に取り込みました。

* [内部と外部をつなぐ脆弱性管理｜FutureVulsでASM・Nmap・Nessusなどの診断結果を活用する方法](https://vuls.biz/blog/articles/20241119a/)

![スクリーンショット 2024-12-25 0.46.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/c5b3ba63-7ec8-b240-5e40-129fdf6ba7ad.png)

 **追加 RAG ナシ** と **追加 RAG アリ** のそれぞれに、ブログの内容を踏まえた質問を投げてみます。

> FutureVulsの「外部スキャン」について教えて

![スクリーンショット 2024-12-25 0.46.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/9e4779b9-8d4d-c4b9-38e0-73027580f49d.png)

![スクリーンショット 2024-12-25 0.47.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261058/d5587058-146f-696c-9839-b52bad803287.png)

**追加 RAG ナシ**

> 申し訳ありませんが、その情報についてはわかりません。

**追加 RAG アリ**

> FutureVulsの「外部スキャン」機能についてご説明します。

> 外部スキャン機能の概要
> 「外部スキャン」機能を使用すると、ASM（Attack Surface Management）、Qualys、Nessus、Nmapなどの外部スキャンツールやWeb脆弱性診断ツールで取得したスキャン結果をFutureVulsにインポートできます。これにより、インターネットからの外部スキャン結果と内部の脆弱性情報を紐付けて一元管理できるようになります。

> 主な特徴とメリット
> 一元管理: 外部からのスキャン結果と内部の脆弱性情報をまとめて管理でき、全体のセキュリティ状況を把握しやすくなります。
> 自動リスク評価: FutureVulsのSSVC（Stakeholder-Specific Vulnerability Categorization）機能により、インポートした脆弱性データを自動でリスク評価し、優先順位を設定します。
> チケット機能との連携: インポートしたスキャン結果をチケットとして管理し、担当者の割り当てや対応状況の追跡が可能です。

> 外部スキャン結果のインポート手順
> ...

追加 RAG アリのアプリでは、「ナレッジ」として取り込んだブログの内容が、質問への回答に反映されていることが確認できました。僅かな操作で、LLM に「学習させる」ことができました。

# おわりに

本ブログでは

① Dify で LLM Bot アプリを構築する
② LLM Bot アプリに RAG を学習させる

の2つを扱いました。

日頃のニュースで「RAG により LLM の学習限界を突破する」ことは十分理解しているつもりでした。しかしながら、簡易版だとしても実際に自分で動かしてみると、サブスクの AI ツールで当たり前に享受しているメリットとは別の感触としての実体験を通したリアルの驚きを感じられました。

また、Jina Reader により Web ページをスクレイピング取得した際に、テキストデータをどのように分割すれば、回答の精度を上げられるのかという実務的な検討ポイントが存在することも体感できました。

エンジニアである以上、こういったリアル感を伴った一次情報を AI 時代でも大事にしていきたいと思うきっかけになりました。

以上、ここまで長文にお付き合いいただき、ありがとうございました。