Freigeben über


Übergabe-Orchestrierung

Von Bedeutung

Agent Orchestration-Features im Agent Framework befinden sich in der experimentellen Phase. Sie befinden sich in der aktiven Entwicklung und können sich erheblich ändern, bevor sie zur Vorschau- oder Veröffentlichungskandidatenphase wechseln.

Die Handoff-Orchestrierung ermöglicht es Agenten, die Steuerung basierend auf dem Kontext oder der Benutzeranforderung aneinander weiterzugeben. Jeder Agent kann die Unterhaltung einem anderen Agenten mit der entsprechenden Expertise "übergeben", um sicherzustellen, dass der richtige Agent jeden Teil der Aufgabe verarbeitet. Dies ist besonders hilfreich bei Kundensupport, Expertensystemen oder szenarien, die eine dynamische Delegierung erfordern.

Weitere Informationen zum Muster, etwa dazu, wann es in Ihrer Workload eingesetzt oder vermieden werden sollte, finden Sie unter Handoff-Orchestrierung.

Gängige Anwendungsfälle

Ein Kundendienstmitarbeiter bearbeitet eine allgemeine Anfrage und übergibt dann bei Bedarf an einen technischen Experten zur Fehlerbehebung oder an einen Rechnungsmitarbeiter.

Diagramm

Sie lernen Folgendes

  • Definieren von Agenten und deren Übergabeverhältnisse
  • Einrichten einer Handoff-Orchestrierung für dynamisches Agent-Routing
  • Wie man einen Menschen in den Kommunikationsablauf einbezieht

Spezialisierte Agenten definieren

Jeder Agent ist für einen bestimmten Bereich verantwortlich. In diesem Beispiel definieren wir einen Triage-Agent, einen Rückerstattungs-Agent, einen Auftragsstatus-Agent und einen Auftragsrückgabe-Agent. Einige Agents verwenden Plug-Ins zum Verarbeiten bestimmter Aufgaben.

Tipp

Dies ChatCompletionAgent wird hier verwendet, aber Sie können jeden Agenttyp verwenden.

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()));

Einrichten von Übergabebeziehungen

Verwenden Sie OrchestrationHandoffs, um festzulegen, welcher Agent unter welchen Umständen Aufgaben an welchen anderen Agenten weitergeben kann.

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");

Beobachte Agentenantworten

Sie können einen Rückruf erstellen, um Antworten von Agenten zu erfassen, während die Unterhaltung über die ResponseCallback Eigenschaft weiterläuft.

ChatHistory history = [];

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

Mensch in der Rückkopplungsschleife

Ein entscheidendes Merkmal der Übergabe-Orchestrierung ist die Möglichkeit für Menschen, an der Unterhaltung teilzunehmen. Dies wird erreicht, indem ein InteractiveCallback bereitgestellt wird, das aufgerufen wird, wenn ein Agent Eingaben vom Benutzer benötigt. In einer echten Anwendung würde dies den Benutzer zur Eingabe auffordern; in einem Beispiel können Sie eine Warteschlange mit Antworten verwenden.

// 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));
}

Einrichten der Handoff-Orchestrierung

Erstellen Sie ein HandoffOrchestration Objekt, übergeben Sie die Agenten, die Übergabe-Beziehungen und die Rückrufe.

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

Laufzeit starten

Zum Verwalten der Ausführung von Agents ist eine Laufzeit erforderlich. Hier verwenden wir InProcessRuntime und beginnen es, bevor wir die Orchestrierung aufrufen.

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

Aufrufen der Orchestrierung

Rufen Sie die Orchestrierung mit Ihrer anfänglichen Aufgabe auf (z. B. "Ich bin ein Kunde, der Hilfe zu meinen Bestellungen benötigt"). Die Agenten leiten die Unterhaltung nach Bedarf weiter, wobei der Mensch bei Bedarf beteiligt ist.

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

Sammeln von Ergebnissen

Warten Sie, bis die Orchestrierung abgeschlossen ist, und rufen Sie die endgültige Ausgabe ab.

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}");
}

Optional: Beenden der Laufzeit

Beenden Sie nach Abschluss der Verarbeitung die Laufzeit, um Ressourcen zu bereinigen.

await runtime.RunUntilIdleAsync();

Beispielausgabe

# 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?

Tipp

Der vollständige Beispielcode ist hier verfügbar.

Spezialisierte Agenten definieren

Jeder Agent ist für einen bestimmten Bereich verantwortlich. Beispiel:

  • TriageAgent: verarbeitet erste Kundenanfragen und entscheidet, welcher Spezialist einbezogen werden soll.
  • RefundAgent: Verarbeitet Erstattungsanfragen.
  • OrderStatusAgent: Überprüft den Bestellstatus.
  • OrderReturnAgent: Bearbeitet Bestellrücksendungen.

Plug-Ins

Zuerst müssen wir die Plug-Ins definieren, die in den Agents verwendet werden. Diese Plug-Ins enthalten die Logik für die Behandlung bestimmter Aufgaben.

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."

Agenten

Als Nächstes definieren wir die Agents, die diese Plug-Ins verwenden.

Tipp

Dies ChatCompletionAgent wird hier mit Azure OpenAI verwendet, Sie können jedoch jeden Agenttyp oder Modelldienst verwenden.

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()],
)

Definieren von Übergabebeziehungen

Verwenden Sie OrchestrationHandoffs, um festzulegen, welcher Agent unter welchen Umständen Aufgaben an welchen anderen Agenten weitergeben kann.

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",
    )
)

Beobachte Agentenantworten

Sie können einen Rückruf definieren, um die Nachricht jedes Agents zu drucken, während die Unterhaltung fortschreitet.

from semantic_kernel.contents import ChatMessageContent

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

Mensch in der Rückkopplungsschleife

Ein entscheidendes Merkmal der Übergabe-Orchestrierung ist die Möglichkeit für Menschen, an der Unterhaltung teilzunehmen. Dies wird erreicht, indem ein human_response_function Rückruf bereitgestellt wird, der aufgerufen wird, wenn ein Agent Eingaben vom Benutzer benötigt.

from semantic_kernel.contents import AuthorRole, ChatMessageContent

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

Einrichten der Handoff-Orchestrierung

Erstellen Sie ein HandoffOrchestration Objekt, übergeben Sie die Agenten, die Übergabe-Beziehungen und die Rückrufe.

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,
)

Laufzeit starten

Starten Sie die Laufzeit, um die Agentausführung zu verwalten.

from semantic_kernel.agents.runtime import InProcessRuntime

runtime = InProcessRuntime()
runtime.start()

Aufrufen der Orchestrierung

Rufen Sie die Orchestrierung mit Ihrer ersten Aufgabe auf (z. B. "Ein Kunde ist in der Leitung"). Die Agenten leiten die Unterhaltung nach Bedarf weiter, wobei der Mensch bei Bedarf beteiligt ist.

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

Sammeln von Ergebnissen

Warten Sie, bis die Orchestrierung abgeschlossen ist.

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

Optional: Beenden der Laufzeit

Beenden Sie nach Abschluss der Verarbeitung die Laufzeit, um Ressourcen zu bereinigen.

await runtime.stop_when_idle()

Beispielausgabe

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.

Tipp

Der vollständige Beispielcode ist hier verfügbar.

Hinweis

Die Agent-Orchestrierung ist noch nicht im Java SDK verfügbar.

Nächste Schritte