検索
連載

Difyによる高度なチャットフロー設計――質問分類とイテレーション、条件分岐の実装生成AI×ノーコードでつくる!Difyワークフロー構築入門(3)

ノーコード/ローコードでAIアプリを構築できるオープンソースプラットフォーム「Dify」を活用して、AIワークフローを構築する本連載。第3回は、より高度なチャットフロー設計に挑戦します。質問分類器やイテレーションなどのブロックを活用し、複数のWebページの要約結果をまとめてユーザー指定の形式(PDF、Wordなど)で返す自動化フローを作成します。

Share
Tweet
LINE
Hatena
「生成AI×ノーコードでつくる!Difyワークフロー構築入門」のインデックス

連載:生成AI×ノーコードでつくる!Difyワークフロー構築入門

本連載のサンプルコード(DSLのYAMLファイル)はGitHubで公開しています。必要な場合はこちらからダウンロードしてみてください。


はじめに

 第1回ではWebページやPDFのスクレイピングと要約、第2回ではワークフローをツール化しチャットフローで活用する方法を紹介しました。第3回となる今回は、より高度なチャットフロー設計に挑戦します。質問分類器やイテレーションなどのブロックを活用し、複数のWebページの要約結果をまとめてユーザー指定の形式(PDF、Wordなど)で返す自動化フローを作成します。

今回作成するチャットフローの概要

 前回までに作成したチャットフロー「Webページ要約ボット」は、単一のURLを入力として受け取り、その内容を要約してPDF形式で返すものでした。今回は、これに以下の機能を追加した新しいチャットフローを作成します。

  • ユーザーからの自然言語によるURL以外の内容も含む指示(例:「以下のURLを要約してWord形式で返して」)に対応
  • 複数URLの並列処理(要約)
  • 出力形式の自動選択(PDF形式またはWord形式)
  • 最終的に要約結果をまとめて指定形式で返す

使用するブロックとツールの紹介

 今回新しく使用する主なブロックとツールは以下の通りです(図1)。

  • IF/ELSE(条件分岐):入力内容に応じて処理を分岐
  • イテレーション(繰り返し処理):複数データ(配列)の要素に対して同じ処理を繰り返し実行(並列処理も可能)
  • 質問分類器:ユーザーの質問内容を分類し、適切な処理に分岐
  • Markdown → DOCX(Markdownエクスポーター):MarkdownをWord(*.docx)形式で出力
図1 今回使用する主なブロックとツール(点線はこれまでに使用しているもの)
図1 今回使用する主なブロックとツール(点線はこれまでに使用しているもの)

 IF/ELSEやイテレーション、質問分類器は、それぞれプログラミング言語におけるif-else、foreach、switchといった構文に相当するもので、Difyのチャットフローやワークフローで高度な処理を実現するための重要なブロックです。

全体の流れ

 最終的なチャットフローのイメージは図2のようになります。

図2 第3回で作成するチャットフローの全体像
図2 第3回で作成するチャットフローの全体像

 具体的な処理の流れは以下の通りです。

  1. ユーザー入力ブロックで、ユーザーからの入力を受け取る
  2. LLMブロックで、入力内容からURLリストを抽出
  3. IF/ELSEブロックで、URLリストが空なら、URLが抽出できなかった旨をユーザーに応答して処理を終了
  4. (URLリストが存在する場合)イテレーションブロックで、各URLに対して以下の処理を実行
    • Webページ要約ツールを呼び出し(Webページの内容をスクレイピングして内容を要約)
  5. テンプレートブロックで、要約結果のMarkdownを結合
  6. 質問分類器で、ユーザーの入力内容から出力形式(PDFまたはWord)を判別
  7. Markdown → DOCX/PDFツールで、要約結果を指定形式に変換
  8. 回答ブロックで、変換したファイルをユーザーに返す

チャットフローの作成

 第2回で作成した「Webページ要約ボット」のチャットフローを複製して編集してもよいのですが、構成が大きく変わるため、新たに作成しましょう。

新規チャットフローの作成

 Difyの「スタジオ」画面に戻り「最初から作成」ボタンをクリックし、「チャットフロー」を選択します。「アプリのアイコンと名前」欄にチャットフローの名前として「Webページ要約ボット v2」(名前はどのようなものでも構いません)と入力し、「作成する」ボタンをクリックします(図3)。

図3 新規チャットフローの作成
図3 新規チャットフローの作成

 新しいチャットフローには、既定で「ユーザー入力」「LLM」「回答」ノードが配置されています。LLM(大規模言語モデル)と回答ノードの接続を削除し、図2のようにノードを追加・接続してください。ノードを全て配置してから、各ノードの設定を行います。

 また、前回と同様に「機能」→「会話の開始」から「オープナー」(チャットの最初に表示される初期メッセージ)を指定しておくとよいでしょう。

ノードの設定

 各ノードを順に設定します。今回もユーザー入力ノードの設定は特に必要ありません。

・URLリスト抽出用LLMノードの設定

 最初のLLMノードは、ユーザー入力からURLリストを抽出するためのものです。ノードをクリックして設定画面を開き、図4のように設定します。

図4 URLリスト抽出用LLMノードの設定
図4 URLリスト抽出用LLMノードの設定
  • モデル:gpt-4o-mini(Temperature:0、Top P:0、Max Tokens:1024)
  • プロンプト:
    • SYSTEM:入力に含まれる全てのURLを正確に抽出して。抽出できなければ空配列でOK
    • USER:ユーザー入力ノードの変数query

 また、図5の流れで構造化出力を設定します。

図5 URLリスト抽出用LLMノードの構造化出力設定
図5 URLリスト抽出用LLMノードの構造化出力設定
  • 出力変数:
    • 構造化出力:ON
    • 構造化データスキーマ(structured_output)
      • フィールド名:url_list
      • タイプ:array[string]
      • 必須項目:ON
      • 説明:URLリスト

 構造化出力を使えば、LLMの出力を任意のJSON形式として取り出せるため、後続の処理で扱いやすくなります。ここでは、ユーザー入力から抽出したURLリストを配列(文字列)形式で取得します。

 なお、この「構造」の定義もJSON形式で定義されます。定義内容は「構造化データスキーマ」ダイアログの「JSON スキーマ」タブをクリックして確認できます。

・IF/ELSEノードの設定

 次にIF/ELSEノードを設定します(図6)。URLリストが空かどうかで処理を分岐するためのノードです。

図6 IF/ELSEノードの設定
図6 IF/ELSEノードの設定
  • IF:「URL 抽出 / structured_output.url_list」が「空でない」
  • ELSE:デフォルトのまま

 このように、LLMノードの構造化出力を定義して結果を出力させることで、後続のノードでは構造をたどって選択するだけでよくなり、タイプミスなどの誤設定を防げます。

・URLリストが空の場合の回答ノードの設定

 次にIF/ELSEノードのELSE側の回答ノードを先に設定しましょう。設定画面を開き、「応答」に固定メッセージを設定します。ここでは「URLが認識できませんでした。要約するWebページのURLを指定してください。」としました(図7)。

図7 URLリストが空の場合の回答ノードの設定
図7 URLリストが空の場合の回答ノードの設定

・イテレーションノードの設定

 次にIF/ELSEノードのIF側のイテレーションノードを設定します。イテレーションノードは内部に処理ノードを持つため、見た目が少し異なります(図8)。

図8 イテレーションノードの外観
図8 イテレーションノードの外観

 中に表示されている家アイコンのノードがイテレーション(繰り返し処理)の起点です。ここに続く処理が配列の各要素に対して繰り返し実行されます。

 「+ブロックを追加」ボタンをクリックして、前回までに作成した「Webページ要約ツール」を追加します。入力変数urlには、イテレーションノードのitem変数(プログラミング言語でいうループ変数)を指定します(図9)。

図9 イテレーションノード内にWebページ要約ツールを追加
図9 イテレーションノード内にWebページ要約ツールを追加

 次に外側のイテレーションノードを設定します(図10)。

図10 イテレーションノードの設定
図10 イテレーションノードの設定
  • 入力:URL 抽出 / structured_output.url_list
  • 出力変数:Webページ要約 / result
  • パラレルモード:ON

 これで、URLリストの各URLに対して「Webページ要約ツール」が実行され、結果が配列として取得できるようになります。

 パラレルモードは並列処理を有効にするオプションです。時間的に並行して処理を進めることで、全体の処理時間を短縮できます。ただし、あまり多く一度に処理しようとすると、LLM側の制限に引っ掛かる可能性があるため注意してください。

・要約結果を結合するテンプレートノードの設定

 要約結果結合のテンプレートノードを図11のように設定し、イテレーションノードの出力であるURLごとの要約結果(Markdown)を結合して1つのMarkdownにまとめます。

図11 テンプレートノードの設定
図11 テンプレートノードの設定
  • 入力変数:イテレーション / output
  • コード:リスト1参照
{% for result in results %}
{{ result }}
- - -
{% endfor %}
リスト1 要約結果を結合するテンプレートノードのコード

 このコードは、Jinja2というテンプレートエンジンの構文で、配列をループ処理(for)して、各要約結果を順次出力します。ここでは、WordやPDFに変換したときに結果の区切りが視覚的に分かりやすくなるように、Markdownの区切り線(- - -)を追加しています。

・出力形式を自動的に選択する質問分類器の設定

 ユーザーの入力内容から、「出力形式をWord(*.docx)にするかPDFにするか」を自動的に選択するための質問分類器を設定します(図12)。

図12 質問分類器の設定
図12 質問分類器の設定
  • モデル:gpt-4o-mini(Temperature:0、Top P:0)
  • 入力変数:ユーザー入力 / sys.query
  • クラス:
    • クラス1:Word
    • クラス2:PDF
  • 高度な設定:出力形式としてWord形式が指定されていると考えられる場合はWord、それ以外はPDF

 ここでは高度な設定に、どちらの形式か判断がつかない場合はPDFを選択するように指示を追加しています。質問分類器はユーザー入力とクラスの内容を基にある程度判断してくれますが、高度な設定は、より確実に正しいクラスを選択させるための補助として利用できます。

【コラム】質問分類器の仕組みと特徴

 今回はファイル形式による処理分岐のために質問分類器を使用しました。この程度であれば、IF/ELSEブロックでユーザー入力に「Word」や「PDF」というキーワードが含まれているかどうかを条件にしても実装できそうですが、質問分類器を使うことで、例えば「ワードで出力して」のように日本語が混ざっていたり、「.docx形式でお願い」のようにファイル拡張子が指定されていたりしても、正しく判断しやすくなります。

 質問分類器の設定ではLLMモデルを選択しますが、実際、質問分類器の中身はほとんど「LLMノード」+「IF/ELSEノード」ような構成になっており、内部で専用にカスタムされた分類指示(プロンプト)によってLLMが選んだ選択肢を元に、出力を分岐するという仕組みになっています。

 質問分類器は、ユーザーの入力内容のように曖昧で多様な表現が考えられるものを分類して処理を分岐したい場合に適しています。ただし、LLMを使う分、単純な条件分岐より時間も費用もかかりますので、必要性を考慮して使いましょう。また、あくまでLLMの出力精度に依存するため、ユーザーの入力内容によっては誤分類する可能性もあることには注意してください。

・Markdown → DOCX/PDFツールノードの設定

 要約結果をユーザーの指定した形式(WordまたはPDF)に変換するためのツールノードを設定します(図13)。

図13 Markdown → DOCX/PDFツールノードの設定
図13 Markdown → DOCX/PDFツールノードの設定
  • 入力変数:要約結果結合 / output
  • Output Filename:summary

 図13はMarkdown → DOCXツールの設定ですが、Markdown → PDFツールも同様の設定にします。

 Output Filenameは、ユーザーに返すときのファイル名です。拡張子は自動的に付与されるため、ここでは拡張子なしのファイル名を指定します。

・回答ノードの設定

 最後に回答ノードを設定します(図14)。

図14 回答ノードの設定
図14 回答ノードの設定
  • 応答:Markdown → DOCX ノード / files, Markdown → PDF ノード / files

 応答には、Markdown → DOCXノードとMarkdown → PDFノードの両方の出力変数filesを指定します。これで、ユーザーの入力内容に応じて、どちらか一方のツールノードが実行され、その出力ファイルがユーザーに返されるようになります。

動作確認

 早速、動作を確認してみましょう。プレビューボタンをクリックしてチャットフローのプレビュー画面を開きます。入力欄に要約したいWebページのURLを含む指示を入力して送信します。しばらく待つと、チャットフローがURLを抽出し、要約処理を実行し、ユーザーの指定した形式で要約結果が返されます(図15)。

図15 チャットフローの動作確認
図15 チャットフローの動作確認

 入力では「.docx形式」としか指定していなかったのですが、正しくWordファイルで要約結果が返されています。特に指定しなければPDFファイルが返されます。この例では図16のようなWordファイルが生成されました。

図16 生成されたWordファイルの内容
図16 生成されたWordファイルの内容

【コラム】Wordファイルのカスタマイズ

 Markdown → DOCXツールでは「DOCX Template File」オプションにテンプレートファイル(.docx)を指定することで、生成されるWordファイルのレイアウトやスタイルをカスタマイズできます。

 テンプレートファイルは、あらかじめWordなどで作成します。主に「ホーム」タブのスタイル機能を利用して、見出しや本文などのスタイルを調整します。また、「デザイン」タブや「レイアウト」タブで全体のフォント設定や余白などのページ設定も行っておくとよいでしょう。

 クラウド版Difyではファイルを保管できないので、外部のファイルストレージサービス(Google DriveやDropboxなど)にテンプレートファイルをアップロードして読み込むか、ユーザー入力のファイルアップロード機能を利用してユーザーに指定させる方法が考えられます。

 ここでは後者の方法を簡単に説明します。「ユーザー入力」ノードでは、デフォルトでqueryとfilesという出力変数が用意されており、ユーザーがチャット画面で送信した文字列はqueryに、ユーザーがアップロードしたファイルはfilesに格納されます。このfilesをMarkdown → DOCXツールの「DOCX Template File」オプションに指定すれば、ユーザーがアップロードしたファイルをテンプレートファイルとして利用できます(図17)。

図17 Markdown → DOCXツールのテンプレートファイル指定
図17 Markdown → DOCXツールのテンプレートファイル指定

 なお、ファイルアップロードを有効にするには、チャットフローの「機能」タブから「ファイルアップロード」をONにし、ファイルタイプとして「ドキュメント」を選択しておく必要があります(図18)。

図18 ファイルアップロード機能の設定
図18 ファイルアップロード機能の設定

 この設定を行った後、プレビュー画面でカスタムしたテンプレートファイルを指定してチャットフローを実行した例です(図19)。元とは異なるスタイルになっていることが分かります。

図19 カスタムテンプレートファイルを指定してチャットフローを実行
図19 カスタムテンプレートファイルを指定してチャットフローを実行

まとめ

 今回は、質問分類器やイテレーション、条件分岐などのブロックを活用して、より高度なチャットフローを作成しました。

 今回のフローでは、ユーザー入力を「URL」と「出力形式」の検出に絞って使用しており、通常のチャットbotのように柔軟な会話をするようにしていません。極端に言えばユーザー入力で「要約しないでください」と書いたとしても、要約は実行されます。

 もちろん質問分類器を追加し、ユーザーの入力内容に応じて「URL抽出用の処理をするか」「会話用の処理をするか」を分岐させ、会話用の処理を追加することも可能です。役割特化型にするか会話もできるような柔軟なチャットbotにするかは、ユースケースやユーザーのニーズに応じた設計が必要です。

 次回は、ここまで使ってきたMarkdownエクスポーターのようなプラグインを自作して、Dify内で利用する方法を紹介します。

筆者紹介

WINGSプロジェクト 山田研二(ヤマダ ケンジ)

株式会社MSEN CTO(https://msen.jp/)。高校卒業後、大阪大学の研究所で働きながらプログラミングやWebデザインをはじめ、以後20年以上、Webサイト制作や業務システムの構築を手掛けている。フリーソフトも幾つか公開している。好きな言語はC#とTypeScript、趣味は旅行。

GitHubアカウント(https://github.com/kenzauros

WINGSプロジェクト

有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティー(代表山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手掛ける。2021年10月時点での登録メンバーは55人で、現在も執筆メンバーを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。

サーバーサイド技術の学び舎 - WINGS(https://wings.msn.to/
RSS(https://wings.msn.to/contents/rss.php
X: @WingsPro_info(https://x.com/WingsPro_info
Facebook(https://www.facebook.com/WINGSProject


Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る