Skip to content

サブグラフの作成と設定

以下のセクションでは、エージェントワークフロー用のサブグラフを作成する際のコードテンプレートと一般的なパターンについて説明します。

基本的なサブグラフの作成

カスタムサブグラフは通常、以下のパターンを使用して作成されます。

  • 特定のツール選択戦略を持つサブグラフ:

  • 特定のツールリスト(定義されたツールレジストリからのツールのサブセット)を持つサブグラフ:

パラメータおよびパラメータ値の詳細については、subgraph APIリファレンスを参照してください。ツールの詳細については、ツールを参照してください。

以下のコードサンプルは、カスタムサブグラフの実際の実装を示しています。

kotlin
strategy<String, String>("my-strategy") {
   val mySubgraph by subgraph<String, String>(
      tools = listOf(firstTool, secondTool)
   ) {
        // Define nodes and edges for this subgraph
        val sendInput by nodeLLMRequest()
        val executeToolCall by nodeExecuteTool()
        val sendToolResult by nodeLLMSendToolResult()

        edge(nodeStart forwardTo sendInput)
        edge(sendInput forwardTo executeToolCall onToolCall { true })
        edge(executeToolCall forwardTo sendToolResult)
        edge(sendToolResult forwardTo nodeFinish onAssistantMessage { true })
    }
}

サブグラフでのツールの設定

ツールは、いくつかの方法でサブグラフに設定できます。

  • サブグラフの定義内で直接:

    kotlin
    val mySubgraph by subgraph<String, String>(
       tools = listOf(AskUser)
     ) {
        // Subgraph definition
     }
  • ツールレジストリから:

    kotlin
    val mySubgraph by subgraph<String, String>(
        tools = listOf(toolRegistry.getTool("AskUser"))
    ) {
        // Subgraph definition
    }
  • 実行時に動的に:

    kotlin
    // ツールのセットを作成します
    this.llm.writeSession {
        tools = tools.filter { it.name in listOf("first_tool_name", "second_tool_name") }
    }

高度なサブグラフのテクニック

マルチパート戦略

複雑なワークフローは複数のサブグラフに分割でき、それぞれがプロセスの特定の部分を処理します。

kotlin
strategy("complex-workflow") {
   val inputProcessing by subgraph<String, A>(
   ) {
      // 初期入力を処理します
   }

   val reasoning by subgraph<A, B>(
   ) {
      // 処理された入力に基づいて推論を実行します
   }

   val toolRun by subgraph<B, C>(
      // ツールレジストリからのオプションのツールサブセット
      tools = listOf(firstTool, secondTool)
   ) {
      // 推論に基づいてツールを実行します
   }

   val responseGeneration by subgraph<C, String>(
   ) {
      // ツールの結果に基づいて応答を生成します
   }

   nodeStart then inputProcessing then reasoning then toolRun then responseGeneration then nodeFinish

}

ベストプラクティス

サブグラフを操作する際は、以下のベストプラクティスに従ってください。

  1. 複雑なワークフローをサブグラフに分割する:各サブグラフは明確で集中した責任を持つべきです。

  2. 必要なコンテキストのみを渡す:後続のサブグラフが正しく機能するために必要な情報のみを渡します。

  3. サブグラフの依存関係を文書化する:各サブグラフが前のサブグラフから何を期待し、後続のサブグラフに何を提供するのかを明確に文書化します。

  4. サブグラフを単独でテストする:各サブグラフを戦略に統合する前に、様々な入力で正しく動作することを確認します。

  5. トークン使用量を考慮する:特にサブグラフ間で大量の履歴を渡す場合は、トークン使用量を意識してください。

トラブルシューティング

ツールが利用できない

サブグラフでツールが利用できない場合:

  • ツールがツールレジストリに正しく登録されていることを確認してください。

サブグラフが定義された期待される順序で実行されない

サブグラフが定義された順序で実行されない場合:

  • サブグラフが正しい順序でリストされていることを確認するために、戦略の定義をチェックしてください。
  • 各サブグラフがその出力を次のサブグラフに正しく渡していることを確認してください。
  • サブグラフが残りのサブグラフと接続されており、開始(および終了)から到達可能であることを確認してください。条件付きエッジには注意し、サブグラフやノードでブロックされないように、考えられるすべての条件をカバーするようにしてください。

以下の例は、サブグラフを使用して実際のシナリオでエージェント戦略を作成する方法を示しています。 このコードサンプルには、researchSubgraphplanSubgraphexecuteSubgraphという3つの定義済みサブグラフが含まれており、各サブグラフはアシスタントフロー内で定義された個別の目的を持っています。

kotlin
// エージェント戦略を定義します
val strategy = strategy<String, String>("assistant") {
    // ツール呼び出しを含むサブグラフ

    val researchSubgraph by subgraph<String, String>(
        "research_subgraph",
        tools = listOf(WebSearchTool())
    ) {
        val nodeCallLLM by nodeLLMRequest("call_llm")
        val nodeExecuteTool by nodeExecuteTool()
        val nodeSendToolResult by nodeLLMSendToolResult()

        edge(nodeStart forwardTo nodeCallLLM)
        edge(nodeCallLLM forwardTo nodeExecuteTool onToolCall { true })
        edge(nodeExecuteTool forwardTo nodeSendToolResult)
        edge(nodeSendToolResult forwardTo nodeExecuteTool onToolCall { true })
        edge(nodeCallLLM forwardTo nodeFinish onAssistantMessage { true })
    }

    val planSubgraph by subgraph(
        "plan_subgraph",
        tools = listOf()
    ) {
        val nodeUpdatePrompt by node<String, Unit> { research ->
            llm.writeSession {
                rewritePrompt {
                    prompt("research_prompt") {
                        system(
                            "問題と、それを解決するための調査結果が与えられます。" +
                                    "与えられたタスクを解決するための計画を段階的に作成してください。"
                        )
                        user("Research: $research")
                    }
                }
            }
        }
        val nodeCallLLM by nodeLLMRequest("call_llm")

        edge(nodeStart forwardTo nodeUpdatePrompt)
        edge(nodeUpdatePrompt forwardTo nodeCallLLM transformed { "Task: $agentInput" })
        edge(nodeCallLLM forwardTo nodeFinish onAssistantMessage { true })
    }

    val executeSubgraph by subgraph<String, String>(
        "execute_subgraph",
        tools = listOf(DoAction(), DoAnotherAction()),
    ) {
        val nodeUpdatePrompt by node<String, Unit> { plan ->
            llm.writeSession {
                rewritePrompt {
                    prompt("execute_prompt") {
                        system(
                            "タスクと、それを実行するための詳細な計画が与えられます。" +
                                    "関連するツールを呼び出して実行してください。"
                        )
                        user("Execute: $plan")
                        user("Plan: $plan")
                    }
                }
            }
        }
        val nodeCallLLM by nodeLLMRequest("call_llm")
        val nodeExecuteTool by nodeExecuteTool()
        val nodeSendToolResult by nodeLLMSendToolResult()

        edge(nodeStart forwardTo nodeUpdatePrompt)
        edge(nodeUpdatePrompt forwardTo nodeCallLLM transformed { "Task: $agentInput" })
        edge(nodeCallLLM forwardTo nodeExecuteTool onToolCall { true })
        edge(nodeExecuteTool forwardTo nodeSendToolResult)
        edge(nodeSendToolResult forwardTo nodeExecuteTool onToolCall { true })
        edge(nodeCallLLM forwardTo nodeFinish onAssistantMessage { true })
    }

    nodeStart then researchSubgraph then planSubgraph then executeSubgraph then nodeFinish
}