Difyのワークフロー機能を使い、お客様からの質問に対して自動で回答を生成するSlack Botを作成しました。回答生成の際には、過去にお客様から頂いた質問と回答させていただいたデータに加え、さらに必要となる専門的な固有の知識も与えるようにしています。
Dify(ディファイ)は、ノーコードやローコードでAIチャットボットやAIアプリを作れるツールです。一般的な生成AIは、あらかじめ学習した知識の範囲内でしか回答できませんが、DifyではRAG(Retrieval-Augmented Generation:検索拡張生成)という技術を用いることで、AIが社内資料や業務データなど外部の情報も参照して回答する仕組みを簡単に実現できます。
今回構築したBotは、社内Slack上でBotにメンションして質問を送信すると、その内容に応じてRAGによる検索・生成処理をDify側で行い、回答がSlackに自動で返信されるという流れです。
ただ具体的な中身をそのままお見せすることはできないため、本記事では例として「日報」の記述内容に対して、書籍『プログラマが知るべき97のこと』*1を参考に、メンターとしてコメントを返すBotを紹介します。
前提として、SlackからDifyへの通信はAWS Lambda使って実現しています。また、DifyはEC2でセルフホスティングしています。
Difyでナレッジベースをつくる
RAGで拡張・検索するナレッジベース(知識データ)の生成は、DifyのGUI上で操作が完了できます。 まず、ナレッジとして活用したいファイル(テキストやCSV、PDFなど)をアップロードします。

次にチャンク分割と埋め込み(embedding)です。 チャンク分割とはアップロードしたドキュメントをAIが扱いやすい単位に分割する処理で、埋め込み(embedding)は分割したテキストをAIが検索しやすいように数値データに変換する処理です。プレビュー機能で分割の単位を確認でき、各チャンクが外部知識としてAIの参照対象となります。
検索方式はハイブリッド検索を選んでおくと良いでしょう。

保存ボタンを押すと埋め込みが始まり、完了画面が表示されます。

今回の実務で作成したBotでは、過去の質問と回答がGoogleスプレッドシートにまとまっており、csv形式でダウンロードしたものをアップロードしています。行ごとに自動で適切な粒度のチャンクに分割されたので、追加調整は不要でした。本来はチャンク分割がしやすいように、元ドキュメントはチャンク分割後のイメージをしながら作成する必要があると思います。
ワークフローを作る
ワークフローは以下の流れで設計しました。ノードをつなげるだけで、基本的にはGUI上の操作で直感的に作成できます。
- 開始ノードでリクエストを受け付けて、入力内容を取得
- 知識検索ノードで作成したナレッジベースを選択してRAGを行う
- LLM(大規模言語モデル)のノードで回答生成する
- HTTP リクエストノードで生成した回答をSlackにPOSTで投稿する

Difyは外部からのリクエストを受け付けるエンドポイントも提供しています。 今回のBotは「Slack → AWS Lambda → Dify → Slack」という構成で連携を実現しています。
なお、本記事での紹介している例は非常にシンプルな例ですが、実務のワークフローでは下記のような形になっています。
- 質問分類器を挟んで、システム関連のトラブルシューティングは別のフローで回答を生成
- 過去回答・専門的知識といったナレッジベースは分けており、それぞれ知識検索ノードを並列に配置
- 知識検索の結果を参考情報としてSlackに投稿するため、pythonコードを書いて抽出
回答をもらう
わかりやすさのために同等の機能を持つチャットボットで回答を生成しました。こちらもDifyの基本的な機能だけで構築できます。

チャットの左側にある「PROMPT LOG」のcontext欄で実際にAIが参照した知識情報が表示されます。おおむね関連する知識を引っ張ってきた上で回答を生成できていると思います。ただ「入力したテキスト」に関連した知識をそのまま探しに行くので、質問の解釈やクエリ拡張などのLLMを挟んだ方がより良い回答ができると思います。 またこのままでは異常系・例外系の質問に対してはうまく回答ができないのですが、社内で使う分には許容範囲のレベルではあります。このあたりは要改善項目で今後の課題となっています。
困ったこと
投稿するSlackのメッセージが長くなり、「show less/ show more」を表示したかったのでBlock Kitを使うことにしました。その際、日本語が「\u3042」などに文字化けしてしまい、Blockごとの3000文字の文字制限で引っかかることになりました。
そのため、payloadのjsonを自分で作成し、ensure_ascii=False オプションを指定して日本語を含むJSON 文字列を出力することで回避しました。
return { "result": json.dumps(payload, ensure_ascii=False) }
まとめと次やること
SlackとDifyを使ってRAGを使ったBotをローコードで作ることができました。操作もGUI上で完結しとても使いやすさを感じました。 次は精度向上・フロー改善をやっていきたいと思います。
- エージェントを使用して回答を洗練させるフローを作る
- Advanced RAGに基づいて回答精度アップする
本サイトの更新情報は、Twitterの株式会社プレセナ・ストラテジック・パートナーズエンジニア公式で発信しています。ご確認ください。
*1:本記事ではナレッジベースとして『プログラマが知るべき97のこと』(O'Reilly Japan, 2010)を使用しています。
- 著作権者:(C) O'Reilly Japan, 2010
- ライセンス:Creative Commons BY 3.0 US
- コンテンツの出典リポジトリ:yoshi389111/kinokobooks
※ 上記リポジトリは書籍をもとにMarkdown形式で再構成・公開されたものです。