Freigeben über


Erweiterte Themen der semantischen Orchestrierung von Kernel-Agenten

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.

Laufzeit

Die Laufzeit ist die grundlegende Komponente, die den Lebenszyklus, die Kommunikation und die Ausführung von Agenten und Orchestrierungen verwaltet. Sie fungiert als Nachrichtenbus und Ausführungsumgebung für alle Akteure (Agenten und orchestrierungsspezifische Akteure) im System.

Rolle der Laufzeit

  • Nachrichtenweiterleitung: Die Laufzeit ist für die Übermittlung von Nachrichten zwischen Agents und Orchestrierungsakteuren verantwortlich, wobei je nach Orchestrierungsmuster ein Pub-Sub- oder Direct Messaging-Modell verwendet wird.
  • Actor Lifecycle Management: Es erstellt, registriert und verwaltet den Lebenszyklus aller Akteure, die an einer Orchestrierung beteiligt sind, und stellt eine Isolation und ein ordnungsgemäßes Ressourcenmanagement sicher.
  • Ausführungskontext: Die Laufzeit stellt den Ausführungskontext für Orchestrierungen bereit, sodass mehrere Orchestrierungen (und ihre Aufrufe) unabhängig und gleichzeitig ausgeführt werden können.

Beziehung zwischen Laufzeit und Orchestrierung

Stellen Sie sich eine Orchestrierung als Diagramm vor, das definiert, wie Agents miteinander interagieren. Die Laufzeit ist der Motor, der dieses Diagramm ausführt und den Nachrichtenfluss sowie den Lebenszyklus von Agenten verwaltet. Entwickler können dieses Diagramm mehrmals mit unterschiedlichen Eingaben in derselben Laufzeitinstanz ausführen, und die Laufzeit stellt sicher, dass jede Ausführung isoliert und unabhängig ist.

Auszeiten

Wenn eine Orchestrierung aufgerufen wird, wird die Orchestrierung sofort mit einem Handler zurückgegeben, der verwendet werden kann, um das Ergebnis später abzurufen. Dieses asynchrone Muster ermöglicht ein flexibleres und reaktionsfähiges Design, insbesondere in Szenarien, in denen die Orchestrierung sehr lange dauern kann.

Von Bedeutung

Wenn ein Timeout auftritt, wird der Aufruf der Orchestrierung nicht abgebrochen. Die Orchestrierung wird weiterhin im Hintergrund laufen, bis sie abgeschlossen ist. Entwickler können das Ergebnis später noch abrufen.

Entwickler können das Ergebnis eines Orchestrierungsaufrufs später abrufen, indem Sie die GetValueAsync Methode für das Ergebnisobjekt aufrufen. Wenn die Anwendung bereit ist, das Ergebnis zu verarbeiten, kann der Aufruf abgeschlossen sein oder nicht abgeschlossen sein. Daher können Entwickler optional ein Timeout für die GetValueAsync Methode angeben. Wenn die Orchestrierung nicht innerhalb des angegebenen Timeouts abgeschlossen ist, wird eine Timeoutausnahme ausgelöst.

string output = await result.GetValueAsync(TimeSpan.FromSeconds(60));

Wenn die Orchestrierung nicht innerhalb des angegebenen Timeouts abgeschlossen ist, wird eine Timeoutausnahme ausgelöst.

Entwickler können das Ergebnis eines Orchestrierungsaufrufs später abrufen, indem Sie die get Methode für das Ergebnisobjekt aufrufen. Wenn die Anwendung bereit ist, das Ergebnis zu verarbeiten, kann der Aufruf abgeschlossen sein oder nicht abgeschlossen sein. Daher können Entwickler optional ein Timeout für die get Methode angeben. Wenn die Orchestrierung nicht innerhalb des angegebenen Timeouts abgeschlossen ist, wird eine Timeoutausnahme ausgelöst.

value = await orchestration_result.get(timeout=60)

Wenn die Orchestrierung nicht innerhalb des angegebenen Timeouts abgeschlossen ist, wird eine Timeoutausnahme ausgelöst.

Hinweis

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

Human-in-the-Loop

Agent-Antwortrückruf

Um Agentantworten innerhalb eines Aufrufs anzuzeigen, können Entwickler eine ResponseCallback der Orchestrierung übergeben. Auf diese Weise können Entwickler die Antworten jedes Agents während des Orchestrierungsprozesses beobachten. Entwickler können diesen Rückruf für Ui-Updates, Protokollierung oder andere Zwecke verwenden.

public ValueTask ResponseCallback(ChatMessageContent response)
{
    Console.WriteLine($"# {response.AuthorName}\n{response.Content}");
    return ValueTask.CompletedTask;
}

SequentialOrchestration orchestration = new SequentialOrchestration(
    analystAgent, writerAgent, editorAgent)
{
    ResponseCallback = ResponseCallback,
};

Um Agentantworten innerhalb eines Aufrufs zu sehen, können Entwickler ein agent_response_callback in die Orchestrierung einfügen. Auf diese Weise können Entwickler die Antworten jedes Agents während des Orchestrierungsprozesses beobachten. Entwickler können diesen Rückruf für Ui-Updates, Protokollierung oder andere Zwecke verwenden.

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

sequential_orchestration = SequentialOrchestration(
    members=agents,
    agent_response_callback=agent_response_callback,
)

Hinweis

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

Menschliche Reaktionsfunktion

Stellen Sie für Orchestrierungen, die Benutzereingaben unterstützen (z. B. Übergabe und Gruppenchat), eine InteractiveCallback bereit, die eine ChatMessageContent vom Benutzer zurückgibt. Mithilfe dieses Rückrufs können Entwickler benutzerdefinierte Logik implementieren, um Benutzereingaben zu sammeln, z. B. das Anzeigen einer Benutzeroberflächenaufforderung oder die Integration in andere Systeme.

HandoffOrchestration orchestration = new(...)
{
    InteractiveCallback = () =>
    {
        Console.Write("User: ");
        string input = Console.ReadLine();
        return new ChatMessageContent(AuthorRole.User, input);
    }
};

Stellen Sie für Orchestrierungen, die Benutzereingaben unterstützen (z. B. Übergabe und Gruppenchat), eine human_response_function bereit, die eine ChatMessageContent vom Benutzer zurückgibt. Mithilfe dieses Rückrufs können Entwickler benutzerdefinierte Logik implementieren, um Benutzereingaben zu sammeln, z. B. das Anzeigen einer Benutzeroberflächenaufforderung oder die Integration in andere Systeme.

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

handoff_orchestration = HandoffOrchestration(
    ...,
    agent_response_callback=agent_response_callback,
)

Hinweis

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

Strukturierte Daten

Wir glauben, dass strukturierte Daten ein wichtiger Bestandteil der Erstellung agentischer Workflows sind. Mithilfe von strukturierten Daten können Entwickler mehr wiederverwendbare Orchestrierungen erstellen und die Entwicklungserfahrung wird verbessert. Das semantische Kernel-SDK bietet eine Möglichkeit, strukturierte Daten als Eingabe an Orchestrierungen zu übergeben und strukturierte Daten als Ausgabe zurückzugeben.

Von Bedeutung

Intern verarbeiten die Orchestrierungen weiterhin Daten als ChatMessageContent.

Strukturierte Eingaben

Entwickler können strukturierte Daten als Eingabe an Orchestrierungen übergeben, indem sie eine stark typisierte Eingabeklasse verwenden und als generischer Parameter für die Orchestrierung angeben. Dies ermöglicht die Typsicherheit und mehr Flexibilität für Orchestrierungen, um komplexe Datenstrukturen zu verarbeiten. Um z. B. GitHub-Probleme zu triagen, definieren Sie eine Klasse für die strukturierte Eingabe:

public sealed class GithubIssue
{
    public string Id { get; set; } = string.Empty;
    public string Title { get; set; } = string.Empty;
    public string Body { get; set; } = string.Empty;
    public string[] Labels { get; set; } = [];
}

Entwickler können diesen Typ dann als Eingabe für eine Orchestrierung verwenden, indem Sie ihn als generischen Parameter angeben:

HandoffOrchestration<GithubIssue, string> orchestration =
    new(...);

GithubIssue input = new GithubIssue { ... };
var result = await orchestration.InvokeAsync(input, runtime);

Benutzerdefinierte Eingabetransformationen

Standardmäßig verwendet die Orchestrierung die integrierte Eingabetransformation, die das Objekt in JSON serialisiert und in ein ChatMessageContent. Wenn Sie anpassen möchten, wie ihre strukturierte Eingabe in den zugrunde liegenden Nachrichtentyp konvertiert wird, können Sie ihre eigene Eingabetransformationsfunktion über die InputTransform Eigenschaft bereitstellen:

HandoffOrchestration<GithubIssue, string> orchestration =
    new(...)
    {
        InputTransform = (issue, cancellationToken) =>
        {
            // For example, create a chat message with a custom format
            var message = new ChatMessageContent(AuthorRole.User, $"[{issue.Id}] {issue.Title}\n{issue.Body}");
            return ValueTask.FromResult<IEnumerable<ChatMessageContent>>([message]);
        },
    };

Auf diese Weise können Sie genau steuern, wie Ihre eingegebenen Eingaben den Agents angezeigt werden, wodurch erweiterte Szenarien wie benutzerdefinierte Formatierung, Feldauswahl oder Mehrnachrichteneingabe ermöglicht werden.

Tipp

Sehen Sie sich das vollständige Beispiel in Step04a_HandoffWithStructuredInput.cs

Entwickler können strukturierte Daten als Eingabe an Orchestrierungen übergeben, indem sie ein Pydantisches Modell (oder eine beliebige benutzerdefinierte Klasse) als generischen Parameter für die Orchestrierung angeben. Dies ermöglicht die Typsicherheit und ermöglicht es den Orchestrierungen, komplexe Datenstrukturen zu verarbeiten.

Um z. B. GitHub-Probleme zu triagen, definieren Sie ein Pydantisches Modell für die strukturierte Eingabe:

from pydantic import BaseModel

class GithubIssue(BaseModel):
    id: str
    title: str
    body: str
    labels: list[str] = []

Sie können diesen Typ dann als Eingabe für Ihre Orchestrierung verwenden, indem Sie ihn als generischen Parameter angeben:

from semantic_kernel.agents import HandoffOrchestration

def custom_input_transform(input_message: GithubIssue) -> ChatMessageContent:
    return ChatMessageContent(role=AuthorRole.USER, content=f"[{input_message.id}] {input_message.title}\n{input_message.body}")


handoff_orchestration = HandoffOrchestration[GithubIssue, ChatMessageContent](
    ...,
    input_transform=custom_input_transform,
)

GithubIssueSample = GithubIssue(
    id="12345",
    title="Bug: ...",
    body="Describe the bug...",
    labels=[],
)

orchestration_result = await handoff_orchestration.invoke(
    task=GithubIssueSample,
    runtime=runtime,
)

Tipp

Sehen Sie sich das vollständige Beispiel in step4a_handoff_structured_inputs.py

Hinweis

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

Strukturierte Ausgaben

Agents und Orchestrierungen können strukturierte Ausgaben zurückgeben, indem eine streng typisierte Ausgabeklasse als generischer Parameter für die Orchestrierung angegeben wird. Auf diese Weise können Sie mit umfangreichen, strukturierten Ergebnissen in Ihrer Anwendung arbeiten und nicht nur mit Nur-Text.This enables you to work with rich, structured results in your application, rather than just plain text.

Angenommen, Sie möchten einen Artikel analysieren und Themen, Stimmungen und Entitäten extrahieren. Definieren sie eine Klasse für die strukturierte Ausgabe:

public sealed class Analysis
{
    public IList<string> Themes { get; set; } = [];
    public IList<string> Sentiments { get; set; } = [];
    public IList<string> Entities { get; set; } = [];
}

Sie können diesen Typ dann als Ausgabe für Ihre Orchestrierung verwenden, indem Sie ihn als generischen Parameter angeben:

ConcurrentOrchestration<string, Analysis> orchestration =
    new(agent1, agent2, agent3)
    {
        ResultTransform = outputTransform.TransformAsync, // see below
    };

// ...
OrchestrationResult<Analysis> result = await orchestration.InvokeAsync(input, runtime);
Analysis output = await result.GetValueAsync(TimeSpan.FromSeconds(60));

