Difyで何ができるの?(湘.なんか #1 LT補足)
はじめに
2024/8/24(土)に湘.なんか #1というイベントに参加してDifyについてのLTをしました。
時間が足りなくてちゃんと説明できなかったところをこの記事で補足します。
サンプルアプリ「CfPサポートくん」
作ったサンプルアプリ「CfPサポートくん」は、テックカンファレンスにプロポーザルを出す際の、タイトルや概要文を考えてくれる生成AIです。
イベント情報と、話したいトピック、KEY TAKEAWAYSなどを入力してチャットを開始します。
(下図は実際にLTで動かした時のキャプチャで、きのこカンファレンスに応募するという想定で入力したサンプル)。
とりあえず挨拶を投げかけると返事をしてくれます。
フランクな応答をするのは、システムプロンプト設定によるものです。プロポーザルに関する質問以外は、適当にユーザーの相手をするように設定しているので、陽気なおっさんとのチャットを楽しむことも可能です(笑)。
プロポーザル案の作成を依頼すると、ちゃんと真面目に考えてくれます。MAGIシステムというプロンプトエンジニアリングの手法を取り入れてるのですが、中間出力として専門家の意見を表示するようにしてます。
最終的な回答(タイトル案と、プロポーザルの概要文)は以下のとおりです。そこそこ悪くない文章を考えてくれました。
chatflowの説明
作成したフローの全体像は下図の通りです。Difyで複雑かつ定型的な処理を生成AIにやらせたい場合、workflowという種類のアプリケーションを作るのですが、workflowは処理を単発で実行して終了となります。対話形式で処理をしたい場合は、チャットボット(chatflow)という種類のアプリケーションを作成します。
質問分類器
ユーザーと対話ができるチャットボットとして振る舞うために、応答のパターンを作ります。ユーザーの質問の意図(Intent)に応じて、「この場合はこうする」というルールを事前に定義するのです。
質問の意図の特定には、「質問分類器」ブロックを使用します。質問分類器自体、LLMを使ったタスクとして処理されます。
IF/ELSEによる分岐とツールの利用
サンプルでは、ユーザーがイベントのWebサイトのURLを入力した場合、そのWebサイトの情報を読みにいくようにしています。このような条件分岐には「IF/ELSE」ブロックを使います。
また、Difyでは組み込みで提供される様々なツールを利用することができます(ツール自体を自作することも可能)。サンプルでは、WEB SCRAPERというツールを用いて、Webサイトの情報を取得・要約させています。
MAGIシステム
MAGIシステムとは、複数の専門家に議論させることで多角的な視点を盛り込んだ文章を生成させるプロンプトエンジニアリングのテクニックです。ChatGPTやClaudeなどでこのテクニックを使う場合、ユーザー自身で三人の専門家の専門性を指定することが多いですが、このサンプルでは、その選定もLLMにやらせるようにしてみました。
一人目:イベントプランナーで固定
二人目:セッション内容に沿った、特定の技術領域の専門家
三人目:多角的な観点でグループ討論を発展させるのに適した、別の専門家
専門家を選定した後、実際にグループ討論を行わせて、収束した意見をもとに、最終的な回答を出力させています。
LLMアプリケーション構築のポイント
私自身まだまだ勉強中の身ではありますが、現在感じているLLMアプリ構築のポイントをまとめます。
分割して統治せよ
ChatGPTを使う場合、複雑なタスクを生成AIにやらせて期待に沿う回答を得るためには、処理を複数のサブタスクに分割して段階的に取り組ませる方法が効果的です。
LLMアプリを構築すればより複雑なタスクに取り組むことができますが、やはり処理の分割が肝となります。ユーザー目的を達成するために振る舞いを分割し、処理フロー(アプリケーションロジック)を組み立てるというのは、ソフトウェア設計に通ずるものがあるのではないでしょうか。
LLMはアシスタント、主役は人間
LLMが最も得意なのは、文章の要約や補完です。そういったタスクはかなりの精度でこなします。一方で、アイデア出しについてはランダム性が高まります。LLMは「回答を出力することで文章を完成させないと気が済まないマン」なので、何かしらそれっぽい回答は出してくれますが、それがお望みのものになるかどうかはわかりません。
壁打ち相手として使うならそれで構わないのですが、ブログ記事のようなものを生成するのであれば、骨格となる主張や要点はユーザー自身が考えて与えなければなりません。それをもとに肉付けをし、文章に飾り付けをする作業をLLMにやらせるという役割分担になります。
今回のサンプルでは、プロンプト中に以下のような指示を入れています。ユーザーが考えたKEY TAKEAWAYSが最重要であり、それに帰結するような概要文となるように考えさせています。
プロンプトの構造化(XMLの復権?)
生成AIに対する指示を明確にするために、プロンプトを構造化することは重要です。一般的にはマークダウン形式などがよく使われます。
おすすめしたいのはXML形式です。タグによる階層構造はマークダウンよりも厳密で、タグ名によって情報のチャンクにラベル付けができます。
また、 userInput.topic のような書き方で情報を指し示すと、LLMはちゃんと理解してくれます。
(XMLなんて二度と書くことはないと思ってたけど)
<instruction>
ユーザーがテックカンファレンスに登壇者としてプロポーザルを提出するにあたって、その草案をまとめてください。
<process>
1. userInput.topic の内容をもとに、eventInfo に記載されたイベント概要に相応しい講演内容を考える。 userInput.query の内容も考慮すること。
2. 講演内容は、 userInput.keyTakeaways のまとめに帰結するようにする
3. 講演内容を整理し、講演概要として日本語で500文字以内にまとめる
4. userInput.tantativeTitle の講演タイトルをより良いものに修正する
</process>
<format>
以下のXML構造のみを出力する。
<draft>
<title>タイトルをここに書く</title>
<abstract>講演概要をここに書く</abstract>
</draft>
</format>
</instruction>
<ref>
{{#1723433957922.output#}}
</ref>
サンプルアプリの動かし方
Difyで作ったアプリケーションは、「DSLをエクスポート」機能により、Y AML形式のファイルとして定義情報を出力できます。今回のサンプルアプリを動かしながら確認してみたい方は、以下のYMLをダウンロードし、ご自分の環境にインポートしてください。
サンプルアプリでは、LLMのモデルは全てGemini 1.5を指定しています。APIキーの準備や設定については以下の記事を参考にしてください。