メインコンテンツへスキップ
開発者は API 拡張モジュール機能を使用してモジュール機能を拡張できます。現在、以下のモジュール拡張がサポートされています:
  • moderation センシティブコンテンツ審査
  • external_data_tool 外部データツール
モジュール機能を拡張する前に、API と認証用の API Key を準備する必要があります。 対応するモジュール機能を開発する必要があるだけでなく、Dify が API を正しく呼び出せるように、以下の仕様に従う必要があります。

API 仕様

Dify は以下の仕様でインターフェースを呼び出します:
POST {Your-API-Endpoint}
HeaderValueDesc
Content-Typeapplication/jsonリクエストコンテンツは JSON 形式です。
AuthorizationBearer API Key はトークン形式で送信されます。この api_key を解析し、提供された API Key と一致することを確認して、インターフェースのセキュリティを確保する必要があります。

Request Body

{
    "point":  string, //  拡張ポイント、異なるモジュールには複数の拡張ポイントが含まれる場合があります
    "params": {
        ...  // 各モジュール拡張ポイントに渡されるパラメータ
    }
}

API レスポンス

{
    ...  // API が返すコンテンツ、異なる拡張ポイントのレスポンスについては各モジュールの仕様設計を参照してください
}

検証

Dify で API-based Extension を設定する際、Dify は API の可用性を確認するために API Endpoint にリクエストを送信します。 API Endpoint が point=ping を受信したとき、インターフェースは result=pong を返す必要があります。具体的には以下の通りです:

Header

Content-Type: application/json
Authorization: Bearer {api_key}

Request Body

{
    "point": "ping"
}

API 期待レスポンス

{
    "result": "pong"
}

サンプル

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

API サンプル

POST https://fake-domain.com/api/dify/receive
Header
Content-Type: application/json
Authorization: Bearer 123456
Request Body
{
    "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)):
        """
        Receive API query data from Dify.
        """
        expected_api_key = "123456"  # TODO Your API key of this 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
    
        # for debug
        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 other point implementation here
    
        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")
    
        # for debug
        print(f"app_id: {app_id}")
        print(f"tool_variable: {tool_variable}")
        print(f"inputs: {inputs}")
        print(f"query: {query}")
    
        # TODO your external data tool query implementation here, 
        #  return must be a dict with key "result", and the value is the query 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 Key は 123456 です。
    uvicorn main:app --reload --host 0.0.0.0
    
  4. Dify でこの API を設定します。
  5. App でこの API 拡張を選択します。
App のデバッグ時、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 ファイルをダウンロードします。 Download
  2. ダウンロード完了後、ダウンロードディレクトリに移動し、以下の説明に従って圧縮ファイルを解凍し、説明の初期化スクリプトを実行します。
    unzip /path/to/ngrok.zip
    ./ngrok config add-authtoken あなたのToken
    
  3. ローカル API サービスのポートを確認します: ポート確認 そして、以下のコマンドを実行して起動します:
    ./ngrok http ポート番号
    
    起動成功のサンプルは以下の通りです: Ngrok 起動
  4. 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 拡張のデプロイ

API 拡張をデプロイするには Cloudflare Workers の使用をお勧めします。Cloudflare Workers は簡単に公開ネットワークアドレスを提供でき、無料で使用できます。 詳細な説明については、Cloudflare Workers を使用した API 拡張のデプロイ を参照してください。