決定論的ワークフロー vs エージェント型ワークフロー:ショッピングアシスタント構築からの教訓
.png)
Built for Speed: ~10ms Latency, Even Under Load
Blazingly fast way to build, track and deploy your models!
- Handles 350+ RPS on just 1 vCPU — no tuning needed
- Production-ready with full enterprise support
決定論的ワークフロー、エージェント型推論、状態管理における教訓
AIアシスタントの構築は、一見すると単純な問題から始まることが多いものです。ユーザーが質問し、システムが情報を取得し、LLMが応答を生成する。最初のバージョンは通常、驚くほど上手く機能します。
真の課題は、機能が拡張するにつれて現れます。新しいツールやワークフローが導入されると、ユーザーは複数の領域にまたがる質問をするようになります。会話はより長く、より文脈に沿ったものになり、アシスタントは単なるQAボットから、ユーザーが複雑なタスクを完了するのを助けるツールへと変化していきます。
TrueFoundryでは、私たちは会話型ショッピングアシスタントを構築する中で、まさにこの課題に直面しました。このアシスタントは当初、単一製品に関する質問に答えられる製品詳細ページ(PDP)のコンパニオンとして始まりました。時間とともに、製品の発見、取得、レビューの要約、クーポン処理、店舗検索、在庫確認、配送方法の選択、カート操作を処理できるカタログ全体のショッピングアシスタントへと進化しました。
外部機能が大幅に拡張される一方で、最も重要なエンジニアリング上の課題が2つの領域で浮上しました。
- 決定論的ワークフローとエージェント型推論のどちらをいつ使用するかを決定すること。
- 状態管理を単一製品の会話モデルから複数製品のショッピング体験へと進化させること。
1. システムアーキテクチャの概要
ショッピングアシスタントは、パフォーマンス、コスト、信頼性のバランスを取るように設計された4つの主要なアーキテクチャ層に基づいて構築されています。
A. データ層
システムは、構造化ストレージシステムと非構造化ストレージシステムの間で厳格な分離を維持しています。
- 製品カタログ:PostgreSQL (Cloud SQL) に保存されており、製品メタデータ、価格、バリアント、カテゴリ情報、フルフィルメントメタデータが含まれています。
- レビュー:顧客レビューはQdrantに保存されています。これにより、キーワードマッチングのみに頼るのではなく、レビューコンテンツのセマンティックな取得が可能になります。ユーザーが次のようなセマンティックな質問をした場合 「バッテリーの寿命について顧客は何と言っていますか?」、システムは関連するレビューを取得し、証拠に基づいた要約を生成します。
B. データ取り込みパイプライン
カタログデータとレビューデータは、Google Cloud Storage (GCS) を介して継続的に到着し、Google Dataflow パイプラインで処理されます。
- カタログパイプライン: GCS → Dataflow → Cloud SQL (毎日処理されます)。
- レビューパイプライン: GCS → Dataflow → 埋め込み生成 → Qdrant (顧客からの新しいフィードバックのために、日次および時間単位のスケジュールで処理されます)。
C. モデル層
すべてのモデルインタラクションは、 TrueFoundry AI Gatewayを介してルーティングされます。これにより、モデルへの集中アクセス、可観測性、ガバナンス、コスト追跡、レート制限、モデル抽象化が提供されます。アシスタントは、Gemini 2.5 Flash および Qwen モデルを利用して、レイテンシ、品質、運用コストのバランスを取ります。
D. オーケストレーション層
会話ワークフローはLangGraphを使用してオーケストレーションされ、これにより明示的な状態遷移とワークフロー管理が可能になり、決定論的な実行パスとエージェント的な推論の両方をサポートします。
2. 課題1: 決定論的ワークフロー vs. エージェント的ワークフロー
AIシステムにおける一般的な傾向として、LLMが推論できるのであればすべてを処理すべきであるという仮定のもと、すべてを完全にエージェント的にすることです。しかし、本番環境では、純粋なエージェントアプローチはすぐに高価になり、遅くなり、制御が困難になります。
パフォーマンスと意図における明確なトレードオフに基づいて、ショッピングインタラクションを2つの異なる実行パラダイムに分割しました。
内部構造: 実行のメカニズム
これらのフローを分離するというアーキテクチャ上の決定は、主に内部ループ、LLM呼び出しの総数、およびトークン処理のオーバーヘッドによって推進されています。
[ReAct Loop]
--> (1. Complex Tool-Selection Prompt)
--> [Tool Call]
--> (2. Synthesis Prompt)
[Deterministic Flow]
--> [Tool Call]
--> (1. Light Formatting Prompt)
ReActエージェントのライフサイクル (3段階ループ)
複雑なワークフローの場合、専用のReActエージェントが3段階のサイクルを通じて動的に実行を処理します。
- ステップ1: プランニングプロンプト (LLM呼び出し): システムは、利用可能なすべてのツールの定義を含むシステムプロンプトとともに、ユーザーのクエリを渡します。LLMは、ユーザーが何を言ったかを推論し、使用するツールを特定し、そのツールに必要な正確なパラメータを抽出する必要があります。
- ステップ2: ツールの実行: システムは、抽出されたパラメータを使用して、実際のツールまたはAPI呼び出しを実行します。
- ステップ3:観測と統合のプロンプト(LLM呼び出し): 生のツール応答はLLMにフィードバックされます。モデルは、ユーザーの元の質問と照らし合わせてツールの応答を評価し、クリーンで文脈に沿ったユーザー応答に修正します。
決定論的ライフサイクル(2ステップのショートカット)
製品仕様、レビュー、クーポンなどの機能は、ツールの選択や実行順序について推論する必要がありません。パフォーマンスを最適化するため、計画フェーズを完全にスキップします。
- ステップ1:ツール直接実行: 意図分類が既知のツールに直接マッピングされるため、最初のLLMプロンプト呼び出しは完全にスキップされます。システムはツールを即座に実行し、完全な推論サイクルを排除し、ファーストバイトまでの時間を短縮します。
- ステップ2:応答の統合(LLM呼び出し): システムは、生のツールデータとユーザーのクエリを、最終的な回答を整形するための非常に特化したプロンプトに直接渡します。
レイテンシーとプロンプトの複雑さによるペナルティ
呼び出し回数を数えるだけでなく、 複雑さ が応答速度を大きく左右します。
- ReActプロンプトの負担: ReActエージェントのステップ1では、プロンプトは非常に複雑です。LLMは複数のツールを横断的に参照し、実行ロジックを評価し、コンテキストを維持する必要があります。この高い認知的負荷は、トークン処理時間と生成レイテンシーを増加させます。
- 決定論的プロンプトの効率: 決定論的なフローでは、最終的なプロンプトは単純です。 「これが質問で、これが生のツール応答です。回答を生成してください。」 モデルがパスを評価したりツールを追跡したりする必要がないため、トークン生成は高速かつ軽量です。
重要な教訓:基本的なデータクエリにReAct推論ループを強制することは、回答の品質を向上させることなく、不要なレイテンシー、コスト、運用上の複雑さを追加します。相互作用が決定論的に処理できるのであれば、それは そうあるべきです である。
ReActエージェントのガードレール設定
決定論的なパスが機能しなくなる場合(例: 「今日中にこれを入手できますか?」 位置情報の特定、店舗検索、フルフィルメントチェックなど)、ReActエージェントは不可欠です。しかし、完全自律型エージェントは、一貫性のない顧客体験を生み出すことがよくあります。そこで、TrueFoundryは制御を維持するため、動的なエージェント内に構造化されたワークフローステージを実装しました。
- 在庫エージェントのステージ: 位置情報の特定 → 店舗選択 → 在庫確認 → 結果説明
- 購入エージェントのステージ: 製品検証 → 在庫検証 → フルフィルメント選択 → カート操作 → 確認
3. 課題2:状態管理の進化
単一製品ページのアシスタントから、カタログ全体を対象とするショッピングコンパニオンへと進化することは、根本的に状態管理の問題です。
- フェーズ1(単一製品の状態): 製品コンテキストはアクティブなページから暗黙的に導き出されていました。状態モデルは、シンプルでフラットな会話履歴スレッドでした。
- フェーズ2(複数製品の会話): カタログ検索により、ユーザーは複数の製品を同時に紹介、比較、切り替えることができます。
システムの脆弱性を招くことなくスケールするために、状態アーキテクチャは4つの主要な設計原則に基づいて完全に刷新されました。
1. 状態スコープの分離
ユーザーデータと一時的な製品データを混在させると、脆弱なシステムが生まれます。状態は明確な境界にリファクタリングされました。
- ユーザーレベルの状態: ショッピングセッション全体で永続的(例:お気に入りの店舗、位置情報の設定、フルフィルメントの選択)。
- 商品レベルのステート: 特定のアイテム(例:カタログメタデータ、有効なクーポン、レビュー)に紐付けられます。
2. 明示的なコンテキスト追跡 (current_product_id)
当社は、current_product_id をファーストクラスのステート変数として導入することで、商品コンテキストを暗黙的から明示的に変更しました。ユーザーが新しいアイテムに焦点を移すと、この単一のIDを更新するだけで、下流のカタログデータ、レビュー、クーポン、在庫変数が自動的にクリアされ、更新されます。
3. エージェント固有のスレッドメモリ
単一のフラットな conversation_history = [] 配列を維持することは、大量のトークンノイズを引き起こし、モデルのパフォーマンスを低下させました。検索の会話は、最終的なチェックアウト操作とは全く異なるコンテキストウィンドウを必要とします。クロスコンテキスト汚染を最小限に抑えるため、メモリは分離されたエージェントスレッド(検索、在庫、購入、商品)に直接スコープされました。
4. 商品参照解決
グローバルカタログを扱う場合、意図分類だけでは不十分です。ユーザーが 「これは私の近くで利用できますか?」と尋ねた場合、システムは新しく導入された商品参照解決レイヤーに依存し、「これ」がどのアイテムを指すのかを数学的に推論し、クエリがあいまいかどうかを評価し、明確化のプロンプトが必要かどうかを判断します。
主要なアーキテクチャのポイント: ステートは、データドメイン(レビュー、クーポン、商品)ではなく、ワークフロー(検索、在庫、購入)を表すべきです。ユーザーの意図とワークフローの進行を中心にステートを設計することで、オーケストレーションが大幅に簡素化され、マルチエージェント追跡の複雑さが軽減されます。
TrueFoundry AI Gateway delivers ~3–4 ms latency, handles 350+ RPS on 1 vCPU, scales horizontally with ease, and is production-ready, while LiteLLM suffers from high latency, struggles beyond moderate RPS, lacks built-in scaling, and is best for light or prototype workloads.
The fastest way to build, govern and scale your AI


Recent Blogs
Frequently asked questions
When should I use a deterministic workflow instead of a ReAct agent?
Use deterministic workflows when the intent is clear, the tool is known, and the output is predictable, for example, fetching product specs, retrieving coupons, or summarizing reviews. Reserve ReAct agents for multi-step goals where the execution path depends on intermediate results.
How many LLM calls does a ReAct agent use compared to a deterministic flow?
A ReAct loop requires two LLM calls per cycle, one for planning and tool selection, one for synthesis, plus additional cycles if the agent needs to re-evaluate. A deterministic flow skips the planning call entirely, reducing it to a single lightweight synthesis prompt.
How does the system know which product a user is referring to in a multi-product conversation?
A Product Reference Resolution layer evaluates the current state, conversation context, and the current_product_id variable to deduce what item the user means. If the reference is ambiguous, the system triggers a clarification prompt rather than guessing.
Why is agent-specific thread memory important for performance?
A single flat conversation history accumulates irrelevant context across unrelated workflows, increasing token load and degrading model focus. Scoping memory to individual agent threads (Search, Inventory, Purchase) keeps each context window tight and relevant, improving both speed and answer quality.










.webp)












.webp)
.webp)



.webp)





