Explorando a colaboração do agente no bate-papo do agente (experimental)
Aviso
O Semantic Kernel Agent Framework é experimental, ainda está em desenvolvimento e está sujeito a alterações.
A documentação detalhada da API relacionada a esta discussão está disponível em:
Os agentes estão atualmente indisponíveis em Java.
O que é o Agent Chat?
O Agent Chat fornece uma estrutura que permite a interação entre vários agentes, mesmo que sejam de tipos diferentes. Isso torna possível que um Agente de Conclusão de Chat e um Agente Assistente de IA Aberta trabalhem juntos dentro da mesma conversa. O Chat do Agente também define pontos de entrada para iniciar a colaboração entre agentes, seja por meio de várias respostas ou de uma única resposta do agente.
Como uma classe abstrata, o Agent Chat pode ser subclassificado para oferecer suporte a cenários personalizados.
Uma dessas subclasses, Agent Group Chat, oferece uma implementação concreta do Agent Chat, usando uma abordagem baseada em estratégia para gerenciar a dinâmica da conversa.
Criando um bate-papo de grupo de agentes
Para criar um Chat de Grupo de Agente, você pode especificar os agentes participantes ou criar um bate-papo vazio e, posteriormente, adicionar participantes do agente. A configuração das Configurações e Estratégias do Chat também é realizada durante a inicialização do Chat de Grupo do Agente. Essas configurações definem como a dinâmica da conversa funcionará dentro do grupo.
Observação: as configurações de bate-papo padrão resultam em uma conversa limitada a uma única resposta. Consulte Comportamento do bate-papo do agente para obter detalhes sobre como configurar _Chat-Settings.
Criando um bate-papo de grupo de agentes com agentes:
// Define agents
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Create chat with participating agents.
AgentGroupChat chat = new(agent1, agent2);
# Define agents
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Create chat with participating agents
chat = AgentGroupChat(agents=[agent1, agent2])
Os agentes estão atualmente indisponíveis em Java.
Adicionando agentes a um bate-papo de grupo de agentes:
// Define agents
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Create an empty chat.
AgentGroupChat chat = new();
// Add agents to an existing chat.
chat.AddAgent(agent1);
chat.AddAgent(agent2);
# Define agents
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Create an empty chat
chat = AgentGroupChat()
# Add agents to an existing chat
chat.add_agent(agent=agent1)
chat.add_agent(agent=agent2)
Os agentes estão atualmente indisponíveis em Java.
Usando o Chat de Grupo de Agentes
O Agent Chat suporta dois modos de operação: Single-Turn e Multi-Turn. Em turno único, um agente específico é designado para fornecer uma resposta. Em turnos múltiplos, todos os agentes na conversa se revezam respondendo até que um critério de rescisão seja atendido. Em ambos os modos, os agentes podem colaborar respondendo uns aos outros para atingir um objetivo definido.
Fornecendo informações
Adicionar uma mensagem de entrada a um Chat do Agente segue o mesmo padrão de um objeto do Histórico do Chat .
AgentGroupChat chat = new();
chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, "<message content>"));
chat = AgentGroupChat()
await chat.add_chat_message(ChatMessageContent(role=AuthorRole.USER, content="<message content>"))
Os agentes estão atualmente indisponíveis em Java.
Invocação de agente de turno único
Em uma invocação de vários turnos, o sistema deve decidir qual agente responde em seguida e quando a conversa deve terminar. Por outro lado, uma invocação de turno único simplesmente retorna uma resposta do agente especificado, permitindo que o chamador gerencie diretamente a participação do agente.
Depois que um agente participa do Chat do Agente por meio de uma chamada de turno único, ele é adicionado ao conjunto de agentes qualificados para invocação de turno múltiplo.
// Define an agent
ChatCompletionAgent agent = ...;
// Create an empty chat.
AgentGroupChat chat = new();
// Invoke an agent for its response
ChatMessageContent[] messages = await chat.InvokeAsync(agent).ToArrayAsync();
# Define an agent
agent = ChatCompletionAgent(...)
# Create an empty chat
chat = AgentGroupChat()
# Invoke an agent for its response(s)
async for message in chat.invoke(agent)
# process message response(s)
Os agentes estão atualmente indisponíveis em Java.
Invocação de agente multiturno
Embora a colaboração do agente exija a existência de um sistema que não apenas determine qual agente deve responder durante cada turno, mas também avalie quando a conversa atingiu o objetivo pretendido, iniciar a colaboração em vários turnos permanece simples.
As respostas do agente são retornadas de forma assíncrona à medida que são geradas, permitindo que a conversa se desenvolva em tempo real.
Nota: Nas seções a seguir, Seleção do agente e Encerramento do bate-papo, aprofundará as Configurações de execução em detalhes. As Configurações de Execução padrão empregam seleção sequencial ou round-robin e limitam a participação do agente a um único turno.
API de configurações de execução do .NET:AgentGroupChatSettings
// Define agents
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Create chat with participating agents.
AgentGroupChat chat =
new(agent1, agent2)
{
// Override default execution settings
ExecutionSettings =
{
TerminationStrategy = { MaximumIterations = 10 }
}
};
// Invoke agents
await foreach (ChatMessageContent response in chat.InvokeAsync())
{
// Process agent response(s)...
}
# Define agents
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Create chat with participating agents
chat = AgentGroupChat(
agents=[agent1, agent2],
termination_strategy=DefaultTerminationStrategy(maximum_iterations=10),
)
async for response in chat.invoke():
# process agent response(s)
Os agentes estão atualmente indisponíveis em Java.
Aceder ao Histórico de Chat
O histórico de conversas do Chat do Agente está sempre acessível, mesmo que as mensagens sejam entregues por meio do padrão de invocação. Isso garante que as trocas anteriores permaneçam disponíveis durante toda a conversa.
Nota: A mensagem mais recente é fornecida primeiro (ordem decrescente: da mais recente para a mais antiga).
// Define and use a chat
AgentGroupChat chat = ...;
// Access history for a previously utilized AgentGroupChat
ChatMessageContent[] history = await chat.GetChatMessagesAsync().ToArrayAsync();
# Define a group chat
chat = AgentGroupChat(...)
# Access history for a previously utilized AgentGroupChat
history = await chat.get_chat_messages()
Os agentes estão atualmente indisponíveis em Java.
Como diferentes tipos ou configurações de agente podem manter sua própria versão do histórico de conversas, o histórico específico do agente também está disponível especificando um agente. (Por exemplo: Abra o Assistente de IA versus o Agente de Conclusão de Chat.)
// Agents to participate in chat
ChatCompletionAgent agent1 = ...;
OpenAIAssistantAgent agent2 = ...;
// Define a group chat
AgentGroupChat chat = ...;
// Access history for a previously utilized AgentGroupChat
ChatMessageContent[] history1 = await chat.GetChatMessagesAsync(agent1).ToArrayAsync();
ChatMessageContent[] history2 = await chat.GetChatMessagesAsync(agent2).ToArrayAsync();
# Agents to participate in a chat
agent1 = ChatCompletionAgent(...)
agent2 = OpenAIAssistantAgent(...)
# Define a group chat
chat = AgentGroupChat(...)
# Access history for a previously utilized AgentGroupChat
history1 = await chat.get_chat_messages(agent=agent1)
history2 = await chat.get_chat_messages(agent=agent2)
Os agentes estão atualmente indisponíveis em Java.
Definindo o comportamento do bate-papo de grupo do agente
A colaboração entre agentes para resolver tarefas complexas é um padrão agentic central. Para usar esse padrão de forma eficaz, deve existir um sistema que não apenas determine qual agente deve responder durante cada turno, mas também avalie quando a conversa atingiu o objetivo pretendido. Isso requer gerenciar a seleção de agentes e estabelecer critérios claros para o término de conversas, garantindo uma cooperação perfeita entre os agentes em direção a uma solução. Ambos os aspetos são regidos pela propriedade Execution Settings .
As seções a seguir, Seleção de agentes e Encerramento do bate-papo, aprofundarão essas considerações em detalhes.
Seleção de agentes
Na invocação multiturno, a seleção de agentes é guiada por uma Estratégia de Seleção. Essa estratégia é definida por uma classe base que pode ser estendida para implementar comportamentos personalizados adaptados a necessidades específicas. Por conveniência, duas estratégias de seleção concretas predefinidas também estão disponíveis, oferecendo abordagens prontas para uso para lidar com a seleção de agentes durante as conversas.
Se conhecido, pode ser especificado um agente inicial para dar sempre a primeira volta. Um redutor de histórico também pode ser empregado para limitar o uso de token ao usar uma estratégia baseada em uma função do kernel.
API de estratégia de seleção do .NET:
SelectionStrategy
SequentialSelectionStrategy
KernelFunctionSelectionStrategy
Microsoft.SemanticKernel.Agents.History
// Define the agent names for use in the function template
const string WriterName = "Writer";
const string ReviewerName = "Reviewer";
// Initialize a Kernel with a chat-completion service
Kernel kernel = ...;
// Create the agents
ChatCompletionAgent writerAgent =
new()
{
Name = WriterName,
Instructions = "<writer instructions>",
Kernel = kernel
};
ChatCompletionAgent reviewerAgent =
new()
{
Name = ReviewerName,
Instructions = "<reviewer instructions>",
Kernel = kernel
};
// Define a kernel function for the selection strategy
KernelFunction selectionFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Determine which participant takes the next turn in a conversation based on the the most recent participant.
State only the name of the participant to take the next turn.
No participant should take more than one turn in a row.
Choose only from these participants:
- {{{ReviewerName}}}
- {{{WriterName}}}
Always follow these rules when selecting the next participant:
- After {{{WriterName}}}, it is {{{ReviewerName}}}'s turn.
- After {{{ReviewerName}}}, it is {{{WriterName}}}'s turn.
History:
{{$history}}
""",
safeParameterNames: "history");
// Define the selection strategy
KernelFunctionSelectionStrategy selectionStrategy =
new(selectionFunction, kernel)
{
// Always start with the writer agent.
InitialAgent = writerAgent,
// Parse the function response.
ResultParser = (result) => result.GetValue<string>() ?? WriterName,
// The prompt variable name for the history argument.
HistoryVariableName = "history",
// Save tokens by not including the entire history in the prompt
HistoryReducer = new ChatHistoryTruncationReducer(3),
};
// Create a chat using the defined selection strategy.
AgentGroupChat chat =
new(writerAgent, reviewerAgent)
{
ExecutionSettings = new() { SelectionStrategy = selectionStrategy }
};
REVIEWER_NAME = "Reviewer"
WRITER_NAME = "Writer"
agent_reviewer = ChatCompletionAgent(
service_id=REVIEWER_NAME,
kernel=kernel,
name=REVIEWER_NAME,
instructions="<instructions>",
)
agent_writer = ChatCompletionAgent(
service_id=WRITER_NAME,
kernel=kernel,
name=WRITER_NAME,
instructions="<instructions>",
)
selection_function = KernelFunctionFromPrompt(
function_name="selection",
prompt=f"""
Determine which participant takes the next turn in a conversation based on the the most recent participant.
State only the name of the participant to take the next turn.
No participant should take more than one turn in a row.
Choose only from these participants:
- {REVIEWER_NAME}
- {WRITER_NAME}
Always follow these rules when selecting the next participant:
- After user input, it is {WRITER_NAME}'s turn.
- After {WRITER_NAME} replies, it is {REVIEWER_NAME}'s turn.
- After {REVIEWER_NAME} provides feedback, it is {WRITER_NAME}'s turn.
History:
{{{{$history}}}}
""",
)
chat = AgentGroupChat(
agents=[agent_writer, agent_reviewer],
selection_strategy=KernelFunctionSelectionStrategy(
function=selection_function,
kernel=_create_kernel_with_chat_completion("selection"),
result_parser=lambda result: str(result.value[0]) if result.value is not None else COPYWRITER_NAME,
agent_variable_name="agents",
history_variable_name="history",
),
)
Os agentes estão atualmente indisponíveis em Java.
Término do bate-papo
Na invocação de turnos múltiplos, a Estratégia de Rescisão dita quando ocorre a volta final. Essa estratégia garante que a conversa termine no ponto apropriado.
Essa estratégia é definida por uma classe base que pode ser estendida para implementar comportamentos personalizados adaptados a necessidades específicas. Por conveniência, também estão disponíveis Estratégias de Seleção concretas pré-definidas, oferecendo abordagens prontas para uso para definir critérios de término para conversas de Chat de Agente.
API de estratégia de seleção do .NET:
TerminationStrategy
RegexTerminationStrategy
KernelFunctionSelectionStrategy
KernelFunctionTerminationStrategy
AggregatorTerminationStrategy
Microsoft.SemanticKernel.Agents.History
// Initialize a Kernel with a chat-completion service
Kernel kernel = ...;
// Create the agents
ChatCompletionAgent writerAgent =
new()
{
Name = "Writer",
Instructions = "<writer instructions>",
Kernel = kernel
};
ChatCompletionAgent reviewerAgent =
new()
{
Name = "Reviewer",
Instructions = "<reviewer instructions>",
Kernel = kernel
};
// Define a kernel function for the selection strategy
KernelFunction terminationFunction =
AgentGroupChat.CreatePromptFunctionForStrategy(
$$$"""
Determine if the reviewer has approved. If so, respond with a single word: yes
History:
{{$history}}
""",
safeParameterNames: "history");
// Define the termination strategy
KernelFunctionTerminationStrategy terminationStrategy =
new(selectionFunction, kernel)
{
// Only the reviewer may give approval.
Agents = [reviewerAgent],
// Parse the function response.
ResultParser = (result) =>
result.GetValue<string>()?.Contains("yes", StringComparison.OrdinalIgnoreCase) ?? false,
// The prompt variable name for the history argument.
HistoryVariableName = "history",
// Save tokens by not including the entire history in the prompt
HistoryReducer = new ChatHistoryTruncationReducer(1),
// Limit total number of turns no matter what
MaximumIterations = 10,
};
// Create a chat using the defined termination strategy.
AgentGroupChat chat =
new(writerAgent, reviewerAgent)
{
ExecutionSettings = new() { TerminationStrategy = terminationStrategy }
};
REVIEWER_NAME = "Reviewer"
WRITER_NAME = "Writer"
agent_reviewer = ChatCompletionAgent(
service_id=REVIEWER_NAME,
kernel=kernel,
name=REVIEWER_NAME,
instructions="<instructions>",
)
agent_writer = ChatCompletionAgent(
service_id=WRITER_NAME,
kernel=kernel,
name=WRITER_NAME,
instructions="<instructions>",
)
termination_function = KernelFunctionFromPrompt(
function_name="termination",
prompt="""
Determine if the copy has been approved. If so, respond with a single word: yes
History:
{{$history}}
""",
)
chat = AgentGroupChat(
agents=[agent_writer, agent_reviewer],
termination_strategy=KernelFunctionTerminationStrategy(
agents=[agent_reviewer],
function=termination_function,
kernel=_create_kernel_with_chat_completion("termination"),
result_parser=lambda result: str(result.value[0]).lower() == "yes",
history_variable_name="history",
maximum_iterations=10,
),
)
Os agentes estão atualmente indisponíveis em Java.
Redefinindo o estado de conclusão do bate-papo
Independentemente de o Chat de Grupo de Agentes ser invocado usando a abordagem de turno único ou multiturno, o estado do Chat de Grupo de Agentes é atualizado para indicar que ele é concluído assim que os critérios de término forem atendidos. Isso garante que o sistema reconheça quando uma conversa foi totalmente concluída. Para continuar usando uma instância do Chat de Grupo do Agente depois que ela atingir o estado Concluído , esse estado deve ser redefinido para permitir mais interações. Sem a redefinição, interações adicionais ou respostas do agente não serão possíveis.
No caso de uma invocação de várias voltas que atinja o limite máximo de voltas, o sistema interromperá a invocação do agente, mas não marcará a instância como concluída. Isso permite a possibilidade de estender a conversa sem a necessidade de redefinir o estado de conclusão .
// Define an use chat
AgentGroupChat chat = ...;
// Evaluate if completion is met and reset.
if (chat.IsComplete)
{
// Opt to take action on the chat result...
// Reset completion state to continue use
chat.IsComplete = false;
}
# Define a group chat
chat = AgentGroupChat()
# Evaluate if completion is met and reset
if chat.is_complete:
# Reset completion state to continue use
chat.is_complete = False
Os agentes estão atualmente indisponíveis em Java.
Limpar estado de conversação completo
Quando feito usando um Agent Chat onde um Open AI Assistant participou, pode ser necessário excluir o thread remoto associado ao assistente. O Agent Chat suporta a redefinição ou limpeza de todo o estado da conversa, o que inclui a exclusão de qualquer definição de thread remoto. Isso garante que nenhum dado residual da conversa permaneça vinculado ao assistente após a conclusão do bate-papo.
Uma redefinição completa não remove os agentes que ingressaram no Chat do Agente e deixa o Chat do Agente em um estado em que possa ser reutilizado. Isso permite a continuação das interações com os mesmos agentes sem a necessidade de reinicializá-los, tornando as conversas futuras mais eficientes.
// Define an use chat
AgentGroupChat chat = ...;
// Clear the all conversation state
await chat.ResetAsync();
# Define a group chat
chat = AgentGroupChat()
# Clear the conversation state
await chat.reset()
Os agentes estão atualmente indisponíveis em Java.
Procedimentos
Para obter um exemplo completo de como usar o Chat de Grupo de Agentes para colaboração de Agente , consulte: