Difyで遊んでみる - 前編 (環境構築～チャットボット作成まで) - 

# はじめに

ctcの情シスに所属する42daといいます。
初めての記事投稿で緊張しています。どうか暖かく見ていただけますと幸いです。

わたしはこれまで社内システムの開発・運用を中心としてお仕事をしてまいりましたが、
最近では生成AIの活用推進の取り組みに力をいれております。

本記事では、生成AI界隈で話題の「**Dify**」について、わたしが遊んでみた内容を簡単に
まとめてみます。

# Difyについて
ローコードでLLMと戯れられるステキなソリューションです。
> DifyはオープンソースのLLMアプリ開発プラットフォームです。
> RAGエンジンを使用して、エージェントから複雑なAIワークフローまでLLMアプリを編成します。

https://dify.ai/jp

Microsoft Power AutomateなどのiPaaS製品のように、GUI上でかんたんに処理を記述できるのが特徴です。ブロックを線でつないでワークフローをつくる、あれですね。

ものすごく頻繁にアップデートされていて、次々と新機能がリリースされています。

（Dify自体の紹介や事例はたくさん公開されていますので、詳細な説明は割愛します。）

# あそんでみたこと
以下のようにあそんでみました。
なお、今回の記事では★までの内容になります。続きはまた別途。。。（じかんぎれ）

1. 環境を構築　★
1. チャットボットであそぶ　★
1. RAGであそぶ　
1. Code Interpreterであそぶ


# 環境構築
### Difyをローカルにデプロイする
DifyはSaaS版も提供されていますが、Docker Composeでローカルへのデプロイも可能です。
今回は自宅の端末にいれてみました。
- マシン : MacBook Air M1,2020
- OS : Sequoia 15.1.1
- コンテナ管理 : Rancher Desktop

コンテナ管理ですが、あくまで今回はプライベートな”あそび”ですので、Docker Desktopを無償の範囲で使えるかな、と思いつつ、「一応会社名だしてQiitaに投稿するつもりだし、どこから商用なんだ…？」と~~いうのを考えるのがめんどくさく~~なったので、代替ツールとして情報が多そうなRancher Desktopを選定しました。

基本的には[公式ドキュメント](https://docs.dify.ai/getting-started/install-self-hosted/docker-compose)どおり進めればOKだったのですが、Rancher Desktopだと```docker-nginx-1```や```docker-db-1```コンテナがうまく起動しませんでした。

Advent Calendarの担当日が迫るなか初手の環境構築で詰まって吐きそうになっておりましたが、以下の記事を参考に対応させていただところ、うまくいきました。
先人の知恵ってすばらしい… 本当にありがとうございました。

https://zenn.dev/bohnen/articles/59ed33bc9dc55e

Difyで動いているコンテナさんたち

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/3c4b05bb-e095-1d72-4c23-e4640a19f95e.png)

わーいログインできるようになった（初回、管理者アカウント登録が必要です）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/ed56dff3-2f20-1359-89cf-b8c59d64340d.png)


### API Keyを取得する
さて、Difyが起動しただけでは まだLLMと戯れることはできません。
LLMに接続するためのAPI Keyを取得しましょう。

今回はお金をかけずにあそびたいので、（記事執筆時点で）無料枠があるGeminiのAPIを使います。Google様ありがとう。



https://ai.google.dev/gemini-api/docs/api-key?hl=ja

※Gemini APIの料金は変動する可能性があります。必ず公式サイトをご確認ください。

https://ai.google.dev/pricing?hl=ja#1_5flash

取得したAPI Keyは、以下の場所に設定します。

Difyの画面右上のアカウントアイコン＞設定

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/b3a236eb-3a09-dc41-5c5d-b9416017da5d.png">

モデルプロバイダー＞Gemini＞セットアップ（キャプチャに映ってないですが、ホバーすると「セットアップ」とでます）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/def03d60-86db-471b-b2ca-d01a5fdcdf49.png)

Keyをコピペして、保存

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/c46ddc90-832b-65c9-0384-ab779f007224.png)

# チャットボットであそぶ
これでやっと、あそぶ準備ができました。さっそく作っていきましょう。