Benutzerdefinierte Ausgabetransformationen

Standardmäßig verwendet die Orchestrierung die integrierte Ausgabetransformation, die versucht, den Antwortinhalt des Dienstes auf Ihren Ausgabetyp zu deserialisieren. Für komplexere Szenarien können Sie eine benutzerdefinierte Ausgabetransformation (z. B. mit strukturierter Ausgabe durch einige Modelle) bereitstellen.

StructuredOutputTransform<Analysis> outputTransform =
    new(chatCompletionService, new OpenAIPromptExecutionSettings { ResponseFormat = typeof(Analysis) });

ConcurrentOrchestration<string, Analysis> orchestration =
    new(agent1, agent2, agent3)
    {
        ResultTransform = outputTransform.TransformAsync,
    };

Mit diesem Ansatz können Sie strukturierte Daten direkt aus der Orchestrierung empfangen und verarbeiten, sodass erweiterte Workflows und Integrationen einfacher erstellt werden können.

Tipp

Sehen Sie sich das vollständige Beispiel in Step01a_ConcurrentWithStructuredOutput.cs

Agents und Orchestrierungen können strukturierte Ausgaben zurückgeben, indem ein Pydantic-Modell (oder eine beliebige benutzerdefinierte Klasse) als generischer Ausgabetyp für die Orchestrierung angegeben wird. Auf diese Weise können Sie mit umfangreichen, strukturierten Ergebnissen in Ihrer Anwendung arbeiten und nicht nur mit Nur-Text.This enables you to work with rich, structured results in your application, rather than just plain text.

Angenommen, Sie möchten einen Artikel analysieren und Themen, Stimmungen und Entitäten extrahieren. Definieren Sie ein Pydantisches Modell für die strukturierte Ausgabe:

from pydantic import BaseModel

class ArticleAnalysis(BaseModel):
    themes: list[str]
    sentiments: list[str]
    entities: list[str]

Sie können diesen Typ dann als Ausgabe für Ihre Orchestrierung verwenden, indem Sie ihn als generischen Parameter angeben und eine Ausgabetransformation angeben:

from semantic_kernel.agents import ConcurrentOrchestration
from semantic_kernel.agents.orchestration.tools import structured_outputs_transform
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion

# `structured_outputs_transform` is a built-in transform that uses the structured output

concurrent_orchestration = ConcurrentOrchestration[str, ArticleAnalysis](
    members=agents,
    output_transform=structured_outputs_transform(ArticleAnalysis, AzureChatCompletion()),
)

...

orchestration_result = await concurrent_orchestration.invoke(
    task="article text",
    runtime=runtime,
)

value = await orchestration_result.get(timeout=20)

# `value` is now an instance of ArticleAnalysis

Mit diesem Ansatz können Sie strukturierte Daten direkt aus der Orchestrierung empfangen und verarbeiten, sodass erweiterte Workflows und Integrationen einfacher erstellt werden können.

Tipp

Sehen Sie sich das vollständige Beispiel in step1a_concurrent_structured_outputs.py

Hinweis

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

Abbruch

Von Bedeutung

Abbruch hindert die Agenten daran, weitere Nachrichten zu verarbeiten, jedoch werden Agenten, die bereits Nachrichten verarbeiten, nicht gestoppt.

Von Bedeutung

Der Abbruch beendet die Laufzeit nicht.

Sie können eine Orchestrierung abbrechen, indem Sie die Cancel Methode für den Ergebnishandler aufrufen. Dadurch wird die Orchestrierung beendet, indem das Signal an alle Agents weitergegeben wird, und sie beenden die Verarbeitung weiterer Nachrichten.

var resultTask = orchestration.InvokeAsync(input, runtime);
resultTask.Cancel();

Entwickler können eine Orchestrierung abbrechen, indem sie die cancel Methode für den Ergebnishandler aufrufen. Dadurch wird die Orchestrierung beendet, indem das Signal an alle Agents weitergegeben wird, und sie beenden die Verarbeitung weiterer Nachrichten.

orchestration_result = await orchestration.invoke(task=task, runtime=runtime)
orchestration_result.cancel()

Hinweis

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

Nächste Schritte

Hinweis

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