話題のローコードツール「Dify」で生成AIアプリを作ってみよう！

# Difyって何？

少し前から話題の、プログラミングなしで生成AIアプリケーションを開発できるOSSです。

https://github.com/langgenius/dify

**「Dify すごい」** でSNSを検索すると、驚き屋さんがみんな驚いています。このゴールデンウィークはAmazon BedrockとDifyの話題でもちきりでしたね。

https://twitter.com/search?q=dify%20%E3%81%99%E3%81%94%E3%81%84&src=typed_query

元々は「GPTビルダーのOSS版ね。はい解散」という感じだったのですが、最近追加された「ワークフロー」機能がすごく便利のようです。

ちょっとしたアプリなら、ローコードで簡単に作れてしまうとのこと。

![スクリーン ショット 2024-05-06 に 11.43.46 午前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/097e8cfb-edb5-3066-43d2-6cd3a842b868.png)

最近は自分でPCやサーバー準備して動かさなくても、SaaS版が公式から準備されたようです。無料プランもあります。

![スクリーン ショット 2024-05-06 に 11.53.52 午前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/aa4dd6bf-07f2-3445-7711-2b5270316fd3.png)



# やってみた

### サインアップ

公式サイト右上の「Get Started」からサインアップします。

https://dify.ai/

GitHub連携すると、いきなり開発画面に辿り着きました！いいUX。

![スクリーン ショット 2024-05-06 に 11.26.09 午前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/6a9021ac-ef3f-e215-11e1-e2a5d72382a4.png)

「（いち？）から作成」よりワークフローを作ってみましょう。まだベータ版のようです。

アプリ名は「ワイのかわりに検索くん」にしてみます。

![スクリーン ショット 2024-05-06 に 11.56.07 午前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/8ad1d313-a7d8-509e-4039-5a42c3c06f5f.png)

### ワークフロー作り

最初に配置されている「開始」というモジュールをクリックして、「入力フィールド」に `Input` という名前の変数を定義しておきます。

これによって、まずアプリの開始時にユーザーから質問を受け取れるようにします。

![スクリーン ショット 2024-05-06 に 11.57.47 午前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/720496d1-a30e-b869-1ac5-92d83253cdda.png)

次に、開始モジュール右側の「＋」ボタンから新しいコンポーネントを追加します。
ユーザーの質問をもとに、まずGoogle検索をさせたいので「GoogleSearch」を追加しましょう。

最初にSerpApiのAPIキーが必要なので、アカウントがない方はGoogleアカウント連携などでサインアップしてください。一定は無料で使えます。

https://serpapi.com/

入力変数に、先ほど「開始」モジュールで設定した `Input` を指定し、Result typeをURLではなく `text` に設定しておきましょう。

![スクリーン ショット 2024-05-06 に 11.59.54 午前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/637e0bd2-8341-cdaf-fcb1-c7352a0eeb3a.png)

その後、検索結果を受け取って推論する「LLM」モジュールを追加します。

モデルは、無料で選べる中で高性能な `gpt-3.5-turbo-16k-0613` を選択し、Systemプロンプトに以下を入力します。

```
以下の「ユーザーの質問」に対して、「Google検索結果」を用いて回答してください。

「ユーザーの質問」：{{#1714964227074.input#}}
「Google検索結果」：{{#1714964362288.text#}}
```

※変数部分は `/` を入力してサジェストから選択できます。

![スクリーン ショット 2024-05-06 に 12.06.11 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/90b3754a-77e5-1af5-a937-cb78f1c68fac.png)

最後に「終了」モジュールを追加すれば完成です。

LLMの回答が出力されるように、出力変数に `LLM / text` を設定しておきましょう。

![スクリーン ショット 2024-05-06 に 12.08.49 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/d48f2e9a-1df3-f53c-b621-e770f8a0242a.png)


### いざ、テスト！

それでは実際に使ってみます。

画面右上の「実行」を押して、テストウィンドウの入力に「Difyって何？」と入力してみます。素のGPTはまだ知らない知識なので、Google検索しないと正しく回答できない質問です。

![スクリーン ショット 2024-05-06 に 12.10.08 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/2c6e1311-da1d-e3b4-9af8-18c9f3d26679.png)

すると、ワークフローが流れて正しい回答が出力されました！これでアプリの完成が確認できました。

![スクリーン ショット 2024-05-06 に 12.11.26 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/99d3161f-14cc-552a-554f-7b3154ccbc2f.png)


