Difyカスタムツール × Azure Functions で疎結合なワークフローノードを展開
はじめに
Difyにおいて任意のPythonライブラリを使用したり、外部API呼び出しを組み込んだワークフローを構築したいケースが多くあるかと思います。
マーケットプレイスにあるサービスであればフローへの組み込みは簡単ですが、使いたいサービスがなかったり、カスタマイズして使用したい場合もあるかと思います。
そんな時に、"疎結合" を保ちながら独自処理の構築、展開が可能となる
Azure Functions + Dify Custom Tool
という構成がとても使いやすいと思いましたので、本記事にて紹介できればと思います。
なぜこの構成を検討したか?
Difyにはコード実行ノードが用意されており、Python / NodeJSコードを実行することが可能です。
ただし、コード実行ノードには以下のような課題があります。
-
インターネットアクセス不可
コードノードから直接外部APIの呼び出しができないので、コードノードとhttpリクエストノードを組み合わせる必要あり。
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のデプロイ
プロジェクト作成 & ロジック実装
本記事では詳細説明を割愛しますが、以下公式ドキュメント等を参考にリソースの作成、デプロイをしてください。
-
実行環境(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
C. Dify ワークフローへの組み込み
フロー全体
1. 開始ノードで引数として渡す'name'変数を設定
name
に前段ノードで生成した値を設定
2. 作成したカスタムツールを配置し、引数 3. 終了ノードで結果を表示
利点まとめ
- 疎結合 — Dify 側にスクリプトを埋め込まず Function URL で切り離し
- 保守性 — ランタイム依存ライブラリは Azure にお任せ
- 再利用性 — Dify 以外のクライアント(Power Automate 等)でも同じ Function を再利用
- セキュリティ — Function Key / AAD 認証、VNet 統合など Azure 標準オプションが使える
Discussion