🛠️

Difyカスタムツール × Azure Functions で疎結合なワークフローノードを展開

に公開

はじめに

Difyにおいて任意のPythonライブラリを使用したり、外部API呼び出しを組み込んだワークフローを構築したいケースが多くあるかと思います。

マーケットプレイスにあるサービスであればフローへの組み込みは簡単ですが、使いたいサービスがなかったり、カスタマイズして使用したい場合もあるかと思います。

そんな時に、"疎結合" を保ちながら独自処理の構築、展開が可能となる
Azure Functions + Dify Custom Tool という構成がとても使いやすいと思いましたので、本記事にて紹介できればと思います。

なぜこの構成を検討したか?

Difyにはコード実行ノードが用意されており、Python / NodeJSコードを実行することが可能です。
ただし、コード実行ノードには以下のような課題があります。

  • インターネットアクセス不可
    コードノードから直接外部APIの呼び出しができないので、コードノードとhttpリクエストノードを組み合わせる必要あり。
    alt text
    https://docs.dify.ai/en/guides/workflow/node/code

  • カスタムパッケージのインストール不可(=pip installできない)
    Dify Sandboxコンテナでrequirements.txtファイルに任意のライブラリを追加インストールできるようですが、Difyの内部構成を理解できていないバージョンアップなど、いつか保守のタイミングで躓きそう。。
    https://dify.ai/blog/dify-ai-blog-introducing-difysandbox

  • コード実行ノードは基本的にテキスト処理などの短時間実行(数秒)想定の簡易処理向けの認識


前提(Prerequisites)

準備物 メモ
Dify クラウド版 Free プランで OK
Azure サブスクリプション Functions をデプロイできれば可
開発環境 VS Code + Azure Functions Extention

A. Azure Functionsのデプロイ

プロジェクト作成 & ロジック実装

本記事では詳細説明を割愛しますが、以下公式ドキュメント等を参考にリソースの作成、デプロイをしてください。
https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-develop-vs-code?tabs=node-v4%2Cpython-v2%2Cisolated-process%2Cquick-create&pivots=programming-language-python

  • 実行環境(Pythonなど)や認証の設定についてGUIで設定を求められますが、任意のものを設定してください。本記事では以下を設定します。

    • 実行環境:Python
    • 認証:Anonymous
  • また今回は初期で作成されるサンプルの処理をそのまま使ってDifyから呼び出してみます。

import azure.functions as func
import logging

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="http_trigger")
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    if name:
        return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )

B. Dify Custom Toolを設定

Custom Toolで以下 YAML を登録

  • yamlファイルの説明
    • info: APIの基本情報(タイトルやバージョン)を定義するセクション
    • servers: APIのベースURLを指定するセクション(Azure Functionsのエンドポイント)
    • paths: 利用可能なAPIエンドポイントとその詳細(パラメータ、レスポンス形式など)を定義
openapi: 3.0.3
info:
  title: DifyTool Function
  version: "1.0.0"
servers:
  # <YOUR_FUNCTION_APP_NAME> をご自身の関数アプリ名に置き換えてください
  - url: https://<YOUR_FUNCTION_APP_NAME>.azurewebsites.net/api
paths:
  /http_trigger:
    get:
      summary: hello azfunc
      operationId: getDifytool
      parameters:
        - name: name
          in: query
          description: Person to greet
          required: false
          schema:
            type: string
      responses:
        "200":
          description: Plain-text greeting
          content:
            text/plain:
              schema:
                type: string

alt text

C. Dify ワークフローへの組み込み

フロー全体

alt text

1. 開始ノードで引数として渡す'name'変数を設定

2. 作成したカスタムツールを配置し、引数 name に前段ノードで生成した値を設定

alt text

3. 終了ノードで結果を表示

alt text


利点まとめ

  1. 疎結合 — Dify 側にスクリプトを埋め込まず Function URL で切り離し
  2. 保守性 — ランタイム依存ライブラリは Azure にお任せ
  3. 再利用性 — Dify 以外のクライアント(Power Automate 等)でも同じ Function を再利用
  4. セキュリティ — Function Key / AAD 認証、VNet 統合など Azure 標準オプションが使える

Discussion