DifyをAzure OpenAIで試してみる

# DifyをAzure OpenAIで試してみる

## Difyとは？
Difyは、オープンソースのLLM（大規模言語モデル）アプリケーション開発プラットフォーム。Difyを使用すると、さまざまなLLMやAIワークフローを簡単に構築し、迅速にプロトタイプから製品化に移行できる。

主な機能
	1.	ワークフロー構築: AIワークフローを視覚的に構築できるキャンバスを提供し、様々なタスクを自動化。
	2.	エージェント機能: LLMエージェントを作成し、複数のツールやモデルと連携させることが可能。Google検索、DALL·E、Stable Diffusionなど、50以上のツールをエージェントに組み込むことができる。
	3.	RAGパイプライン: 文書の取り込みや検索に対応するRAG（Retrieval-Augmented Generation）機能を備えており、PDFやPPTからのテキスト抽出をサポートできる。
	4.	自己ホスティング: Dockerを利用してDifyを自分の環境に展開でき、特定のLLMやエンベディングモデルを組み込んで運用することが可能。



Langflowと同じジャンルのサービス・製品。ノー・ローコードでオリジナルチャットやLLMワークフローを作成できる。


## インストール&起動
リポジトリからソースをcloneして、付帯のdockerfileを起動するだけ。

```bash
git clone https://github.com/langgenius/dify.git
cd dify/docker
docker-compose up -d
```

ローカル起動ポートは80なので、変更したい場合は以下のとおり。（.envのサンプルがあるため、これをコピーして設定）
```bash
cp .env.example .env
vim .env

# ------------------------------

# Docker Compose Service Expose Host Port Configurations

# ------------------------------

#EXPOSE_NGINX_PORT=80 #コメントアウト
EXPOSE_NGINX_PORT=8082 #追加
EXPOSE_NGINX_SSL_PORT=443

```

（補足）
個人的備忘録。docker→podmanに移行したため、podman-composeで起動する場合、defaultNW関連のエラーが出る。（dockerとpodmanの差異）
docker-compose.yamlにdefaultネットワークを追加する。
```bash
vim ./docker-compose.yaml

networks:
  ssrf_proxy_network:
    driver: bridge
    internal: true
  default: #追加
    driver: bridge #追加

podman-compose up -d   
```

## 実行
ブラウザから　http://localhost:8082/　にアクセスすると、ログイン画面が開く。
初回アクセスであれば、「管理者アカウントの設定」からユーザ登録をする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/b035cd66-cc50-2ce6-6ab2-c122d1942151.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/fc66e85b-a0b3-0a01-a0f6-23b0bc733959.png)

ユーザ登録後、再度トップから登録したユーザにてログインすると、Difyのトップ画面が開く。
最初から作成で、チャットボットを作成してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/612fb2e6-010d-a4a5-25d0-f13224ccf46b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/c99cecef-dc36-12a5-9cf7-9c82c7a6ac1e.png)

プレイグラウンドライクな画面が表示される。LLMプロバイダーキーの設定にて、AzureOpenAIのいつもの設定を行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/abe16f1f-e2c8-b453-bae1-d4317f54050d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/43a7dae5-e327-d825-0698-9ee7ae468fb5.png)

LLMの設定が完了すると利用可能状態となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/657d6ed1-157d-e41e-f09d-5d2e24aed39c.png)

チャットが機能することを確認する。ここまでで利用疎通は完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/ed903688-88f7-79b9-e9d0-405204a5a8e1.png)





## ワークフローの作成、実行

### ワークフローの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/96715e3a-b2b2-b601-e973-a6adb4481472.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/18e0a531-f2b6-6069-df3c-460ce8219855.png)


### 作成シナリオ
Pythonコードの実行とLLM問い合わせの組み合わせを試したいため、以下のようなシナリオを考えてみる。
・コード実行にて、pythonで「今日の日付」を取得する。
・取得した「今日の日付」をプロンプトに埋め込み、「今日の日付」を起点とした、「明後日の日付」をLLMに回答させてみる。

### コード
以下のように引数なしで「今日の日付」を返す関数を作成する。戻り値はデフォルトの辞書型をそのまま踏襲。
引数などは不要なので削除した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/dafa2e37-3484-0476-05b5-a98e987a3266.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/630a473c-17a8-9343-8663-b707618adb2f.png)


### LLM（プロンプト）
モデルは先ほど定義済みのものを使用。
コードの出力の「今日の日付」（result）を入力となるようにコンテキストを設定。またプロンプト（USER）の中に{x}から指定してこれを埋め込む。(LangchainのTemplate部のような定義)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/082c5e9b-eaaf-e0f1-119b-eca384037f33.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/88b47ef1-73c9-2804-606b-da70ce2272b6.png)


### 実行
コードで取得した「今日の日付」を利用して、LLMに引き渡して問い合わせ、回答を正しく得ていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/433842db-cc8b-6faf-90f2-75079f9b05bd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/352ed026-acee-1006-e5d3-b11a829dd222.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/00fa1a2a-95e1-48a6-f3b1-0b3fa7291ba6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/870ca7e8-890e-3826-008b-e0b3317c42f5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/9bd3e85c-0c0d-b35c-8c34-60a39d155b3d.png)


このように他にもRAG連携などを視覚的に組むことができ、手軽にアプリとして公開することも可能。

その場合、このワークフローだと実行結果がわからないので、「終了」にてLLMの実行結果を出力するようにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/1ac08cb2-a57c-343f-06a0-47078c9c3fa7.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/ebfd3fa7-69bf-ae7f-dc47-a5e73097660e.png)

ただし、portを変更している場合、アプリを実行のURLをブラウザで手動で変更する必要がある。
http://localhost/workflow/I5poEv4322jZa3MX
　↓
http://localhost:8082/workflow/I5poEv4322jZa3MX

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/841764a0-6baa-8665-afab-f90891dce61f.png)

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/0e087574-b9a5-78e4-a383-fae37e5ef8a6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288299/72362fbf-8bbb-1282-004f-d3ac1098727a.png)


# まとめ
LangChainでのChain部分を視覚的にさくっと試せるのは大きい。また修正したチャットも手軽に公開できるため、活用の幅は大きい。複雑なロジックはコードの記載制限もありそうな点、セキュリティ面の懸念もあるので、使い所は要検討。