Freigeben über


Gruppenchat-Koordination

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.

Gruppenchat-Steuerung modelliert eine kooperative Unterhaltung zwischen Agenten, wobei optional ein menschlicher Teilnehmer einbezogen werden kann. Ein Gruppenchat-Manager koordiniert den Fluss, der bestimmt, welcher Agent als Nächstes reagieren soll und wann menschliche Eingaben angefordert werden sollen. Dieses Muster ist leistungsfähig zum Simulieren von Besprechungen, Debatten oder kollaborativen Problemlösungssitzungen.

Gängige Anwendungsfälle

Agenten, die verschiedene Abteilungen vertreten, besprechen einen Geschäftsvorschlag, wobei ein Manager die Unterhaltung moderiert und bei Bedarf einen Menschen beteiligt:

Diagramm

Sie lernen Folgendes

  • Festlegung von Agenten mit unterschiedlichen Rollen für einen Gruppenchat
  • Verwenden eines Gruppenchat-Managers zur Steuerung des Unterhaltungsflusses
  • Einbeziehen eines menschlichen Teilnehmers in die Unterhaltung
  • So beobachten Sie die Unterhaltung und sammeln das Endergebnis

Definieren Sie Ihre Agenten

Jeder Agent im Gruppenchat hat eine bestimmte Rolle. In diesem Beispiel definieren wir einen Texter und einen Rezensenten.

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.GroupChat;
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;

// Create a kernel with an AI service
Kernel kernel = ...;

ChatCompletionAgent writer = new ChatCompletionAgent {
    Name = "CopyWriter",
    Description = "A copy writer",
    Instructions = "You are a copywriter with ten years of experience and are known for brevity and a dry humor. The goal is to refine and decide on the single best copy as an expert in the field. Only provide a single proposal per response. You're laser focused on the goal at hand. Don't waste time with chit chat. Consider suggestions when refining an idea.",
    Kernel = kernel,
};

ChatCompletionAgent editor = new ChatCompletionAgent {
    Name = "Reviewer",
    Description = "An editor.",
    Instructions = "You are an art director who has opinions about copywriting born of a love for David Ogilvy. The goal is to determine if the given copy is acceptable to print. If so, state that it is approved. If not, provide insight on how to refine suggested copy without example.",
    Kernel = kernel,
};

Optional: Beobachten von Agentantworten

Sie können einen Rückruf erstellen, um Agentantworten zu erfassen, während die Sequenz über die ResponseCallback Eigenschaft voranschreitet.

ChatHistory history = [];

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

Einrichten der Gruppenchat-Orchestrierung

Erstellen Sie ein GroupChatOrchestration Objekt, indem Sie die Agenten, einen Gruppenchat-Manager (hier, einen RoundRobinGroupChatManager) und den Antwortrückruf übergeben. Der Vorgesetzte steuert den Fluss – hier wechselt es in einer Roundrobin-Mode für eine festgelegte Anzahl von Runden.

GroupChatOrchestration orchestration = new GroupChatOrchestration(
    new RoundRobinGroupChatManager { MaximumInvocationCount = 5 },
    writer,
    editor)
{
    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 ersten Aufgabe auf (z. B. "Erstellen Sie einen Slogan für einen neuen elektrischen SUV..."). Die Agents reagieren abwechselnd und verfeinern das Ergebnis.

var result = await orchestration.InvokeAsync(
    "Create a slogan for a new electric SUV that is affordable and fun to drive.",
    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(60));
Console.WriteLine($"\n# RESULT: {text}");
Console.WriteLine("\n\nORCHESTRATION HISTORY");
foreach (ChatMessageContent message in history)
{
    this.WriteAgentChatMessage(message);
}

Optional: Beenden der Laufzeit

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

await runtime.RunUntilIdleAsync();

Beispielausgabe

# RESULT: “Affordable Adventure: Drive Electric, Drive Fun.”


ORCHESTRATION HISTORY

# Assistant - CopyWriter: “Charge Ahead: Affordable Thrills, Zero Emissions.”

# Assistant - Reviewer: The slogan is catchy but it could be refined to better ...

# Assistant - CopyWriter: “Electrify Your Drive: Fun Meets Affordability.”

# Assistant - Reviewer: The slogan captures the essence of electric driving and ...

# Assistant - CopyWriter: “Affordable Adventure: Drive Electric, Drive Fun.”

Tipp

Der vollständige Beispielcode ist hier verfügbar.

Definieren Sie Ihre Agenten

Jeder Agent im Gruppenchat hat eine bestimmte Rolle. In diesem Beispiel:

  • Writer: Erstellt und bearbeitet Inhalte basierend auf Feedback.
  • Prüfer: Überprüft Inhalte und gibt Feedback zur Verbesserung.

Tipp

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

from semantic_kernel.agents import Agent, ChatCompletionAgent
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion

def get_agents() -> list[Agent]:
    writer = ChatCompletionAgent(
        name="Writer",
        description="A content writer.",
        instructions=(
            "You are an excellent content writer. You create new content and edit contents based on the feedback."
        ),
        service=AzureChatCompletion(),
    )
    reviewer = ChatCompletionAgent(
        name="Reviewer",
        description="A content reviewer.",
        instructions=(
            "You are an excellent content reviewer. You review the content and provide feedback to the writer."
        ),
        service=AzureChatCompletion(),
    )
    return [writer, reviewer]

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}**\n{message.content}")

Einrichten der Gruppenchat-Orchestrierung

Erstellen Sie ein GroupChatOrchestration Objekt, übergeben Sie die Agenten, einen Gruppenchat-Manager (in diesem Fall ein RoundRobinGroupChatManager) und den Rückruf für die Antwort. Der Vorgesetzte steuert den Fluss – hier wechselt es in einer Roundrobin-Mode für eine festgelegte Anzahl von Runden.

from semantic_kernel.agents import GroupChatOrchestration, RoundRobinGroupChatManager

agents = get_agents()
group_chat_orchestration = GroupChatOrchestration(
    members=agents,
    manager=RoundRobinGroupChatManager(max_rounds=5),  # Odd number so writer gets the last word
    agent_response_callback=agent_response_callback,
)

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. "Erstellen Sie einen Slogan für einen neuen elektrischen SUV..."). Die Agents reagieren abwechselnd und verfeinern das Ergebnis.

orchestration_result = await group_chat_orchestration.invoke(
    task="Create a slogan for a new electric SUV that is affordable and fun to drive.",
    runtime=runtime,
)

Sammeln von Ergebnissen

Warten Sie, bis die Orchestrierung abgeschlossen ist.

value = await orchestration_result.get()
print(f"***** Final Result *****\n{value}")

Optional: Beenden der Laufzeit

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

await runtime.stop_when_idle()

Beispielausgabe

**Writer**
"Drive Tomorrow: Affordable Adventure Starts Today!"
**Reviewer**
This slogan, "Drive Tomorrow: Affordable Adventure Starts Today!", effectively communicates the core attributes...
**Writer**
"Embrace the Future: Your Affordable Electric Adventure Awaits!"
**Reviewer**
This revised slogan, "Embrace the Future: Your Affordable Electric Adventure Awaits!", further enhances the message...
**Writer**
"Feel the Charge: Adventure Meets Affordability in Your New Electric SUV!"
***** Result *****
"Feel the Charge: Adventure Meets Affordability in Your New Electric SUV!"

Tipp

Der vollständige Beispielcode ist hier verfügbar.

Hinweis

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

Anpassen des Gruppenchat-Managers

Sie können den Gruppenchatablauf anpassen, indem Sie Ihr eigenes GroupChatManager implementieren. Auf diese Weise können Sie steuern, wie Ergebnisse gefiltert werden, wie der nächste Agent ausgewählt wird und wann Benutzereingaben angefordert oder der Chat beendet werden soll.

Sie können beispielsweise einen benutzerdefinierten Manager erstellen, indem Sie die GroupChatManager abstrakten Methoden erben und außer Kraft setzen:

using Microsoft.SemanticKernel.Agents.Orchestration.GroupChat;
using Microsoft.SemanticKernel.ChatCompletion;
using System.Threading;
using System.Threading.Tasks;

public class CustomGroupChatManager : GroupChatManager
{
    public override ValueTask<GroupChatManagerResult<string>> FilterResults(ChatHistory history, CancellationToken cancellationToken = default)
    {
        // Custom logic to filter or summarize chat results
        return ValueTask.FromResult(new GroupChatManagerResult<string>("Summary") { Reason = "Custom summary logic." });
    }

    public override ValueTask<GroupChatManagerResult<string>> SelectNextAgent(ChatHistory history, GroupChatTeam team, CancellationToken cancellationToken = default)
    {
        // Randomly select an agent from the team
        var random = new Random();
        int index = random.Next(team.Members.Count);
        string nextAgent = team.Members[index].Id;
        return ValueTask.FromResult(new GroupChatManagerResult<string>(nextAgent) { Reason = "Custom selection logic." });
    }

    public override ValueTask<GroupChatManagerResult<bool>> ShouldRequestUserInput(ChatHistory history, CancellationToken cancellationToken = default)
    {
        // Custom logic to decide if user input is needed
        return ValueTask.FromResult(new GroupChatManagerResult<bool>(false) { Reason = "No user input required." });
    }