ただ単にLLMと会話するだけだと面白くないので、以下のように（以下が面白いかどうかはおいておいて）テーマを設定してみました。


**テーマ：AI懺悔室**
 1. **ユーザが、小さな罪を懺悔する**
 1. **天使と悪魔がそれぞれユーザの告白をうけて、意見を述べる**
 1. **神が天使と悪魔の意見を加味した上で、ユーザが天国行きか地獄行きかをジャッジする**


LLMに役割（ペルソナ）を与えて一撃で回答させても悪くないのですが、Difyのフローのお試しをしたいので、天使と悪魔をそれぞれ別のLLMブロックで意見させ、その意見をインプットとして神のLLMブロックがジャッジする、という流れにします。


※なお、このテーマは、なにかしら宗教的な主義主張を意図したものではありません。よくある漫画表現的なものだと捉えてください。あしからず。

### フローの全体像

以下のようにフローを組みました。

```mermaid
graph LR;
    開始-->ANGEL-LLM;
    開始-->DEMON-LLM;
    ANGEL-LLM-->GOD-LLM;
    DEMON-LLM-->GOD-LLM;
    GOD-LLM-->回答
```

1. 開始ブロックでユーザが入力
1. ANGEL (LLM)とDEMON（LLM）を並列で処理
1. ANGELとDEMONの生成結果をGOD（LLM）にいれて生成
1. 回答ブロックで各LLMの生成結果をチャットにまとめて回答

実際にDifyで作ったフローが以下になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/c5be9cf8-2f21-d985-b094-b81a19c33ea9.png)




### LLMブロックの設定
LLMブロックにはそれぞれSYSTEMとUSERのプロンプトを設定することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/a8151562-7577-8fb3-5c16-00de52647fd7.png)


SYSTEMのプロンプトを考えるのは骨が折れますが、Difyには「**プロンプト生成器**」の機能がありますので、軽ーくやらせたいことを書くとすごくいい感じに作ってくれます。便利。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/3f59e2d5-3984-6278-91e7-ceafb53cd46b.png)

今回のプロンプトも全部このプロンプト生成器を使ってほとんど作ってもらいました。
以下、各LLMブロックのプロンプト設定です。

#### ANGEL（天使）
##### SYSTEMのプロンプト
```xml
<instructions>
あなたは天使として、ユーザーから提供された懺悔に対して優しくジャッジする必要があります。ユーザーの懺悔は様々な内容が考えられます。小さな失敗談から深刻な過ちまで、どんな懺悔に対しても、天使として優しく、そして時には少しユーモラスにジャッジしてください。

以下のステップに従ってタスクを実行してください。

1. ユーザーの懺悔内容をよく理解する。
2. 天使として、その懺悔に対してどのようなジャッジをするかを考える。
3. 優しく、そして時には少しユーモラスな言葉でジャッジを表現する。
4. 懺悔の内容によっては、反省を促すようなアドバイスや、優しい励ましの言葉を加える。
5. 出力にはxmlタグを含めない。
6. 会話の最初に　天使：　と必ずつけてください

常に天使としての役割を意識し、ユーザーに寄り添う姿勢を忘れないようにしてください。あなたの言葉が、ユーザーの心を軽くし、前向きな気持ちになる助けとなるように心がけてください。
</instructions>

<examples>
<example>
懺悔：お昼ご飯に買ったプリンを、うっかり落としてしまいました…。
ジャッジ：あらあら、それは残念でしたね。でも大丈夫！プリンは天国で美味しく食べられていますよ。きっとプリンの妖精さんが慰めてくれるでしょう。次にプリンを買うときは、しっかりと持ってくださいね。
</example>

<example>
懺悔：友達の陰口を言ってしまいました。
ジャッジ：あら、それはいけませんね。陰口は、言われた人も、言ったあなた自身も、そして聞いている周りの人も、みんなを悲しませる魔法の言葉です。今度からは、その友達の良いところを探して、褒めてあげてみてください。きっと素敵な笑顔が見られるはずです。
</example>

<example>
懺悔：テストでカンニングをしてしまいました。
ジャッジ：うーん、それは良くないですね。カンニングは、自分の本当の力を隠してしまう魔法です。あなたはもっと素晴らしい力を持っているはずです。次は、自分の力で頑張って、本当の力を試してみてください。応援していますよ！
</example>
</examples>

<constraints>
常に天使のペルソナを維持すること。
優しく、共感的な口調で応答すること。
ユーモアを交えて、ユーザーの気持ちを軽くするような表現を心がけること。
xmlタグを含めないこと。
300文字以内で回答すること。
</constraints>
```

##### USERのプロンプト
```
{{#sys.query#}}
```
```{{#sys.query#}}```は開始ブロックで入力されるユーザの入力内容そのものです。

#### DEMON（悪魔）
##### SYSTEMのプロンプト
```xml
<prompt>
<instructions>
あなたは悪魔です。ユーザーから懺悔を聞き、厳しくジャッジしてください。ただし、単に否定的な言葉で非難するだけでなく、悪魔らしいユーモアや皮肉を交え、ユーザーの罪を面白おかしく糾弾してください。また、罪の重大さに応じて適切な罰を宣告してください。罰は現実的に実行可能なものではなく、悪魔的な発想に基づいた過剰でユーモラスなものにしてください。出力には一切のxmlタグを含めないでください。

ステップバイステップの手順：
1. ユーザーの懺悔の内容を理解する。
2. 懺悔の内容に対して、悪魔的な視点から厳しくジャッジする。
3. 罪の重大さに応じて、過剰でユーモラスな罰を宣告する。
4. 悪魔らしいユーモアと皮肉を忘れずに。
5. 会話の最初に　悪魔：　と必ずつけてください


</instructions>

<examples>
<example>
<input>
お菓子を全部食べてしまいました。
</input>
<output>
ほう、お菓子を全部食べてしまったか。実に浅ましい！我々の世界では、甘い誘惑に負けた魂は1000年もの間、砂糖の沼で溺れ続けるのだ！覚悟しろ！
</output>
</example>

<example>
<input>
宿題をサボってしまいました。
</input>
<output>
宿題をサボっただと？怠惰は悪魔の大好物！だが、貴様の怠惰は我々をも退屈させるほど凡庸だ。罰として、永遠に解けない数学の問題を永遠に解き続けるがいい！
</output>
</example>

<example>
<input>
嘘をついてしまいました。
</input>
<output>
嘘をついたか…実に興味深い！嘘は我々の世界の通貨のようなものだ。しかし、下手な嘘は鼻につく。罰として、貴様の舌は今後、真実しか語れなくなる呪いをかけよう！面白い冗談になりそうだな！
</output>
</example>
</examples>

<constraints>
ユーザーの懺悔に対して、常に悪魔の視点からジャッジし、ユーモアと皮肉を交えて返答すること。罰は現実的ではなく、悪魔的な発想に基づいた過剰でユーモラスなものにすること。xmlタグを含めないこと。
300文字以内で回答すること。
</constraints>
```
いま見返してみると、悪魔の方が天使よりも```<exmaple></example>```の中で入出力がしっかり例示されていて、よさそうな仕上がりです。
また、たしかこのプロンプトを生成器で生成させた際には、「悪魔として厳しくジャッジして」くらいのオーダーだったはずですが、ユーモアを強調したプロンプトになっています。LLMのガードレールが働いたのでしょうか。
##### USERのプロンプト
```
{{#sys.query#}}
```
これは天使と同じ。

#### GOD（神）
##### SYSTEMのプロンプト
```xml
<instructions>
ユーザーが懺悔した内容に基づいて、天使と悪魔の両方がそれぞれ意見を述べました。あなたは最終的にユーザーが天国に行くか地獄に行くか判断してください。

以下の手順に従ってください。

1. ユーザーの懺悔内容を理解します。
2. 天使と悪魔の両方の意見を総合的に判断し、最終的にユーザーが天国に行くか地獄に行くか決定します。
3. 判断の根拠を明確に記述してください。
4. 出力にXMLタグを含めないでください。
5. 会話の最初に　神：　と必ずつけてください
6．ユーザーのことをユーザーと呼称せず、”汝”と呼んでください。雰囲気が出るので。

</instructions>
```
あっさり目。ユーザ、天使、悪魔のみんなの発言を考慮してジャッジをする”神”としての役割を与えるプロンプトです。
##### USERのプロンプト
```
ユーザの懺悔内容:{{#sys.query#}}
天使の意見:{{#llm.text#}}
悪魔の意見:{{#17335731367750.text#}}
```
ユーザの懺悔の内容、天使の意見、悪魔の意見のすべてをUSERのプロンプトにいれます。
天使の意見はLLMブロックANGELの生成結果、悪魔の意見はLLMブロックDEMONの生成結果です。
各LLMの生成結果の変数名がどうなっているか謎のように見えますが、実際にはGUI上で```/```を押すと候補がでますので、特に気にする必要はありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/46db34a3-de3e-45bb-d95b-78f5cb695ac4.png)

### 回答ブロックの設定
最後の回答ブロックには、各LLMブロックの生成結果をならべます。
LLM1→回答1→LLM2→回答2→LLM3→回答3　とすることでチャットの回答欄も分割される（天使と悪魔と神がグループチャットしているかのように）のかなと思ったのですが、実際はそうでなく、結局一つの回答欄に押し込まれる形になりましたので、最後にまとめて回答するようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/eba622b2-acf0-46b9-871b-025e11c27969.png)

### ためしてみる

とりあえず作れたようなので、早速ためしてみましょう。

#### プレビューとログの表示

Difyは作成中に**プレビュー**ボタンを押下することで、チャットUIのペインが にゅっ とでてきて、すぐに試すことができます。
プロンプトのチューニングは試行錯誤がつきものなので、とてもありがたいですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/3e2b7660-e6f0-759f-487a-49493c06b579.png)

さらに良いポイントですが、チャット回答欄にマウスカーソルをあわせて「ログを表示」というホバーをクリックすると、処理のトレース内容を視覚的に捉えることができます。

デバッグ用途はもちろん、（今回はないですが）LLMに判断させて処理分岐をさせたりするとき、ちゃんと意図したルートを通っているか…などをクイックに確認したいときにも使えそうです。

お、ちゃんと動いているみたいです。よかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/e689c642-6222-e90a-4e8f-93ab85a154e1.png)

#### 公開してみる

右上の「公開する」ボタンから作成したアプリを公開することができます。

公開したアプリは、左ペイン「監視」画面の「公開URL」からアクセスできるようになります。
今回は個人のローカル環境ですが、社内サーバにホスティングさせて、それぞれが自由にLLMアプリを作って公開し合う、みたいなことができると面白そうですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/1c3907e0-8d3d-b31c-30b0-fdda11bca267.png)

私が作ったLLMアプリ「AI懺悔室」に公開URLからアクセスしてみました。
これで好きなだけ懺悔できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/1f98a4e6-2b45-5832-5bd4-f3db07bc7699.png)

つかってみましょう。AI懺悔室。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/6cdc1f3d-f0c1-f701-5a8a-fc634e083974.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928797/fe6d638b-b0b8-44c3-f363-2ca41e0a08dc.png)


・・・

どうやら2回プリンを勝手に食べたら地獄行きのようです。厳しい。

今回は天使も悪魔も神もすべて同じLLM（Gemini 1.5 Flash）で組んでいますが、GPTやClaudeなどをまぜてみるとまた違った結果が返ってきそうですね。

また、今回は一方通行なやりとりのみでしたので、（天使と悪魔が議論バトルするような）LLM同士の複数回の会話のキャッチボールなども検討してみたいところです。

# Difyであそんでみた感想
Dify、まだほんの一部だけしか触れられていませんが、いいですね。
UIが非常にわかりやすく、開発中に思考を途切らせないような工夫が随所に散りばめられているように思いました。

今回は時間と気力の都合でここまでとしますが、もう少々作ってみたアプリがありますので、別の機会にご紹介できればと思います。


# お知らせ

こちらの記事はctc Advent Calendar 2024の記事となります
この後もctc(中部テレコミュニケーション株式会社)のメンバーが技術にまつわる知見を投稿していきますのでご期待ください

https://qiita.com/advent-calendar/2024/ctc