API 拡張

開発者はAPIエクステンションを通じてモジュールの機能を拡張できます。現在、以下のモジュールがサポートされています:

  • モデレーション 敏感内容の監査

  • 外部データツール 外部データツール

モジュールの機能を拡張する前に、APIと認証用のAPIキー(Difyが自動生成することも可能)を準備する必要があります。

対応するモジュール機能を開発するだけでなく、DifyがAPIを正しく呼び出せるよう、以下の規範にも従う必要があります。

API規範

Difyは以下の規範に従ってインターフェースを呼び出します:

POST {Your-API-Endpoint}

ヘッダー

HeaderValueDesc

コンテンツタイプ

アプリケーション/JSON

リクエスト内容はJSON形式です。

認証

ベアラー {api_key}

APIキーはトークン形式で送信されます。api_keyを解析し、提供されたAPIキーと一致するか確認してください。

リクエストボディ

{
    "point":  string, //  エクステンションポイント、異なるモジュールは複数のエクステンションポイントを含む可能性があります
    "params": {
        ...  // 各モジュールのエクステンションポイントに渡すパラメータ
    }
}

APIレスポンス

{
    ...  // APIレスポンスの内容、異なるエクステンションポイントのレスポンスは各モジュールの規範に従います
}

検証

DifyがAPIベースのエクステンションを設定する際、DifyはAPIエンドポイントにリクエストを送り、APIの有効性を確認します。

APIエンドポイントがpoint=pingを受信した場合、インターフェースはresult=pongを返す必要があります。具体的には次の通りです:

ヘッダー

コンテンツタイプ: アプリケーション/JSON
認証: ベアラー {api_key}

リクエストボディ

{
    "point": "ping"
}

API期待レスポンス

{
    "result": "pong"
}

ここでは外部データツールを例にとり、地域に基づいて外部の天気情報を取得するシナリオを示します。

API例

POST https://fake-domain.com/api/dify/receive

ヘッダー

コンテンツタイプ: アプリケーション/JSON
認証: ベアラー 123456

リクエストボディ

{
    "point": "app.external_data_tool.query",
    "params": {
        "app_id": "61248ab4-1125-45be-ae32-0ce91334d021",
        "tool_variable": "weather_retrieve",
        "inputs": {
            "location": "London"
        },
        "query": "How's the weather today?"
    }
}

APIレスポンス

{
    "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain"
}

コード例

コードはPython FastAPIフレームワークに基づいています。

  1. 依存関係をインストールする

    pip install fastapi[all] uvicorn
  2. インターフェース仕様に従ってコードを書く

    from fastapi import FastAPI, Body, HTTPException, Header
    from pydantic import BaseModel
    
    app = FastAPI()
    
    
    class InputData(BaseModel):
        point: str
        params: dict = {}
    
    
    @app.post("/api/dify/receive")
    async def dify_receive(data: InputData = Body(...), authorization: str = Header(None)):
        """
        DifyからのAPIクエリデータを受信します。
        """
        expected_api_key = "123456"  # TODO このAPIのAPIキー
        auth_scheme, _, api_key = authorization.partition(' ')
    
        if auth_scheme.lower() != "bearer" or api_key != expected_api_key:
            raise HTTPException(status_code=401, detail="Unauthorized")
    
        point = data.point
    
        # デバッグ用
        print(f"point: {point}")
    
        if point == "ping":
            return {
                "result": "pong"
            }
        if point == "app.external_data_tool.query":
            return handle_app_external_data_tool_query(params=data.params)
        # elif point == "{point name}":
            # TODO その他のポイントの実装
    
        raise HTTPException(status_code=400, detail="Not implemented")
    
    
    def handle_app_external_data_tool_query(params: dict):
        app_id = params.get("app_id")
        tool_variable = params.get("tool_variable")
        inputs = params.get("inputs")
        query = params.get("query")
    
        # デバッグ用
        print(f"app_id: {app_id}")
        print(f"tool_variable: {tool_variable}")
        print(f"inputs: {inputs}")
        print(f"query: {query}")
    
        # TODO 外部データツールクエリの実装
        # 返り値は"result"キーを持つ辞書でなければならず、その値はクエリの結果でなければならない
        if inputs.get("location") == "London":
            return {
                "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind "
                          "Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain"
            }
        else:
            return {"result": "Unknown city"}
  3. APIサービスを起動する。デフォルトポートは8000で、APIの完全なアドレスは:http://127.0.0.1:8000/api/dify/receive、設定されたAPIキーは123456です。

    uvicorn main:app --reload --host 0.0.0.0
  4. DifyにこのAPIを設定します。

  1. アプリでこのAPIエクステンションを選択します。

アプリのデバッグ時、Difyは設定されたAPIにリクエストを送り、以下の内容(例)を送信します:

{
    "point": "app.external_data_tool.query",
    "params": {
        "app_id": "61248ab4-1125-45be-ae32-0ce91334d021",
        "tool_variable": "weather_retrieve",
        "inputs": {
            "location": "London"
        },
        "query": "How's the weather today?"
    }
}

APIレスポンスは以下の通りです:

{
    "result": "City: London\nTemperature: 10°C\nRealFeel®: 8°C\nAir Quality: Poor\nWind Direction: ENE\nWind Speed: 8 km/h\nWind Gusts: 14 km/h\nPrecipitation: Light rain"
}

ローカルデバッグ

Difyクラウド版は内網APIサービスにアクセスできないため、ローカルでAPIサービスをデバッグするために、Ngrokを使用してAPIサービスのエンドポイントをパブリックに公開し、クラウドでローカルコードをデバッグすることができます。操作手順は次の通りです:

  1. https://ngrok.comの公式サイトにアクセスし、登録してNgrokファイルをダウンロードします。

  2. ダウンロードが完了したら、ダウンロードディレクトリに移動し、以下の説明に従って圧縮ファイルを解凍し、初期化スクリプトを実行します。

    • $ unzip /path/to/ngrok.zip
      $ ./ngrok config add-authtoken 你的Token
  3. ローカルAPIサービスのポートを確認します:

次に以下のコマンドを実行して開始します:

  • $ ./ngrok http 端口号

    成功例は以下の通りです:

  1. Forwardingで示されるように、上の図ではhttps://177e-159-223-41-52.ngrok-free.app(これは例のドメインです。自分のドメインに置き換えてください)がパブリックドメインとなります。

  • 上記の例に従って、ローカルで既に起動しているサービスエンドポイントを公開し、コード例のインターフェース:http://127.0.0.1:8000/api/dify/receivehttps://177e-159-223-41-52.ngrok-free.app/api/dify/receiveに置き換えます。

これで、このAPIエンドポイントはパブリックアクセス可能となります。これで、DifyでこのAPIエンドポイントを設定してローカルデバッグコードを実行できます。設定手順については、外部データツールを参照してください。

Cloudflare Workersを使用したAPIエクステンションのデプロイ

Cloudflare Workersを使用してAPIエクステンションをデプロイすることをお勧めします。Cloudflare Workersは簡単にパブリックアドレスを提供でき、無料で使用できます。

Cloudflare Workers を使用した API ツールのデプロイ

Last updated