Exploración de la colaboración de agentes en AgentChat
Importante
Esta característica está en la fase experimental. Las características de esta fase aún están en desarrollo y están sujetas a cambios antes de avanzar a la fase de versión preliminar o candidata para lanzamiento.
La documentación detallada de la API relacionada con esta discusión está disponible en:
Los agentes no están disponibles actualmente en Java.
¿Qué es AgentChat
?
AgentChat
proporciona un marco que permite la interacción entre varios agentes, incluso si son de tipos diferentes. Esto permite que un ChatCompletionAgent
y un OpenAIAssistantAgent
funcionen juntos dentro de la misma conversación.
AgentChat
también define puntos de entrada para iniciar la colaboración entre agentes, ya sea a través de varias respuestas o una respuesta de agente único.
Como clase abstracta, AgentChat
se pueden subclasar para admitir escenarios personalizados.
Una de estas subclase, AgentGroupChat
, ofrece una implementación concreta de AgentChat
, mediante un enfoque basado en estrategia para administrar la dinámica de conversación.
Creación de un AgentGroupChat
Para crear un AgentGroupChat
, puede especificar los agentes participantes o crear un chat vacío y, posteriormente, agregar agentes como participantes. La configuración de Chat-Settings y de Estrategias también se realiza durante la inicialización de AgentGroupChat
. Esta configuración define cómo funcionará la dinámica de conversación dentro del grupo.
Nota: La configuración de chat predeterminada da como resultado una conversación limitada a una única respuesta. Consulte
AgentChat
Comportamiento para obtener más información sobre cómo configurar _Chat-Settings.
Creación de un AgentGroupChat
con un 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])
Los agentes no están disponibles actualmente en Java.
Agregar un Agent
a un 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)
Los agentes no están disponibles actualmente en Java.
Uso de AgentGroupChat
AgentChat
admite dos modos de operación: Single-Turn
y Multi-Turn
. En single-turn
, se designa un agente específico para proporcionar una respuesta. En multi-turn
, todos los agentes de la conversación toman turnos respondiendo hasta que se cumpla un criterio de finalización. En ambos modos, los agentes pueden colaborar respondiendo entre sí para lograr un objetivo definido.
Dar opinión
Agregar un mensaje de entrada a un AgentChat
sigue el mismo patrón que un objeto ChatHistory
.
AgentGroupChat chat = new();
chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, "<message content>"));
chat = AgentGroupChat()
await chat.add_chat_message(message="<message content>")
Los agentes no están disponibles actualmente en Java.
Invocación del agente en un solo turno
En una invocación multiturno, el sistema debe decidir qué agente responde a continuación y cuándo debe finalizar la conversación. En cambio, una invocación de un solo turno simplemente devuelve una respuesta del agente especificado, lo que permite al autor de la llamada administrar directamente la participación del agente.
Una vez que un agente participa en el AgentChat
a través de una invocación de turno único, se agrega al conjunto de agentes aptos para la invocación de múltiples turnos.
// 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)
Los agentes no están disponibles actualmente en Java.
Invocación del agente multiturno
Aunque la colaboración del agente requiere que haya un sistema en vigor que no solo determine qué agente debe responder durante cada turno, sino que también evalúa cuándo la conversación ha alcanzado su objetivo previsto, iniciar la colaboración multiturno sigue siendo sencilla.
Las respuestas del agente se devuelven de forma asincrónica a medida que se generan, lo que permite que la conversación se desarrolle en tiempo real.
Nota: En las secciones siguientes, Selección del Agente y Finalización del Chat, se profundizará en la Configuración de Ejecución en detalle. La configuración de ejecución predeterminada emplea la selección secuencial o round robin y limita la participación del agente a un solo turno.
API de .NET para configuración de ejecución: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)
Los agentes no están disponibles actualmente en Java.
Acceso al historial de chats
El historial de conversaciones AgentChat
siempre es accesible, aunque los mensajes se entreguen a través del patrón de invocación. Esto garantiza que los intercambios anteriores permanezcan disponibles en toda la conversación.
Nota: El mensaje más reciente se proporciona primero (orden descendente: más reciente al más antiguo).
// 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()
Los agentes no están disponibles actualmente en Java.
Dado que diferentes tipos de agente o configuraciones pueden mantener su propia versión del historial de conversaciones, el historial específico del agente también está disponible especificando un agente. (Por ejemplo: OpenAIAssistant
frente a 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)
Los agentes no están disponibles actualmente en Java.
Definición del comportamiento de AgentGroupChat
La colaboración entre agentes para resolver tareas complejas es un patrón agente principal. Para usar este patrón de forma eficaz, un sistema debe estar en vigor que no solo determina qué agente debe responder durante cada turno, sino que también evalúa cuándo la conversación ha alcanzado su objetivo previsto. Esto requiere la administración de la selección del agente y el establecimiento de criterios claros para la terminación de la conversación, lo que garantiza una cooperación sin problemas entre los agentes hacia una solución. Ambos aspectos se rigen por la propiedad de Configuración de Ejecución.
En las secciones siguientes, selección del agente y finalización del chat, se profundizarán en estas consideraciones con detalle.
Selección del agente
En la invocación multiturno, la selección de agentes se guía por una estrategia de selección. Esta estrategia se define mediante una clase base que se puede ampliar para implementar comportamientos personalizados adaptados a necesidades específicas. Para mayor comodidad, también hay disponibles dos estrategias de selección concretas predefinidas, que ofrecen enfoques listos para usar para controlar la selección del agente durante las conversaciones.
Si se conoce, se puede especificar un agente inicial que siempre tome el primer turno. También se puede emplear un reductor de historial para limitar el uso de tokens cuando se usa una estrategia basada en un KernelFunction
.
API de estrategia de selección de .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",
),
)
Los agentes no están disponibles actualmente en Java.
Finalización del chat
En la invocación multiturno, la Estrategia de Terminación determina cuándo tiene lugar el turno final. Esta estrategia garantiza que la conversación finalice en el punto adecuado.
Esta estrategia se define mediante una clase base que se puede ampliar para implementar comportamientos personalizados adaptados a necesidades específicas. Para mayor comodidad, también hay disponibles varias estrategias de selección de predefinidas, que ofrecen enfoques listos para usar para definir criterios de terminación para conversaciones de AgentChat
.
API de estrategia de selección de .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,
),
)
Los agentes no están disponibles actualmente en Java.
Restablecer el estado de finalización del chat
Independientemente de si se invoca AgentGroupChat
mediante el enfoque de un solo turno o multiturno, el estado del AgentGroupChat
se actualiza para indicar que está completado una vez que se cumplen los criterios de terminación. Esto garantiza que el sistema reconozca cuando una conversación haya finalizado completamente. Para seguir usando una instancia de AgentGroupChat
una vez alcanzado el estado Completado, este estado debe restablecerse para permitir interacciones adicionales. Sin restablecer, no será posible realizar interacciones adicionales ni que el agente responda.
En el caso de una invocación de varios turnos que alcance el límite máximo de turnos, el sistema interrumpirá la invocación del agente, pero no marcará la instancia como completada. Esto permite la posibilidad de extender la conversación sin necesidad de restablecer el estado finalización .
// 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
Los agentes no están disponibles actualmente en Java.
Borrar el estado completo de la conversación
Cuando termine de usar un AgentChat
en el que haya participado un OpenAIAssistant
, puede ser necesario eliminar el subproceso remoto asociado con el asistente.
AgentChat
admite restablecer o borrar todo el estado de conversación, lo que incluye eliminar cualquier definición de hilo de remoto. Esto garantiza que no se mantenga ningún dato de conversación residual vinculado al asistente una vez que finalice el chat.
Un restablecimiento completo no elimina los agentes que se habían unido al AgentChat
, y deja el AgentChat
en un estado en el que se puede reutilizar. Esto permite la continuación de las interacciones con los mismos agentes sin necesidad de reinicializarlas, lo que hace que las conversaciones futuras sean más eficaces.
// 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()
Los agentes no están disponibles actualmente en Java.
Procedimiento
Para obtener un ejemplo completo de cómo usar AgentGroupChat
para la colaboración Agent
, consulte: