Explorando a colaboração de agentes em AgentChat
Importante
Esta característica encontra-se em fase experimental. Os recursos nesta fase ainda estão em desenvolvimento e sujeitos a alterações antes de avançar para a fase de versão beta ou versão candidata a lançamento.
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 é AgentChat
?
AgentChat
fornece uma estrutura que permite a interação entre vários agentes, mesmo que sejam de tipos diferentes. Isso possibilita que um ChatCompletionAgent
e um OpenAIAssistantAgent
trabalhem juntos dentro da mesma conversa.
AgentChat
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, AgentChat
pode ser subclassificada para dar suporte a cenários personalizados.
Uma dessas subclasses, AgentGroupChat
, oferece uma implementação concreta de AgentChat
, usando uma abordagem baseada em estratégia para gerenciar a dinâmica da conversação.
Criando uma AgentGroupChat
Para criar um AgentGroupChat
, você pode especificar os agentes participantes ou criar um bate-papo vazio e, posteriormente, adicionar participantes do agente. A configuração do Chat-Settings e Strategies também é executada durante AgentGroupChat
inicialização. 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
AgentChat
de comportamento para obter detalhes sobre como configurar _Chat-Settings.
Criando um AgentGroupChat
com um Agent
:
// 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.
Adicionar um Agent
a um AgentGroupChat
:
// 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 AgentGroupChat
AgentChat
suporta dois modos de operação: Single-Turn
e Multi-Turn
. Em single-turn
, um agente específico é designado para fornecer uma resposta. Em multi-turn
, todos os agentes na conversa se revezam na resposta até que um critério de terminaçã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 AgentChat
segue o mesmo padrão de um objeto ChatHistory
.
AgentGroupChat chat = new();
chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, "<message content>"));
chat = AgentGroupChat()
await chat.add_chat_message(message="<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 AgentChat
por meio de uma invocação de turno único, ele é adicionado ao conjunto de agentes elegíveis 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 de vários turnos
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 de agentes e Encerramento do chat, vamos aprofundar nas 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 AgentChat
está sempre acessível, mesmo que as mensagens sejam entregues através 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: OpenAIAssistant
versus ChatCompletionAgent
.)
// 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 AgentGroupChat
comportamento
A colaboração entre agentes para resolver tarefas complexas é um padrão central dos agentes. 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 Definições de Execução.
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 usado para limitar o uso de tokens ao empregar uma estratégia baseada em um KernelFunction
.
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(
kernel=kernel,
name=REVIEWER_NAME,
instructions="<instructions>",
)
agent_writer = ChatCompletionAgent(
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 Terminação dita quando ocorre o turno 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, várias Estratégias de Seleção de concretas predefinidas também estão disponíveis, oferecendo abordagens prontas a usar para definir critérios de término para conversas AgentChat
.
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(
kernel=kernel,
name=REVIEWER_NAME,
instructions="<instructions>",
)
agent_writer = ChatCompletionAgent(
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 AgentGroupChat
ser invocado usando a abordagem de turno único ou multiturno, o estado do AgentGroupChat
é atualizado para indicar que foi concluído quando os critérios de terminação são cumpridos. Isso garante que o sistema reconheça quando uma conversa foi totalmente concluída. Para continuar a usar uma instância AgentGroupChat
após atingir o estado Concluído, esse estado deve ser redefinido para permitir futuras 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 completo da conversação
Quando feito usando um AgentChat
onde um OpenAIAssistant
participou, pode ser necessário excluir o thread de remoto associado ao assistente de .
AgentChat
oferece suporte à redefinição ou limpeza de todo o estado da conversa, incluindo 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 se juntaram ao AgentChat
e deixa o AgentChat
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 uso do AgentGroupChat
para colaboração Agent
, consulte: