次の方法で共有


引き渡しの調整

Von Bedeutung

エージェント フレームワークのエージェント オーケストレーション機能は、試験段階にあります。 これらはアクティブな開発中であり、プレビューまたはリリース候補ステージに進む前に大幅に変更される可能性があります。

ハンドオフ オーケストレーションを使用すると、エージェントはコンテキストまたはユーザー要求に基づいて相互に制御を転送できます。 各エージェントは、適切な専門知識を持つ別のエージェントに会話を "ハンドオフ" し、適切なエージェントがタスクの各部分を処理できるようにします。 これは、カスタマー サポート、エキスパート システム、または動的委任を必要とするあらゆるシナリオで特に役立ちます。

一般的なユース ケース

カスタマー サポート エージェントが一般的な問い合わせを処理した後、トラブルシューティングのために技術専門家エージェントに連絡し、必要に応じて課金エージェントに引き続き連絡します。

ダイアグラム

ここでは、次の内容について学習します

  • エージェントとそのハンドオフ関係を定義する方法
  • 動的エージェント ルーティングのハンドオフ オーケストレーションを設定する方法
  • 会話ループに人間を関与させる方法

特殊なエージェントの定義

各エージェントは、特定の領域を担当します。 この例では、トリアージ エージェント、払い戻しエージェント、注文状態エージェント、および注文返品エージェントを定義します。 一部のエージェントでは、プラグインを使用して特定のタスクを処理します。

ヒント

ここでは ChatCompletionAgent を使用しますが、任意の 種類のエージェントを使用できます。

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.Agents.Orchestration;
using Microsoft.SemanticKernel.Agents.Orchestration.Handoff;
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
using Microsoft.SemanticKernel.ChatCompletion;

// Plugin implementations
public sealed class OrderStatusPlugin {
    [KernelFunction]
    public string CheckOrderStatus(string orderId) => $"Order {orderId} is shipped and will arrive in 2-3 days.";
}
public sealed class OrderReturnPlugin {
    [KernelFunction]
    public string ProcessReturn(string orderId, string reason) => $"Return for order {orderId} has been processed successfully.";
}
public sealed class OrderRefundPlugin {
    [KernelFunction]
    public string ProcessReturn(string orderId, string reason) => $"Refund for order {orderId} has been processed successfully.";
}

// Helper function to create a kernel with chat completion
public static Kernel CreateKernelWithChatCompletion(...)
{
    ...
}

ChatCompletionAgent triageAgent = new ChatCompletionAgent {
    Name = "TriageAgent",
    Description = "Handle customer requests.",
    Instructions = "A customer support agent that triages issues.",
    Kernel = CreateKernelWithChatCompletion(...),
};

ChatCompletionAgent statusAgent = new ChatCompletionAgent {
    Name = "OrderStatusAgent",
    Description = "A customer support agent that checks order status.",
    Instructions = "Handle order status requests.",
    Kernel = CreateKernelWithChatCompletion(...),
};
statusAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderStatusPlugin()));

ChatCompletionAgent returnAgent = new ChatCompletionAgent {
    Name = "OrderReturnAgent",
    Description = "A customer support agent that handles order returns.",
    Instructions = "Handle order return requests.",
    Kernel = CreateKernelWithChatCompletion(...),
};
returnAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderReturnPlugin()));

ChatCompletionAgent refundAgent = new ChatCompletionAgent {
    Name = "OrderRefundAgent",
    Description = "A customer support agent that handles order refund.",
    Instructions = "Handle order refund requests.",
    Kernel = CreateKernelWithChatCompletion(...),
};
refundAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderRefundPlugin()));

ハンドオフ リレーションシップを設定する

OrchestrationHandoffsを使用して、どのエージェントがどの状況でどのエージェントに引き渡すことができるかを指定します。

var handoffs = OrchestrationHandoffs
    .StartWith(triageAgent)
    .Add(triageAgent, statusAgent, returnAgent, refundAgent)
    .Add(statusAgent, triageAgent, "Transfer to this agent if the issue is not status related")
    .Add(returnAgent, triageAgent, "Transfer to this agent if the issue is not return related")
    .Add(refundAgent, triageAgent, "Transfer to this agent if the issue is not refund related");

エージェントの応答を観察する

ResponseCallback プロパティを使用して会話が進行するときにエージェントの応答をキャプチャするコールバックを作成できます。

ChatHistory history = [];

ValueTask responseCallback(ChatMessageContent response)
{
    history.Add(response);
    return ValueTask.CompletedTask;
}

人間のループ

ハンドオフ オーケストレーションの主な機能は、人間が会話に参加できることです。 これは、エージェントがユーザーからの入力を必要とするたびに呼び出される InteractiveCallbackを提供することによって実現されます。 実際のアプリケーションでは、ユーザーに入力を求めるメッセージが表示されます。サンプルでは、応答のキューを使用できます。

