Difyワークフロー大量実行のコスト最適化とProvisioned Throughputの活用法
Difyで重いワークフローを大量に実行するとAPIコストがどんどん増えていく問題が起こったので解決までの道筋をまとめます。
サマリ
Difyで実行に時間がかかるワークフローを大量に回していたらコストがかかる上に画面上で待機しないとエラーになっていたので解決した話です。
当初1回の実行で$4かかっていたものがモデルの最適化で$2で実行可能に。軽量モデルを採用しているので、実行も高速になりました。
次にGCPのprovisioned-throughputを採用。あらかじめ枠を予約しておくことでコストを固定化する(不足分は従量課金なので調整が重要)ものです。
実際のログでも80%程度を維持できていることが確認できます。
これで1回あたりの実行で$1くらいまで下げられたのでコストは1/4となりました。
provisioned-throughputはGSUという単位で扱われ、1GSUあたりの秒間トークン数が定められています。したがって、このスループット範囲内で実行できる回数をできる限り増やしていけばコストは0に収束していくのです。
解決したかった課題
今回は以下二つの課題解決を狙っていました。
- ワークフローの実行が遅い
- コストが高騰していた
Dify上で複数のLLMノードを含むワークフローを構築していたが、実行完了までに時間がかかりすぎてリアルタイム性が欠如。ユーザーを待たせないようにバックグラウンドで非同期実行できる仕組みが必要でした。
また、LLMを何度も呼び出す構成のため、従量課金が急増。1回の実行あたり約$4かかる状況に。大量実行するとコストが積み上がり、持続不可能な構造になっていた。
目指した状態
最終的に目指したのは、重いAIワークフローをDify上で安定的かつ効率的に大量実行できる仕組みの構築です。まずは、バックグラウンドでも安定して動作するワークフローを整備し、ユーザーを待たせずに処理を完了できる環境の整備が必要です。
次に、1実行あたりのコストを大幅に圧縮し、長期的にも持続可能な運用を実現するため、モデル選定や実行方式、インフラ構成を最適化。スピード・安定性・コストの3点をバランスよく両立し、Difyを基盤としたスケーラブルなAI実行環境の整備が必要となります。
解決策
上記の課題に対し、私たちは以下のような三本柱の解決策を実装しました。
LLMモデルの軽量化による時間・コスト削減
従来使用していた大規模モデルを、Google Cloudの軽量モデル(例: Gemini 2.5 Flash)に置き換えました。これにより応答速度を向上させるとともに、トークン単価を抑えてコストを削減しました
並列実行と直列実行を切り替える仕組み
ワークフローの実行モードを柔軟に制御できるように設計しました。必要に応じて複数のLLM呼び出しを並列に動かし高速化し、反対にコスト重視の場合は呼び出しを直列に順次実行することでリソース使用を平準化しました。
GCP Vertex AIのProvisioned Throughputでコスト固定化
従量課金の代替として、Google Cloudのプロビジョンド・スループット (Provisioned Throughput) を採用しました。あらかじめ一定のスループット容量を月額固定料金で確保することで、月額固定のコスト枠内でワークフローを実行できるようにしました。
これらの取り組みにより、モデルの最適化だけでも1実行あたりの費用を約4ドルから1ドル前後へ半減できました。グラフは100回の実行あたりの累計費用を比較したものです。従来モデルでは100実行で約400ドルかかっていたのが、軽量モデルへの切り替え後は約200ドルに抑えられていることがわかります。実行時間も短縮され、全体として処理速度とコストの両面で大幅な改善が得られました。
解説
ここからは、上記解決策の詳細とその効果について一つひとつ解説します。モデル変更による品質への影響、並列・直列実行のトレードオフ、Provisioned Throughputの仕組みと活用法、そしてDify側の設定変更やセキュリティへの配慮、JSON出力の扱いやすさなど、技術的なポイントを順に見ていきます。
軽量モデルへの切り替えと品質への影響
まず、LLMモデルの軽量化についてです。私たちは当初、高精度だがコストの高いモデルを使用していたため、これをGCPのGemini系の軽量モデルに差し替えました。
具体的にはGemini 2.5 Flashモデルを採用しています。Gemini 2.5 FlashはGoogleの最新LLMファミリーにおいて価格対効果に優れたモデルであり、スピードと性能のバランスが取れているのが特徴です。
公式ドキュメントでも「大規模処理や低遅延が求められる用途に最適」とされており、高い処理速度を維持しつつコストを抑えられる点が大きなメリットです。
モデルを軽量化する際に懸念されるのが出力品質への影響です。
高性能モデルに比べて応答の精度や表現力が低下しないかを検証する必要がありました。私たちは実際にGemini Flashモデルで従来のワークフローを動かし、得られる回答内容を細かくチェックしました。
その結果、回答の論理性や必要十分な情報量は従来モデルと遜色なく維持されていることを確認できました。Gemini Flashは前世代のFlashモデルから品質も向上しており、我々のユースケースにおいては品質低下はほとんど見られませんでした。むしろ応答速度が向上した分だけユーザー体感の性能は上がっています。
以上のように、より軽量なモデルへの切り替えは、品質を維持しつつコストと時間を大幅に削減する有効な手段となりました。モデル選定時には各モデルのトークン単価や性能特性を比較し、要求精度を満たす中で最も費用対効果の高いものを選ぶことが重要です。
最終的にはローカルLLMを活用することで更なるコスト最適化が達成できると考えています。
並列実行と直列実行のトレードオフ
次に、ワークフロー内での並列処理と直列処理の切り替えについて説明します。
Difyでは通常、各ノードが順次実行されますが、工夫次第で複数のLLM呼び出しを同時に実行することも可能です。私たちはワークフローの一部処理をカスタマイズし、必要に応じて並列実行できるようにしました。これにより、例えば複数のリクエストを同時にLLMに投げて結果を待つ、といったことができ、全体の完了までの時間を短縮できます。
※ワークフロー内部でパラレルモードの有効かも行っています
並列実行の利点は、言うまでもなく処理の高速化です。
特にユーザーからのリクエストに対して即座に回答を返したい場合や、一定時間内に多数のタスクを捌かなければならない場合には、並列実行によってスループット(単位時間あたりの処理件数)を向上できます。
ただし並列にLLMを呼び出すということは、その分同時にトークンを消費する量も増えることになります。そのため、従量課金モデルのまま大量の並列実行を行うと、一気に料金が跳ね上がるリスクがあります。並列度を上げれば上げるほど、短時間に消費するトークン量が増え、「スピードとコストがトレードオフ」の関係になる点に注意が必要です。
一方、直列実行(逐次実行)の利点はコストコントロールにあります。
処理を一つずつ順番に実行すれば、常に一つのLLMインスタンスのみが動作している状態となり、瞬間的なトークン消費量を低く抑えられます。これによりピーク時の課金額を平準化でき、特に後述するプロビジョンドスループット環境下では、用意された固定帯域内で無駄なく処理を回すことが可能になります。
ただし当然ながら全体の処理完了までに時間は余計にかかるため、リアルタイム性は犠牲になります。つまり、直列実行は時間と引き換えにコストを最適化する戦略と言えます。
私たちはこの二つをワークフローの設定で動的に切り替えられる仕組みを実装しました。
急ぎの処理が必要なときや、ある程度コストに余裕がある場合には「並列モード」で実行し、コストを最小化したいバッチ処理などは「直列モード」で長時間かけて実行する、といった具合です。具体的にはDifyの環境変数で同時実行数の最大値を変更したり、タスクキューのワーカー数を調整することで並列度をコントロールしています。
例えばAPP_MAX_ACTIVE_REQUESTS
というパラメータを0(無制限)から1に変更すれば、常に1リクエストのみがアクティブになる(実質直列実行)ように制限できます。このようにシナリオに応じて並列・直列を使い分ける柔軟性を持たせることで、要求性能とコスト効率のバランスを取りました。
以下記事も参考になりました。
Provisioned Throughputによるコスト固定化
三つ目の柱が、Provisioned Throughputの活用によるコスト構造の転換です。
従来のLLM利用はAPIの呼び出しごとに課金される従量課金制でしたが、大量実行する場合にはこの方式では実行回数に比例して費用が青天井に増え続けるという問題があります。そ
こでGoogle CloudのVertex AIが提供するプロビジョンドスループットという仕組みを導入しました。
Provisioned Throughputを一言で言えば、「帯域の予約」です。
あらかじめ一定のトークン処理容量(スループット)をGenerative AI Scale Unit (GSU) と呼ばれる単位で購入しておくことで、その範囲内でいくらリクエストを投げても追加料金が発生しません。
例えばGemini 2.5 Flashモデルの場合、1 GSUあたり毎秒数千トークン程度の処理性能が保証されます。その費用は1 GSUあたり月額2,700ドル(1ヶ月契約の場合)と定められており、この金額を支払えばその月は契約したスループット分までは使い放題になるイメージです。
期間契約を長く結べば(3ヶ月や1年契約)、月額はさらに割安になっていきます。
上の図は、Provisioned Throughputを導入してコストを固定化した場合のイメージです。
例えば2 GSUを契約すると月額料金は約5,400ドルになります。この固定費用の範囲内でどれだけワークフローを実行できるかは、ワークフロー1回あたりに消費するトークン数次第ですが、仮に月に3,000~5,000回程度の実行が可能だとすると、1実行あたりの平均コストは約1.08~1.8ドルにまで低減できる計算になります。
従来は1実行4ドルだったものが、モデル最適化により2ドルへ、さらにProvisioned Throughput環境下では約1ドル台まで圧縮できることになります。ポイントは、コストが使用回数に依存しなくなるため、使えば使うほど1回あたりの単価が下がっていく点です。
もっとも、Provisioned Throughputにも注意点があります。
契約したGSU以上の負荷をかけた場合、その超過分はリクエストが抑制されるか、場合によっては従量課金が発生することになります(サービス側の仕様によりますが、基本的には契約容量内で処理を収める設計が求められます)。
したがって、無制限に使い放題というわけではなく、自分たちのユースケースに見合った適切なGSU数を見積もって契約する必要があります。Google提供の計算ツールなどを用いて、想定QPS(秒あたりクエリ数)や1リクエストのトークン量から必要GSUを試算し、契約容量を決定しました。
24時間稼働による「1実行あたりコストゼロ収束」の仕組み
Provisioned Throughputを最大限に活用するため、我々はワークフローを24時間フル稼働させる戦略を取りました。固定で確保したスループット帯域を遊ばせることなく常に使い切ることで、1実行あたりのコストを限りなく0に近づけることが狙いです。
言い換えれば、固定費の中でできるだけ多くの処理件数をこなすことで、単位処理あたりの平均コストを下げるという発想です。
具体的には、直列実行モードで次々とジョブをキューイングし、夜間や非ピーク時間帯も含めてシステムに処理を走らせ続けました。Difyの設定ではデフォルトでワークフロー1件のタイムアウトが20分(1200秒)に定められていますが、私たちはこれを十分長く取る(あるいは実質無制限に近い値に緩和する)設定に変更しました。
環境変数 APP_MAX_EXECUTION_TIME
を調整することで、長時間実行されるバッチ処理でもタイムアウトせず完了できるようにしています。例えばAPP_MAX_EXECUTION_TIME=3600
(1時間)やそれ以上に設定し、必要に応じてさらに長時間の処理も許容することで、重いワークフローでも安心してバックグラウンド実行できる体制を整えました。
上のグラフは、Provisioned Throughput契約下で当社システムがどの程度スループットを利用できているかを示したものです(縦軸は利用率、横軸は時間)。青いラインがGemini 2.5 Flashモデルの使用率で、常に80~100%近い水準で推移していることがわかります。これは契約した帯域をほぼフルに使い切って処理を回している状態を示しています。
一方、参考までに緑のラインはより高性能なProモデルを試験的に併用した際の使用率ですが、こちらはごく短時間しか使っていないため常に低い値に留まっています。青ラインが長時間にわたりほぼ上限近くで安定しているのは、我々のワークフロー処理が24時間絶え間なく実行され、契約したProvisioned Throughputを効率よく消費していることの証左です。
このようにして**「遊休時間を作らない」設計**を行うことで、月額固定コストあたりの処理件数を極限まで引き上げ、1件あたりの計算コストを事実上ゼロに近づけることを実現しました。
Dify設定の調整例(APP_MAX_EXECUTION_TIMEなど)とセキュリティ・出力形式への配慮
技術的な実装面では、Difyの各種設定を我々のユースケース向けに調整しています。
代表的なものが前述したAPP_MAX_EXECUTION_TIME
やAPP_MAX_ACTIVE_REQUESTS
といった環境変数です。デフォルトではワークフロー全体の最大実行時間が1200秒(20分)に制限されていますが、長時間のバッチ処理を可能にするためこの値を拡大しました。
またAPP_MAX_ACTIVE_REQUESTS
は0(無制限)から1に変更し、一度に処理するリクエストを1件に制限することで直列実行モードを徹底しています。これらの設定はDocker環境下では.env
ファイルで指定できます。設定変更後はコンテナを再起動することで反映され、以降はタイムアウトエラーに悩まされることなく安定して長時間のワークフローを実行できるようになりました。
セキュリティ面にも注意を払いました。特にProvisioned Throughputを利用するためにGoogle CloudのサービスアカウントやAPIキーをDifyに設定する必要がありますが、これらの秘密情報は環境変数やVaultで安全に管理し、コード上にハードコーディングしないよう徹底しました。
最後に、JSON形式での出力取り扱いについて言及します。私たちのワークフローでは、LLMからの応答をJSONフォーマットで受け取り、それを解析・保存する処理が含まれています。
DifyはStructured Output(JSONスキーマ)機能を備えており、LLMの応答をあらかじめ定義したJSONスキーマに適合させることができます。軽量モデルへ切り替えたことで出力の傾向が若干変わる可能性も考慮し、このStructured Output機能を活用して出力JSONの整形・バリデーションを行いました。
具体的には、LLMノードに対して期待するJSONスキーマを設定し、応答が厳密にその形式に従うようプロンプト設計とバリデーションを実施しています。その結果、軽量モデルであっても安定して所定のJSON形式で出力が得られるようになり、後段の処理が簡素化されました。
モデル変更後も出力形式の乱れによるエラーは発生しておらず、安心して大量実行に耐えられる状態になっています。
最後に
以上の取り組みを通じて得られた知見として、Dify上で大量のAIワークフローを実行する際には従量課金モデルのままではコスト高騰のリスクが大きいことが改めて明らかになりました。
一度に処理するリクエスト数やトークン量が増えるほど、そのまま料金に跳ね返ってくるためです。特に高性能なLLMを繰り返し呼び出すような設計では、我々が直面したように1実行あたり数ドルにも達し得ます。
しかし、コストは工夫次第でコントロール可能です。軽量モデルへの置き換えやプロンプトの見直しによって1実行あたりのトークン消費量を減らし、並列度を調節して瞬間的な消費を抑えることで、従量課金モデルであってもある程度のコスト削減は可能です。
そして極めつけはProvisioned Throughputの活用による「コスト固定化」のアプローチです。一定の予算内でスループットを予約し、その枠内で処理を回し続けることで、実行回数に依存しない安定したコスト構造を手に入れることができます。
さらに契約帯域をフルに使い倒すことで、限られたコストを最大限の処理件数で割ることができ、1件あたりの費用は理論上限りなく0に近づいていきます。この「コストが0に収束する設計」を目指すことが、大規模実行における鍵だと痛感しました。
総じて、ビジネス上求められる大量実行ニーズに応えるには、技術スタックと課金モデルの両面から最適化を図ることが重要です。Difyは強力なプラットフォームですが、その上でどのようなモデルを選び、どのような実行戦略を採るかによって、得られる成果も運用コストも大きく変わります。
今回ご紹介したように、モデル最適化・実行制御・クラウドサービス活用を組み合わせれば、高速かつ低コストでAIワークフローを24時間回し続けることも十分に可能です。大量実行時のコスト高騰に悩んでいる方は、ぜひ「コストが0に収束する設計」を意識してシステムを見直してみることをお勧めします。私たちの経験がお役に立てば幸いです。
参考資料:
Discussion