### アプリを公開して使ってもらおう！

画面右上の「公開する」を押すと、誰でもブラウザからこのアプリケーションにアクセス可能なURLが発行されます。

超便利ですね！

![スクリーン ショット 2024-05-06 に 12.14.09 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/775f6acb-c158-53ed-a617-7390db39e41a.png)

※残念ながら、入力欄は日本語変換の「Enter」を押すとチャットが送信されてしまう、海外アプリあるあるなバグ持ちのようです。


### PythonからAPIを使ってみよう

さらに、APIからの利用にも対応しています。アプリの公開ボタンより、APIリファレンスにアクセスできます。

![スクリーン ショット 2024-05-06 に 12.23.28 午後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/b03d407c-55b8-e225-d7a6-2fe2fb27fe36.png)

これを丸々Claude 3 Opusに食わせて、「試しにPythonのサンプルコードを生成して」と頼んでみました。

https://claude.ai/chats

Claudeくんと一緒に少しトラブルシュートすると、動くコードが完成しました👏

```py
import requests
import json

API_KEY = "app-XXXXXXXXXXXXX" # DifyのAPIキーを入れてください
BASE_URL = "https://api.dify.ai/v1"


# ワークフローの実行
def run_workflow(inputs, response_mode, user):
    url = f"{BASE_URL}/workflows/run"
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }
    data = {
        "inputs": inputs,
        "response_mode": response_mode,
        "user": user
    }
    response = requests.post(url, headers=headers, data=json.dumps(data))
    
    if response.status_code == 200:
        if response_mode == "blocking":
            result = response.json()
            if "data" in result and "outputs" in result["data"] and "text" in result["data"]["outputs"]:
                return result["data"]["outputs"]["text"]
            else:
                print("Error: 'text' not found in the API response.")
        elif response_mode == "streaming":
            for chunk in response.iter_content(chunk_size=None):
                if chunk:
                    print(chunk.decode())
    else:
        print(f"Request failed with status code {response.status_code}")


# ワークフローの停止
def stop_workflow(task_id, user):
    url = f"{BASE_URL}/workflows/{task_id}/stop"
    headers = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
    data = {"user": user}
    response = requests.post(url, headers=headers, data=json.dumps(data))

    if response.status_code == 200:
        return response.json()
    else:
        print(f"Request failed with status code {response.status_code}")


# アプリケーション情報の取得
def get_parameters(user):
    url = f"{BASE_URL}/parameters?user={user}"
    headers = {"Authorization": f"Bearer {API_KEY}"}
    response = requests.get(url, headers=headers)

    if response.status_code == 200:
        return response.json()
    else:
        print(f"Request failed with status code {response.status_code}")


# サンプル実行
if __name__ == "__main__":
    inputs = {"input": "Bedrockって何？"} #　ここに質問を入れる
    response_mode = "blocking"
    user = "example_user"

    result = run_workflow(inputs, response_mode, user)
    print(result)
```

実行結果👇

```bash
❯ python dify.py
「Bedrock」とは、複数の意味があります。

1つ目の意味は、マインクラフトのバージョンに関連しています。マインクラフトには「Java版」と「Bedrock版（統合版）」という2つのバージョンがあります。Bedrock Editionは、鮮やかなグラフィックや改良された地形、アイテム、公式のアドオンシステムなど、Java Editionとは異なる特徴を持っています。

2つ目の意味は、Amazon Bedrockというサービスです。これは、APIを通じて主要な基盤モデルを利用できるフルマネージド型のサービスで、生成系AIアプリケーションを構築することができます。

3つ目の意味は、地学の用語で、地表下に存在する固い岩石層を指します。この岩石層は、土壌や堆積物の下にあり、地球の表面を形成する基盤となります。

以上が「Bedrock」の意味の一部です。詳細な情報や他の意味については、提供されたリンク先を参照してください。
```

めでたくPythonから、自分のDifyアプリのAPIを利用することができました！


# おまけ

AWSのMarketplaceにもDifyがありました。AMIとして提供されているので、EC2インスタンスでDifyをホストできるようです。

https://aws.amazon.com/marketplace/pp/prodview-t22mebxzwjhu6

最後に宣伝ですが、AWSで生成AIアプリ開発に入門できる本を書きました！すでにアマゾン等で予約可能です✌️

![カバー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/6bcbc0cd-6df7-4056-1c1f-91b5ab600556.png)

https://www.sbcr.jp/product/4815626440/