記事のサマリー(TL;DR)
- Gradioに組み込まれた新機能「gr.Workflow」は、処理ステップを型付きノードのグラフとして記述すると、ドラッグ&ドロップで実行できるキャンバスをGradioが提供し、各ノードの実行や中間結果の確認ができる。
- 同じグラフはREST APIとしても機能し、Hugging Face Spacesへの1コマンドデプロイにも対応する。
- 画像編集、複数モデルを連携させるメディアスタジオ、並列画像生成、データセットのプロファイリング、GPU上で動くモデルの実行といった複数のライブデモ(Hugging Face Space)が紹介されている。
詳細
背景:パイプライン構築とデバッグの課題
多くの興味深いAIアプリはパイプラインとして構成されています。画像を生成してから背景を切り抜いたり、別のものに編集したりする、あるいはスクリプトを書いてから音声を生成したり、スクリプトはそのままに音声だけ差し替えたりする、といった形です。これまではこうしたステップをPythonで手作業でつなぎ合わせ、何かおかしな挙動が出た際には print によるデバッグに戻って、どのステップが異常な値を出力したかを調べる必要がありました。
Gradioに組み込まれた gr.Workflow は、こうしたパイプライン自体をインターフェースにします。処理ステップを型付きノードのグラフとして記述すると、Gradioはドラッグ&ドロップ操作が可能なキャンバスを提供し、各ノードは実行可能で、すべての中間結果を確認できます。同じグラフはREST APIとしても機能し、Hugging Face Spacesへの1コマンドデプロイにも対応します。
記事では、実際に動作するHugging Face Spaceとして公開されている複数のワークフロー例が紹介されています。いずれもその場で開いて実行し、複製(duplicate)できるとのことです。
画像編集(Edit an Image)
画像をアップロードし、「雪景色にする」「サングラスを追加する」「車を赤くする」のような編集内容をテキストで入力すると、編集済みの画像が返されます。このアプリ全体は、Hugging Face Inference Providers経由でQwen-Image-Editを呼び出す単一のノードで構成されています。
複数モデルを連携させたメディアスタジオ(Pipeline Chain)
1つのグラフの中に3つのパイプラインが含まれる例です。プロンプトから出発し、FLUXで画像を生成したのち、背景除去を行うGradio Spaceに渡してステッカーに変換します。また、あるトピックはテキスト読み上げ(text-to-speech)のGradio Spaceを通じてナレーション音声になり、同じトピックがLLM呼び出しを通じて、印象に残るエピソードタイトルにもなります。これは1つのキャンバスの中で、Hugging Face Inference Providers経由のモデル呼び出しが2回、Gradio Spaceへの呼び出しが2回行われる構成です。
これはワークフローであるため、3つの出力それぞれが独自のRESTエンドポイント(/sticker、/voiceover、/episode_title)を持ちます。これにより、UIを開かなくてもコードから直接それぞれを呼び出せます。コードからの呼び出し例は後述の「コードから呼び出す」セクションで示されています。
並列での画像生成ファンアウト(Generative Art Lab)
1つのアイデアを入力すると、一度に複数の生成アートワークが作られます。具体的には、FLUXによるベース画像、そのベース画像をもとにした2種類のAI再解釈(水彩風バージョンとネオン・サイバーパンク風バージョン)、そしてLLMが書いたギャラリータイトルです。各画像はInference Providersを使うモデルノードによってプロンプトから直接生成され、タイトルはLLMを呼び出すfnノードから生成されます。これは、1つのアイデアが複数のオペレーターに同時に供給され、すべてが並列に生成される「ファンアウト(fan-out)」パターンの実例です。
Hugging Faceデータセットのプロファイリング(Data Detective)
stanfordnlp/imdb や mteb/tweet_sentiment_extraction のようなHugging FaceのデータセットIDを入力すると、単一の入力が4つのオペレーターノードにファンアウトし、Datasets Server APIを使ってデータセットをライブで解析します。得られるのは、概要カード、先頭数行のプレビュー、列ごとの統計情報、分布チャートで、これらはすべて独立して並列に計算されます。
自前のGPUモデルを実行する(ZeroGPU Animator)
これまでのノードはすべてHugging Faceに処理を依頼するものでしたが、fnノードは単なるPythonであるため、Space内のGPU上でモデルを実行することもできます。バインドする関数に @spaces.GPU を付与すると、そのノードが実行される際にZeroGPUがGPUを確保し、モデルを実行したのちGPUを解放します。Inference Providersや既存のGradio Spaceに常に依存する必要はありません。紹介されているデモでは、Diffusers経由で読み込んだLightricks/LTX-Videoを使い、静止画をアニメーション化する処理が、1つのノードの中だけで完結して実行されます。gr.Workflowはユーザーのgpu設定について何も知る必要がなく、単にバインドされた関数を呼び出すだけです。
仕組みの概要
すべてのワークフローは3種類のノードを持つグラフです。
- reference(参照):入力
- operator(オペレーター):処理を行うステップ
- subject(サブジェクト):出力
オペレーターには、自分で書いたPython関数、Hugging Face Inference Providers上のモデル、別のGradio Space、Hubデータセットの行、のいずれかを指定できます。型付きのポート同士をドラッグでつないでRunを実行すると、各結果がその場に表示されます。
コードから呼び出す
作成したワークフローはすべて、追加の作業なしにそのままAPIになります。各出力は、ラベルにちなんで名付けられたRESTエンドポイントになり、Gradioクライアントを使ってPythonから呼び出せます。以下は、マルチエンドポイントのデモSpaceに対する、トークン不要で動作する実例です。
from gradio_client import Client
client = Client("ysharma/gr-workflow-multi-endpoint-API")
print(client.predict("hello there friend", api_name="/word_count"))
# -> 3
print(client.predict(20, api_name="/fahrenheit"))
# -> 68.0
モデルやSpaceを呼び出すエンドポイントはHugging Faceのトークンが必要なため、クライアント作成時にトークンを渡します。
from gradio_client import Client, handle_file
client = Client("ysharma/gr-workflow-image-editor", token="hf_...")
edited = client.predict(
handle_file("dog.jpg"),
"turn it into a snowy winter scene",
api_name="/edited_image",
)
プレーンなHTTPを使いたい場合は、どのエンドポイントもcurlでアクセスできます。
curl -s https://ysharma-gr-workflow-multi-endpoint-API.hf.space/gradio_api/call/word_count \
-H "Content-Type: application/json" -d '{"data": ["hello there friend"]}'
自分で作ってみる
最も手早い方法は、上記のいずれかのデモを開いてDuplicateをクリックし、そこからノードの配線を変更していくことです。Pythonからは、次のように短く記述できます。
import gradio as gr
def your_function(text: str) -> str:
pass
gr.Workflow(bind=[your_function]).launch()
オペレーターの種類、JSONスキーマ、再利用可能なパターンを含む詳しい説明は、Gradioドキュメント内の公式gr.Workflowガイドに記載されています。
記事では、gr.Workflowを使えばAUTOMATIC1111のような複雑なものも構築できるとされており、それを段階的に構築する方法を解説する続編記事が予告されています。
tags省略