2
0

【Dify】flask-openapi3による独自処理のカスタムツール化

Last updated at Posted at 2024-06-30

概要

flask-openapi3を使って、独自処理をDifyのカスタムツール化する方法のメモです。

背景

DifyはLLMアプリケーションをノーコードで作れるツールです。とても便利ですが、組み込みツールだけだと、実現できる処理の自由度に限界があります。
ローカルでAPIを作ってカスタムツールとして登録できれば、開発の自由度が高まることが期待されます。
Difyでは、OpenAPIの仕様に沿って作られたAPIは簡単にカスタムツールとして登録することができます。そこで、flask-openapi3を使って、pythonでローカル実装された関数を、Difyのカスタムツールに登録することを試みました。

環境

  • flask-openapi3 バージョン3.1.3

    pip install flask-openapi3
    
  • M1 Mac

  • pythonは3.11.2

  • Difyのクラウド版

  • ngrok(クラウド版からローカルのサーバーに到達できるようにするために使用)

    brew install ngrok
    

手順

ngrokの起動

ポート5000でAPIサーバを起動することを前提にngrokを実行します。このあと登場するpythonコードにngrokのURLを記載する必要があるので、先に実行します。

ngrok http 5000

実行後、Forwardingという行に記載されたhttpsのURLをコピーしておきます。
ここでは仮に"https://ngrokaddress.app" としておきます。

flaskサーバの実行

flask-openapi3のgithubのservers_demo.pyを参考に、ユーザの入力をオウム返しするAPIを作ってみます。

from pydantic import BaseModel

from flask_openapi3 import Info, Tag
from flask_openapi3 import OpenAPI, Server

info = Info(title="Echo API", version="1.0.0")
servers = [
    Server(url="https://ngrokaddress.app")
]
app = OpenAPI(__name__, info=info, servers=servers)

echo_tag = Tag(name="echo", description="echo your input")


class Query(BaseModel):
    input_text: str

@app.get("/echo", tags=[echo_tag])
def echo_input(query: Query):
    """echo the text you input
    to check server response
    """
    return {
        "code": 0,
        "message": "ok",
        "data": [
            {"response": f"you input {query.input_text}" }
        ]
    }


if __name__ == '__main__':
    app.run(debug=True) # デフォルトポートは5000

実行します。

python app.py

エラーなく、実行できたらngrokのアドレスにブラウザからアクセスしてみます、ngrokを実行していなかったら実行してください。
ngrokのアドレス末尾に"/openapi"を付ける必要があることに注意してください。
(例:"https://ngrokaddress.app/openapi")

pypiのページにあるようなswagger, ReDocなどを選択できるページが表示されれば成功です。
"https://ngrokaddress.app/openapi/openapi.json"にアクセスするとAPIの仕様を表すjsonが見られます。Difyにはこれを登録します。

Difyのカスタムツールの作成

Dify > ツール > カスタム > カスタムツールを作成する > +URLからインポートする
と遷移し、表示されたテキストボックスに"https://ngrokaddress.app/openapi/openapi.json" を入力し、OKを押下します。その後「スキーマ」のテキストボックスにjsonが入力されたら成功です。

image.png

「利用可能なツール」のところに「echo_input_echo_get」という名前のメソッドが追加されていると思います。ソースコードの対応を整理すると先頭の"echo_input"がメソッド名、次のecho"がURLのパス、最後の"get"はリクエストのメソッド名に対応しているようです。

image.png

適当な名前をつけて、登録を完了したら、ワークフローなどの作成画面から作成したカスタムツールが選べるようになっています。

image.png

おわりに

flaskで作ったAPIをDifyのカスタムツールに登録することができました。Difyにpythonの独自関数をツールとして登録できると、やれることの幅が大きく広がるので、実装方法がわかってよかったです。flask-openopi3のお陰で、実装量を大幅に減らせたため開発者の方に感謝です。

今後の課題としては、無料版のngrokだと、URLがngrokの実行ごとに変わってしまって使いにくいので、なにか対応を考えたほうが良さそうです。

本記事がどなたかのお役に立てましたら幸いです。

補足

flask-openapi3のSimple Exampleそのままだとエラーになる

flask-openapi3のPyPIのトップページにあるSimple Exampleをそのままサーバとして用いると、カスタムツールからの登録に失敗します。invalid schema...みたいなメッセージが出ました。少し調べると、server(のurl)の情報がschemaに含まれていないためエラーになるようです。

app.py
info = Info(title="Echo API", version="1.0.0")
servers = [
    Server(url="https://ngrokaddress.app")
]
app = OpenAPI(__name__, info=info, servers=servers)

本記事のapp.pyのようにServerクラスを使って、urlを与えることで、エラーを出さなくすることができました。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0