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