🔨

Difyをdockerで起動しAPIを使ってチャットしてみた

に公開

タイトルの通り、Difyをdockerで起動しAPIを叩いてチャットをしてみました!

Difyとは?

オープンソースのLLMアプリ開発プラットフォームです。
エージェントAIワークフローやRAGパイプラインなどをローコードで組めます。

DifyはDifyクラウドというWeb上で提供されるサービスを使うこともできますし、ローカルで立ち上げることも可能です。

今回はローカルでDifyを起動させるため、dockerを使ってDifyのサーバーを起動します。
その後、APIを叩くPythonコードを書いてチャットをしてみます。

APIの仕様はこちら👇
https://docs.dify.ai/api-reference/chat/send-chat-message

APIを使うと何が良いの?🤔

APIを使うことで様々なカスタムが可能になります。

  • Difyのバックエンド+カスタムUIの構成が使用可能になる!
  • プロンプトや知識データベースを公開せずに生成AI機能をエンドユーザーに提供できるようになる!
  • APIの呼び出しはDifyの管理インターフェースでログ分析が可能。実行が成功したか失敗したかも確認可能!

Difyのダウンロードと起動

以下のGitHubからgit cloneしてdocerコマンドを叩きます。
(事前にdocker desktopなどのdocker環境のインストールが必要。)
https://github.com/langgenius/dify/tree/main

githubからダウンロード

git clone https://github.com/langgenius/dify.git

次にDockerの起動

cd dify
cd docker
cp .env.example .env
docker compose up -d

Difyへアクセス
初回起動時:http://localhost/install
設定後:http://localhost

LLMの設定

LLMを使うための初期設定をしましょう。
起動したらアカウント画像をクリック→設定をクリック→モデルプロバイダーを選択

お好きなモデルプロバイダーをインストールして下さい。(画像はGeminiの例)

チャットフローの作成

次はAPIを使えるように適当なチャットフロー作ります。
最初から作成をクリック

アプリタイプを選択でチャットフローを選び、内容を記入して作成ボタンを押します。

そうすると、基本のチャットフローが作られます。LLMは先ほど設定したモデルを選びます。

次に、APIを使えるようにするため公開をしましょう。青色の公開するボタンを押します。

公開するとWebページとバックエンドサービスAPIが稼働します。

次に、バックエンドサービスAPIを使うためにAPIキーを取得します。

新しいシークレットキーを作成ボタンを押すとキーが生成されます。のちに使うのでメモしておきましょう。
※APIキーの管理は厳重に。

クライアントの準備

APIキーを叩くためのクライアント側スクリプトを書きます。ここではPythonで組みます。
以下のPythonコードを書きましょう。

import requests
import json

def chat_with_dif(api_key, query, inputs, user_id, response_mode="streaming", conversation_id=None):
    """
    Dify API経由でチャットする関数
    """
    url = "http://localhost/v1/chat-messages" # チャットフロー用エンドポイント
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    }
    payload = {
        "query": query,
        "inputs": inputs,
        "response_mode": response_mode,
        "user": user_id,
        "conversation_id": conversation_id
    }
    response = requests.post(url, headers=headers, data=json.dumps(payload))
    return response.text

def answer_decode(response):
    """
    レスポンスからanswerフィールドを抽出し、適切にデコードする
    """
    try:
        response_json = json.loads(response)
        answer = response_json.get("answer", "")
        return answer
    except Exception as e:
        return f"エラーが発生しました: {e}"


if __name__ == "__main__":
    api_key = "<取得したバックエンドサービスAPIキーを書いてね>"
    query = "<質問したいことを書いてね>"
    inputs = {}
    user_id = "<ユーザー名を書いてね>"
    response_mode = "blocking"
    response = chat_with_dif(api_key, query, inputs, user_id, response_mode)
    answer = answer_decode(response)
    print("質問:", query)
    print("回答:", answer)

これでAPIを使ってチャットする準備が整いました!
実行してこんな感じでやりとりができれば完成です!

継続的なチャットをするやり方

実は、前述のコードを使ってAPIを逐次叩いても継続的にチャットすることはできません。
例えば、
クエリ1「私の名前ははっししゅうです。」
クエリ2「私の名前を覚えていますか?」
といったクエリに対して順番にchat_with_dif関数を呼び出しても、

となってしまいます。

そこで使うのが、conversation_idです。
このIDを指定することで継続的にチャットすることが可能になります。

def answer_decode(response):
    """
    レスポンスからanswerフィールドとconversation_idを抽出し、適切にデコードする
    """
    try:
        response_json = json.loads(response)
        answer = response_json.get("answer", "")
        conversation_id = response_json.get("conversation_id", "")
        return answer, conversation_id
    except Exception as e:
        return f"エラーが発生しました: {e}", ""


if __name__ == "__main__":
    api_key = "<取得したバックエンドサービスAPIキーを書いてね>"
    query1 = "私の名前ははっししゅうです。"
    query2 = "私の名前を覚えていますか?"
    inputs = {}
    user_id = "<ユーザー名を書いてね>"
    response_mode = "blocking"
    
    print("=" * 60)
    print("Dify API Chat Test")
    print("=" * 60)
    
    # 最初のクエリ(新しい会話)
    print("\n【新しい会話の開始】")
    response = chat_with_dif(api_key, query1, inputs, user_id, response_mode)
    answer, conversation_id = answer_decode(response)
    print(f"Query: {query1}")
    print(f"Answer: {answer}")
    print(f"Conversation ID: {conversation_id}")
    
    print("\n" + "-" * 50)
    
    # 同じ会話で2番目のクエリ
    print("\n【同じ会話での継続】")
    response = chat_with_dif(api_key, query2, inputs, user_id, response_mode, conversation_id)
    answer, _ = answer_decode(response)
    print(f"Query: {query2}")
    print(f"Answer: {answer}")
    print(f"Conversation ID: {conversation_id}")
    
    print("\n" + "=" * 60)

これを実行すると、

会話履歴を保持しつつ会話できるようになりました!

ちなみにDify側を見るとチャットログを見ることができます。
デバックやログ監視にも有用です。

まとめ

Difyをdockerで起動し、バックエンドサービスAPIを叩いてチャットをしてみました。
次はさらにAPIの使い方を応用した例を記事にしたいと思います。

お読みいただきありがとうございました!

Discussion