// Simulate user input with a queue
Queue<string> responses = new();
responses.Enqueue("I'd like to track the status of my order");
responses.Enqueue("My order ID is 123");
responses.Enqueue("I want to return another order of mine");
responses.Enqueue("Order ID 321");
responses.Enqueue("Broken item");
responses.Enqueue("No, bye");

ValueTask<ChatMessageContent> interactiveCallback()
{
    string input = responses.Dequeue();
    Console.WriteLine($"\n# INPUT: {input}\n");
    return ValueTask.FromResult(new ChatMessageContent(AuthorRole.User, input));
}

ハンドオフ オーケストレーションを設定する

エージェント、ハンドオフ リレーションシップ、コールバックを渡して、 HandoffOrchestration オブジェクトを作成します。

HandoffOrchestration orchestration = new HandoffOrchestration(
    handoffs,
    triageAgent,
    statusAgent,
    returnAgent,
    refundAgent)
{
    InteractiveCallback = interactiveCallback,
    ResponseCallback = responseCallback,
};

ランタイムを開始する

エージェントの実行を管理するには、ランタイムが必要です。 ここでは、オーケストレーションを呼び出す前に、 InProcessRuntime を使用して開始します。

InProcessRuntime runtime = new InProcessRuntime();
await runtime.StartAsync();

オーケストレーションを呼び出す

最初のタスクでオーケストレーション(プロセス制御または業務連携)を呼び出します (例: 「私は注文の手助けが必要な顧客です」)。 エージェントは必要に応じて会話をルーティングし、必要に応じて人間を巻き込みます。

string task = "I am a customer that needs help with my orders";
var result = await orchestration.InvokeAsync(task, runtime);

結果の収集

オーケストレーションが完了するのを待ち、最終的な出力を取得します。

string output = await result.GetValueAsync(TimeSpan.FromSeconds(300));
Console.WriteLine($"\n# RESULT: {output}");
Console.WriteLine("\n\nORCHESTRATION HISTORY");
foreach (ChatMessageContent message in history)
{
    // Print each message
    Console.WriteLine($"# {message.Role} - {message.AuthorName}: {message.Content}");
}

省略可能: ランタイムを停止する

処理が完了したら、ランタイムを停止してリソースをクリーンアップします。

await runtime.RunUntilIdleAsync();

サンプル出力

# RESULT: Handled order return for order ID 321 due to a broken item, and successfully processed the return.

ORCHESTRATION HISTORY

# Assistant - TriageAgent: Could you please specify what kind of help you need with your orders? Are you looking to check the order status, return an item, or request a refund?

# Assistant - OrderStatusAgent: Could you please tell me your order ID?

# Assistant - OrderStatusAgent: Your order with ID 123 has been shipped and will arrive in 2-3 days. Anything else I can assist you with?

# Assistant - OrderReturnAgent: I can help you with that. Could you please provide the order ID and the reason you'd like to return it?

# Assistant - OrderReturnAgent: Please provide the reason for returning the order with ID 321.

# Assistant - OrderReturnAgent: The return for your order with ID 321 has been successfully processed due to the broken item. Anything else I can assist you with?

ヒント

完全なサンプル コードについては、こちらを参照してください

特殊なエージェントの定義

各エージェントは、特定の領域を担当します。 例えば次が挙げられます。

  • TriageAgent: 最初の顧客要求を処理し、関連するスペシャリストを決定します。
  • RefundAgent: 払い戻し要求を処理します。
  • OrderStatusAgent: 注文の状態を確認します。
  • OrderReturnAgent: 注文返品を処理します。

プラグイン

まず、エージェントで使用されるプラグインを定義する必要があります。 これらのプラグインには、特定のタスクを処理するためのロジックが含まれます。

from semantic_kernel.functions import kernel_function

class OrderStatusPlugin:
    @kernel_function
    def check_order_status(self, order_id: str) -> str:
        """Check the status of an order."""
        # Simulate checking the order status
        return f"Order {order_id} is shipped and will arrive in 2-3 days."


class OrderRefundPlugin:
    @kernel_function
    def process_refund(self, order_id: str, reason: str) -> str:
        """Process a refund for an order."""
        # Simulate processing a refund
        print(f"Processing refund for order {order_id} due to: {reason}")
        return f"Refund for order {order_id} has been processed successfully."


class OrderReturnPlugin:
    @kernel_function
    def process_return(self, order_id: str, reason: str) -> str:
        """Process a return for an order."""
        # Simulate processing a return
        print(f"Processing return for order {order_id} due to: {reason}")
        return f"Return for order {order_id} has been processed successfully."

エージェント

次に、これらのプラグインを使用するエージェントを定義します。

ヒント

この ChatCompletionAgent は Azure OpenAI で使用されますが、任意の エージェントの種類 または モデル サービスを使用できます。

from semantic_kernel.agents import ChatCompletionAgent
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion

support_agent = ChatCompletionAgent(
    name="TriageAgent",
    description="A customer support agent that triages issues.",
    instructions="Handle customer requests.",
    service=OpenAIChatCompletion(),
)

refund_agent = ChatCompletionAgent(
    name="RefundAgent",
    description="A customer support agent that handles refunds.",
    instructions="Handle refund requests.",
    service=OpenAIChatCompletion(),
    plugins=[OrderRefundPlugin()],
)

order_status_agent = ChatCompletionAgent(
    name="OrderStatusAgent",
    description="A customer support agent that checks order status.",
    instructions="Handle order status requests.",
    service=OpenAIChatCompletion(),
    plugins=[OrderStatusPlugin()],
)

order_return_agent = ChatCompletionAgent(
    name="OrderReturnAgent",
    description="A customer support agent that handles order returns.",
    instructions="Handle order return requests.",
    service=OpenAIChatCompletion(),
    plugins=[OrderReturnPlugin()],
)

ハンドオフ リレーションシップの定義

OrchestrationHandoffsを使用して、どのエージェントがどの状況でどのエージェントに引き渡すことができるかを指定します。

from semantic_kernel.agents import OrchestrationHandoffs

handoffs = (
    OrchestrationHandoffs()
    .add_many(    # Use add_many to add multiple handoffs to the same source agent at once
        source_agent=support_agent.name,
        target_agents={
            refund_agent.name: "Transfer to this agent if the issue is refund related",
            order_status_agent.name: "Transfer to this agent if the issue is order status related",
            order_return_agent.name: "Transfer to this agent if the issue is order return related",
        },
    )
    .add(    # Use add to add a single handoff
        source_agent=refund_agent.name,
        target_agent=support_agent.name,
        description="Transfer to this agent if the issue is not refund related",
    )
    .add(
        source_agent=order_status_agent.name,
        target_agent=support_agent.name,
        description="Transfer to this agent if the issue is not order status related",
    )
    .add(
        source_agent=order_return_agent.name,
        target_agent=support_agent.name,
        description="Transfer to this agent if the issue is not order return related",
    )
)

エージェントの応答を観察する

会話の進行に合わせ、各エージェントのメッセージを出力するコールバックを定義できます。

from semantic_kernel.contents import ChatMessageContent

def agent_response_callback(message: ChatMessageContent) -> None:
    print(f"{message.name}: {message.content}")

人間のループ

ハンドオフ オーケストレーションの主な機能は、人間が会話に参加できることです。 これは、エージェントがユーザーからの入力を必要とするたびに呼び出される human_response_function コールバックを提供することによって実現されます。

from semantic_kernel.contents import AuthorRole, ChatMessageContent

def human_response_function() -> ChatMessageContent:
    user_input = input("User: ")
    return ChatMessageContent(role=AuthorRole.USER, content=user_input)

ハンドオフ オーケストレーションを設定する

エージェント、ハンドオフ リレーションシップ、コールバックを渡して、 HandoffOrchestration オブジェクトを作成します。

from semantic_kernel.agents import HandoffOrchestration

handoff_orchestration = HandoffOrchestration(
    members=[
        support_agent,
        refund_agent,
        order_status_agent,
        order_return_agent,
    ],
    handoffs=handoffs,
    agent_response_callback=agent_response_callback,
    human_response_function=human_response_function,
)

ランタイムを開始する

ランタイムを起動してエージェントの実行を管理します。

from semantic_kernel.agents.runtime import InProcessRuntime

runtime = InProcessRuntime()
runtime.start()

オーケストレーションを呼び出す

最初のタスクでオーケストレーションを呼び出します (例: "顧客がオンラインです")。 エージェントは必要に応じて会話をルーティングし、必要に応じて人間を巻き込みます。

orchestration_result = await handoff_orchestration.invoke(
    task="A customer is on the line.",
    runtime=runtime,
)

結果の収集

オーケストレーションが完了するまで待ちます。

value = await orchestration_result.get()
print(value)

省略可能: ランタイムを停止する

処理が完了したら、ランタイムを停止してリソースをクリーンアップします。

await runtime.stop_when_idle()

サンプル出力

TriageAgent: Hello! Thank you for reaching out. How can I assist you today?
User: I'd like to track the status of my order
OrderStatusAgent: Sure, I can help you with that. Could you please provide me with your order ID?
User: My order ID is 123
OrderStatusAgent: Your order with ID 123 has been shipped and is expected to arrive in 2-3 days. Is there anything else I can assist you with?
User: I want to return another order of mine
OrderReturnAgent: I can help you with returning your order. Could you please provide the order ID for the return and the reason you'd like to return it?
User: Order ID 321
OrderReturnAgent: Please provide the reason for returning the order with ID 321.
User: Broken item
OrderReturnAgent: The return for your order with ID 321 has been successfully processed due to the broken item. Is there anything else I can assist you with?
User: No, bye
Task is completed with summary: Handled order return for order ID 321 due to a broken item, and successfully processed the return.

ヒント

完全なサンプル コードについては、 こちらをご覧ください

エージェント オーケストレーションは、Java SDK ではまだ使用できません。

次のステップ