    public override ValueTask<GroupChatManagerResult<bool>> ShouldTerminate(ChatHistory history, CancellationToken cancellationToken = default)
    {
        // Optionally call the base implementation to check for default termination logic
        var baseResult = base.ShouldTerminate(history, cancellationToken).Result;
        if (baseResult.Value)
        {
            // If the base logic says to terminate, respect it
            return ValueTask.FromResult(baseResult);
        }

        // Custom logic to determine if the chat should terminate
        bool shouldEnd = history.Count > 10; // Example: end after 10 messages
        return ValueTask.FromResult(new GroupChatManagerResult<bool>(shouldEnd) { Reason = "Custom termination logic." });
    }
}

Dann können Sie Ihren benutzerdefinierten Manager in der Orchestrierung verwenden.

GroupChatOrchestration orchestration = new (new CustomGroupChatManager { MaximumInvocationCount = 5 }, ...);

Tipp

Ein vollständiges Beispiel für einen benutzerdefinierten Gruppenchat-Manager ist hier verfügbar.

Sie können den Gruppenchatablauf anpassen, indem Sie Ihr eigenes GroupChatManager implementieren. Auf diese Weise können Sie steuern, wie Ergebnisse gefiltert werden, wie der nächste Agent ausgewählt wird und wann Benutzereingaben angefordert oder der Chat beendet werden soll.

Sie können beispielsweise einen benutzerdefinierten Manager erstellen, indem Sie die GroupChatManager abstrakten Methoden erben und außer Kraft setzen:

from semantic_kernel.agents import GroupChatManager, BooleanResult, StringResult, MessageResult
from semantic_kernel.contents import ChatMessageContent, ChatHistory

class CustomGroupChatManager(GroupChatManager):
    async def filter_results(self, chat_history: ChatHistory) -> MessageResult:
        # Custom logic to filter or summarize chat results
        summary = "Summary of the discussion."
        return MessageResult(result=ChatMessageContent(role="assistant", content=summary), reason="Custom summary logic.")

    async def select_next_agent(self, chat_history: ChatHistory, participant_descriptions: dict[str, str]) -> StringResult:
        # Randomly select an agent from the participants
        import random
        next_agent = random.choice(list(participant_descriptions.keys()))
        return StringResult(result=next_agent, reason="Custom selection logic.")

    async def should_request_user_input(self, chat_history: ChatHistory) -> BooleanResult:
        # Custom logic to decide if user input is needed
        return BooleanResult(result=False, reason="No user input required.")

    async def should_terminate(self, chat_history: ChatHistory) -> BooleanResult:
        # Optionally call the base implementation to check for default termination logic
        base_result = await super().should_terminate(chat_history)
        if base_result.result:
            return base_result
        # Custom logic to determine if the chat should terminate
        should_end = len(chat_history.messages) > 10  # Example: end after 10 messages
        return BooleanResult(result=should_end, reason="Custom termination logic.")

Dann können Sie Ihren benutzerdefinierten Manager in der Orchestrierung verwenden.

from semantic_kernel.agents import GroupChatOrchestration

group_chat_orchestration = GroupChatOrchestration(manager=CustomGroupChatManager(max_rounds=5), ...)

Tipp

Ein vollständiges Beispiel für einen benutzerdefinierten Gruppenchat-Manager ist hier verfügbar.

Hinweis

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

Reihenfolge der Funktionsaufrufe des Gruppenchat-Verwalters

Beim Orchestrieren eines Gruppenchats werden die Methoden des Gruppenchat-Managers für jede Unterhaltung in einer bestimmten Reihenfolge aufgerufen:

  1. ShouldRequestUserInput: Überprüft, ob Benutzereingaben erforderlich sind, bevor der nächste Agent spricht. Falls wahr, wird die Orchestrierung für die Benutzereingabe angehalten. Die Benutzereingabe wird dann dem Chatverlauf des Vorgesetzten hinzugefügt und an alle Agents gesendet.
  2. ShouldTerminate: Bestimmt, ob der Gruppenchat enden soll (z. B. wenn eine maximale Anzahl von Runden erreicht ist oder eine benutzerdefinierte Bedingung erfüllt ist). Wenn wahr, geht die Orchestrierung zur Ergebnisfilterung über.
  3. FilterResults: Wird nur aufgerufen, wenn der Chat beendet wird, um die endgültigen Ergebnisse der Unterhaltung zusammenzufassen oder zu verarbeiten.
  4. SelectNextAgent: Wenn der Chat nicht beendet wird, wählt den nächsten Agent aus, der in der Unterhaltung antworten soll.

Mit dieser Reihenfolge wird sichergestellt, dass die Benutzereingabe- und Beendigungsbedingungen überprüft werden, bevor sie die Unterhaltung voranbringen, und dass die Ergebnisse nur am Ende gefiltert werden. Sie können die Logik für jeden Schritt anpassen, indem Sie die entsprechenden Methoden im benutzerdefinierten Gruppenchat-Manager überschreiben.

Nächste Schritte