在 AgentChat
中探索代理协作
重要
此功能处于实验阶段。 此阶段的功能仍处于开发阶段,在升级到预览版或候选发布阶段之前可能会更改。
有关此讨论的详细 API 文档在以下位置提供:
代理当前在 Java 中不可用。
什么是 AgentChat
?
AgentChat
提供了一个框架,可以启用多个代理之间的交互,即使它们属于不同类型的代理。 这使得 ChatCompletionAgent
和 OpenAIAssistantAgent
可以在同一对话中协同工作。
AgentChat
还定义了用于启动代理之间协作的入口点,无论是通过多个响应还是单个代理响应。
作为抽象类,可以对 AgentChat
进行子类化以支持自定义方案。
此类子类 AgentGroupChat
提供了 AgentChat
的具体实现,方法是使用基于策略的方法来管理聊天动态。
创建 AgentGroupChat
若要创建 AgentGroupChat
,可以指定参与代理或创建空聊天,然后添加代理参与者。 配置 聊天设置 和 策略 也会在 AgentGroupChat
初始化期间执行。 这些设置定义会话动态在组中的运行方式。
注意:默认 的聊天设置 会导致限制为单个响应的对话。 有关配置聊天设置的详细信息,请参阅
AgentChat
行为。
使用 AgentGroupChat
创建 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])
代理当前在 Java 中不可用。
将 Agent
添加到 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)
代理当前在 Java 中不可用。
使用 AgentGroupChat
AgentChat
支持两种作模式:Single-Turn
和 Multi-Turn
。 在 single-turn
中,指定特定代理来提供响应。 在 multi-turn
中,会话中的所有代理都会轮流响应,直到满足终止条件。 在这两种模式下,代理可以通过相互响应来实现定义的目标进行协作。
提供输入
将输入消息添加到 AgentChat
遵循与 ChatHistory
对象相同的模式。
AgentGroupChat chat = new();
chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, "<message content>"));
chat = AgentGroupChat()
await chat.add_chat_message(message="<message content>")
代理当前在 Java 中不可用。
单轮次代理调用
在多轮调用中,系统必须决定下一步响应哪个代理以及会话何时结束。 相比之下,单轮调用只是返回来自指定代理的响应,从而允许调用方直接管理代理参与。
代理通过单轮调用参与AgentChat
后,会将它添加到代理集,使其有资格进行多轮调用。
// 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)
代理当前在 Java 中不可用。
多轮次代理调用
虽然代理协作要求必须建立一个系统,不仅确定哪个代理应在每个轮次期间做出响应,而且还会评估会话何时达到其预期目标,启动多轮次协作仍然非常简单。
代理响应在生成时异步返回,从而允许聊天实时展开。
注意:在以下部分中,代理选择 和 聊天终止将详细探讨执行设置。 默认 执行设置 采用顺序或轮循机制选择,并将代理参与限制为单个轮次。
.NET 执行设置 API: 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)
代理当前在 Java 中不可用。
访问聊天历史记录
AgentChat
会话历史记录始终可访问,即使消息是通过调用模式传递的。 这确保了过去的交流在整个对话过程中始终可用。
注意:首先提供最新的消息(降序:最新到最早)。
// 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()
代理当前在 Java 中不可用。
由于不同的代理类型或配置可以维护其自己的会话历史记录版本,因此代理特定的历史记录也可以通过指定代理来使用。 (例如:OpenAIAssistant
与 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)
代理当前在 Java 中不可用。
定义 AgentGroupChat
行为
代理之间的协作来解决复杂的任务是一种核心代理模式。 若要有效地使用此模式,必须建立一个系统,不仅确定哪个代理应在每个轮次期间做出响应,而且还会评估会话何时达到其预期目标。 这需要管理代理选择并建立明确的对话终止标准,确保代理之间实现解决方案的无缝合作。 这两个方面都受 执行设置 属性的约束。
以下部分( 代理选择 和 聊天终止)将详细介绍这些注意事项。
代理选择
在多轮次调用中,代理选择由 选择策略指导。 此策略由可扩展的基类定义,以实现根据特定需求定制的自定义行为。 为方便起见,还提供了两个预定义的具体 选择策略 ,提供现成的方法用于在对话期间处理代理选择。
如果已知,可以指定一个初始代理始终由其执行第一轮。 使用基于KernelFunction
策略时,还可以使用历史化简器来限制令牌使用。
.NET 选择策略 API:
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",
),
)
代理当前在 Java 中不可用。
聊天终止
在多回合调用中,终止策略决定最终回合何时发生。 此策略可确保对话在适当的时间点结束。
此策略由可扩展的基类定义,以实现根据特定需求定制的自定义行为。 为方便起见,还提供了多个预定义的具体 选择策略,提供现成的方法,用于定义 AgentChat
对话的终止条件。
.NET 选择策略 API:
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,
),
)
代理当前在 Java 中不可用。
重置聊天完成状态
无论使用单轮还是多轮方法调用 AgentGroupChat
,一旦满足终止条件,AgentGroupChat
的状态将被更新,以表明它是 完成。 这可确保系统在会话完全结束时识别出这一点。 若要在 AgentGroupChat
状态后继续使用 实例,必须重置此状态才能进一步交互。 如果不重置,将无法进行其他交互或代理响应。
对于达到最大轮次限制的多轮次调用,系统将停止代理调用,但不会将实例 标记为已完成。 这允许扩展会话的可能性,而无需重置 完成 状态。
// 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
代理当前在 Java 中不可用。
清除整个对话的状态
当使用由 AgentChat
参与的 OpenAIAssistant
后,可能需要删除关联到 助手的远程线程 。
AgentChat
支持重置或清除整个会话状态,包括删除任何远程 线程 定义。 这可确保聊天结束后,不会将剩余聊天数据链接到助手。
完全重置不会删除已加入 AgentChat
代理,并将 AgentChat
保留为可以重复使用的状态。 这样就可以继续与同一代理的交互,而无需重新初始化它们,从而使将来的对话更高效。
// 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()
代理当前在 Java 中不可用。
操作说明
有关使用 AgentGroupChat
进行 Agent
协作的端到端示例,请参阅:
-
如何使用
AgentGroupChat
协调代理协作