Partager via


Orchestration de conversation de groupe

Important

Les fonctionnalités d’orchestration d’agent dans l’infrastructure d’agent sont à l’étape expérimentale. Ils sont en cours de développement actif et peuvent changer considérablement avant de passer à la phase de version préliminaire ou de candidat à la version finale.

L’orchestration de conversation de groupe modélise une conversation collaborative entre les agents, y compris éventuellement un participant humain. Un responsable de conversation de groupe coordonne le flux, déterminant l’agent qui doit répondre ensuite et quand demander une entrée humaine. Ce modèle est puissant pour simuler des réunions, des débats ou des sessions de résolution de problèmes collaboratives.

Pour en savoir plus sur le modèle, par exemple quand utiliser le modèle ou quand éviter le modèle dans votre charge de travail, consultez orchestration de conversation de groupe.

Cas d’usage courants

Les agents représentant différents services discutent d’une proposition d’entreprise, avec un agent responsable modérant la conversation et impliquant un humain si nécessaire :

diagramme

Ce que vous allez apprendre

  • Comment définir des agents avec différents rôles pour une conversation de groupe
  • Comment utiliser un gestionnaire de conversation de groupe pour contrôler le flux de conversation
  • Comment impliquer un participant humain dans la conversation
  • Comment observer la conversation et collecter le résultat final

Définir vos agents

Chaque agent dans la conversation de groupe a un rôle spécifique. Dans cet exemple, nous définissons un rédacteur et un réviseur.

Conseil / Astuce

Il ChatCompletionAgent est utilisé ici, mais vous pouvez utiliser n’importe quel type d’agent.

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,
};

Facultatif : Observer les réponses de l’agent

Vous pouvez créer un rappel pour capturer les réponses de l’agent à mesure que la séquence progresse via la ResponseCallback propriété.

ChatHistory history = [];

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

Configurer l’orchestration de conversation de groupe

Créez un GroupChatOrchestration objet, en passant les agents, un gestionnaire de conversation de groupe (ici, un RoundRobinGroupChatManager) et le rappel de réponse. Le responsable contrôle le flux : ici, il alterne les tours de manière circulaire pour un nombre défini de manches.

GroupChatOrchestration orchestration = new GroupChatOrchestration(
    new RoundRobinGroupChatManager { MaximumInvocationCount = 5 },
    writer,
    editor)
{
    ResponseCallback = responseCallback,
};

Démarrer le runtime

Un runtime est nécessaire pour gérer l’exécution des agents. Ici, nous utilisons InProcessRuntime et démarrons avant d’invoquer l’orchestration.

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

Appeler l’orchestration

Appelez l’orchestration avec votre tâche initiale (par exemple, « Créer un slogan pour un nouveau SUV électrique... »). Les agents vont se relayer en répondant, en affinant le résultat.

var result = await orchestration.InvokeAsync(
    "Create a slogan for a new electric SUV that is affordable and fun to drive.",
    runtime);

Collecter les résultats

Attendez que l'orchestration se termine et récupérez la sortie finale.

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

Facultatif : arrêter le runtime

Une fois le traitement terminé, arrêtez le runtime pour nettoyer les ressources.

await runtime.RunUntilIdleAsync();

Exemple de sortie

# 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.”

Conseil / Astuce

L’exemple de code complet est disponible ici

Définir vos agents

Chaque agent dans la conversation de groupe a un rôle spécifique. Dans cet exemple :

  • Writer : crée et modifie du contenu en fonction des commentaires.
  • Réviseur : passe en revue le contenu et fournit des commentaires pour l’amélioration.

Conseil / Astuce

Il ChatCompletionAgent est utilisé ici avec Azure OpenAI, mais vous pouvez utiliser n’importe quel type d’agent ou service de modèle.

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]

Observer les réponses de l’agent

Vous pouvez définir un rappel pour imprimer le message de chaque agent à mesure que la conversation progresse.

from semantic_kernel.contents import ChatMessageContent

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

Configurer l’orchestration de conversation de groupe

Créez un GroupChatOrchestration objet, en passant les agents, un gestionnaire de conversation de groupe (dans ce cas un RoundRobinGroupChatManager) et le callback de réponse. Le responsable contrôle le flux : ici, il alterne les tours de manière circulaire pour un nombre défini de manches.

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

Démarrer le runtime

Démarrez le runtime pour gérer l’exécution de l’agent.

from semantic_kernel.agents.runtime import InProcessRuntime

runtime = InProcessRuntime()
runtime.start()

Appeler l’orchestration

Appelez l’orchestration avec votre tâche initiale (par exemple, « Créer un slogan pour un nouveau SUV électrique... »). Les agents vont se relayer en répondant, en affinant le résultat.

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

Collecter les résultats

Attendez que l’orchestration se termine.

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

Facultatif : arrêter le runtime

Une fois le traitement terminé, arrêtez le runtime pour nettoyer les ressources.

await runtime.stop_when_idle()

Exemple de sortie

**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!"

Conseil / Astuce

L’exemple de code complet est disponible ici.

Remarque

L’orchestration de l’agent n’est pas encore disponible dans le Kit de développement logiciel (SDK) Java.

Personnaliser le Gestionnaire de conversation de groupe

Vous pouvez personnaliser le flux de conversation de groupe en implémentant votre propre GroupChatManager. Cela vous permet de contrôler la façon dont les résultats sont filtrés, la façon dont l’agent suivant est sélectionné et quand demander l’entrée de l’utilisateur ou mettre fin à la conversation.

Par exemple, vous pouvez créer un gestionnaire personnalisé en héritant de GroupChatManager et en substituant ses méthodes abstraites :

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

Vous pouvez ensuite utiliser votre gestionnaire personnalisé dans l’orchestration :

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

Conseil / Astuce

Un exemple complet d’un gestionnaire de conversation de groupe personnalisé est disponible ici

Vous pouvez personnaliser le flux de conversation de groupe en implémentant votre propre GroupChatManager. Cela vous permet de contrôler la façon dont les résultats sont filtrés, la façon dont l’agent suivant est sélectionné et quand demander l’entrée de l’utilisateur ou mettre fin à la conversation.

Par exemple, vous pouvez créer un gestionnaire personnalisé en héritant de GroupChatManager et en substituant ses méthodes abstraites :

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

Vous pouvez ensuite utiliser votre gestionnaire personnalisé dans l’orchestration :

from semantic_kernel.agents import GroupChatOrchestration

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

Conseil / Astuce

Un exemple complet d’un gestionnaire de conversation de groupe personnalisé est disponible ici

Remarque

L’orchestration de l’agent n’est pas encore disponible dans le Kit de développement logiciel (SDK) Java.

Ordre des appels de fonction du gestionnaire de discussion de groupe

Lors de l’orchestration d’une conversation de groupe, les méthodes du gestionnaire de conversation de groupe sont appelées dans un ordre spécifique pour chaque tour de la conversation :

  1. ShouldRequestUserInput : vérifie si l’entrée utilisateur (humaine) est requise avant que l’agent suivant ne parle. Si c'est vrai, l'orchestration s'interrompt pour obtenir l'entrée de l'utilisateur. L’entrée utilisateur est ensuite ajoutée à l’historique des conversations du responsable et envoyée à tous les agents.
  2. ShouldTerminate: détermine si le chat de groupe doit se terminer (par exemple, si un nombre maximal de tours est atteint ou si une condition personnalisée est remplie). Si c'est vrai, l'orchestration passe au filtrage des résultats.
  3. FilterResults : appelé uniquement si la conversation se termine, pour résumer ou traiter les résultats finaux de la conversation.
  4. SelectNextAgent : si la conversation ne se termine pas, sélectionne l’agent suivant pour répondre à la conversation.

Cet ordre garantit que les conditions d’entrée et d’arrêt de l’utilisateur sont vérifiées avant d’avancer la conversation, et que les résultats sont filtrés uniquement à la fin. Vous pouvez personnaliser la logique pour chaque étape en remplaçant les méthodes correspondantes dans votre gestionnaire de conversation de groupe personnalisé.

Étapes suivantes