Partilhar via


Orquestração do Chat de Grupo

Importante

Os recursos de orquestração de agentes no Agent Framework estão em estágio experimental. Eles estão em desenvolvimento ativo e podem mudar significativamente antes de avançar para o estágio de prévia ou versão candidata.

A orquestração de bate-papo em grupo modela uma conversa colaborativa entre agentes, incluindo opcionalmente um participante humano. Um gerente de chat de grupo coordena o fluxo, determinando qual agente deve responder em seguida e quando solicitar a entrada humana. Esse padrão é poderoso para simular reuniões, debates ou sessões colaborativas de resolução de problemas.

Casos de uso comuns

Agentes que representam diferentes departamentos discutem uma proposta de negócio, com um agente gerente moderando a conversa e envolvendo um humano quando necessário:

diagrama

O que você vai aprender

  • Como definir agentes com funções diferentes para um chat em grupo
  • Como usar um gerenciador de chat de grupo para controlar o fluxo de conversa
  • Como envolver um participante humano na conversa
  • Como observar a conversa e recolher o resultado final

Defina seus agentes

Cada agente no chat de grupo tem uma função específica. Neste exemplo, definimos um redator e um revisor.

Sugestão

O ChatCompletionAgent é usado aqui, mas você pode usar qualquer tipo de agente.

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

Opcional: Observe as respostas do agente

Você pode criar um retorno de chamada para capturar as respostas do agente à medida que a sequência progride através da ResponseCallback propriedade.

ChatHistory history = [];

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

Configurar a orquestração do chat de grupo

Crie um objeto GroupChatOrchestration, passando os agentes, um gestor de conversas em grupo (aqui, um RoundRobinGroupChatManager) e o callback de resposta. O gerente controla o fluxo — aqui, ele alterna turnos de forma redonda para um determinado número de rodadas.

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

Iniciar o tempo de execução

Um ambiente de execução é necessário para gerir a execução de agentes. Aqui, usamos InProcessRuntime e iniciamos o processo antes de invocar a orquestração.

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

Invoque a orquestração

Invoque a orquestração com a sua tarefa inicial (por exemplo, "Criar um slogan para um novo SUV elétrico..."). Os agentes irão alternar entre si ao responder, refinando o resultado.

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

Recolher Resultados

Aguarde a conclusão da orquestração e recupere a saída final.

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

Opcional: Pare o tempo de execução

Após a conclusão do processamento, pare o tempo de execução para limpar recursos.

await runtime.RunUntilIdleAsync();

Saída de amostra

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

Sugestão

O código de exemplo completo está disponível aqui

Defina seus agentes

Cada agente no chat de grupo tem uma função específica. Neste exemplo:

  • Writer: Cria e edita conteúdo com base no feedback.
  • Revisor: analisa o conteúdo e fornece feedback para melhorias.

Sugestão

O ChatCompletionAgent é utilizado aqui com o Azure OpenAI, contudo, pode-se usar qualquer tipo de agente ou serviço de modelo.

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]

Observar as respostas do agente

Você pode definir um retorno de chamada para imprimir a mensagem de cada agente à medida que a conversa progride.

from semantic_kernel.contents import ChatMessageContent

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

Configurar a orquestração do chat de grupo

Crie um GroupChatOrchestration objeto, passando os agentes, um gerente de chat de grupo (neste caso, um RoundRobinGroupChatManager) e o callback de resposta. O gerente controla o fluxo — aqui, ele alterna turnos de forma redonda para um determinado número de rodadas.

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

Iniciar o tempo de execução

Inicie o ambiente de execução para gerenciar a execução do agente.

from semantic_kernel.agents.runtime import InProcessRuntime

runtime = InProcessRuntime()
runtime.start()

Invoque a orquestração

Invoque a orquestração com a sua tarefa inicial (por exemplo, "Criar um slogan para um novo SUV elétrico..."). Os agentes irão alternar entre si ao responder, refinando o resultado.

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

Recolher Resultados

Aguarde até que a orquestração seja concluída.

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

Opcional: Pare o tempo de execução

Após a conclusão do processamento, pare o tempo de execução para limpar recursos.

await runtime.stop_when_idle()

Saída de amostra

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

Sugestão

O código de exemplo completo está disponível aqui.

Observação

A orquestração de agentes ainda não está disponível no Java SDK.

Personalizar o Gestor de Chat de Grupo

Você pode personalizar o fluxo de bate-papo em grupo implementando o seu próprio GroupChatManager. Isso permite controlar como os resultados são filtrados, como o próximo agente é selecionado e quando solicitar a entrada do usuário ou encerrar o bate-papo.

Por exemplo, pode criar um gestor personalizado ao herdar de GroupChatManager e substituir os seus métodos abstratos.

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

Em seguida, você pode usar seu gerenciador personalizado na orquestração:

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

Sugestão

Um exemplo completo de um gerenciador de bate-papo em grupo personalizado está disponível aqui

Você pode personalizar o fluxo de bate-papo em grupo implementando o seu próprio GroupChatManager. Isso permite controlar como os resultados são filtrados, como o próximo agente é selecionado e quando solicitar a entrada do usuário ou encerrar o bate-papo.

Por exemplo, pode criar um gestor personalizado ao herdar de GroupChatManager e substituir os seus métodos abstratos.

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

Em seguida, você pode usar seu gerenciador personalizado na orquestração:

from semantic_kernel.agents import GroupChatOrchestration

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

Sugestão

Um exemplo completo de um gerenciador de bate-papo em grupo personalizado está disponível aqui

Observação

A orquestração de agentes ainda não está disponível no Java SDK.

Ordem das chamadas de função do Gerenciador de Chat de Grupo

Ao orquestrar um bate-papo em grupo, os métodos do gerente de chat de grupo são chamados em uma ordem específica para cada rodada da conversa:

  1. ShouldRequestUserInput: Verifica se a entrada do usuário (humano) é necessária antes que o próximo agente fale. Se verdadeiro, a orquestração pausa para entrada do usuário. A entrada do usuário é então adicionada ao histórico de bate-papo do gerente e enviada a todos os agentes.
  2. ShouldTerminate: determina se o chat de grupo deve terminar (por exemplo, se um número máximo de rodadas for atingido ou uma condição personalizada for atendida). Caso seja verdadeiro, a orquestração prossegue para a filtragem de resultados.
  3. FilterResults: Chamado apenas se o chat estiver terminando, para resumir ou processar os resultados finais da conversa.
  4. SelectNextAgent: Se o bate-papo não estiver a terminar, seleciona o próximo agente para responder na conversa.

Esta ordem garante que a entrada do utilizador e as condições de término sejam verificadas antes de avançar na conversa, e que os resultados sejam filtrados apenas no final. Você pode personalizar a lógica para cada etapa substituindo os métodos correspondentes em seu gerenciador de chat de grupo personalizado.

Próximos passos