重要
代理框架中的代理编排功能处于实验阶段。 它们处于积极开发阶段,在升级到预览版或候选发布阶段之前可能会发生重大变化。
交接编排允许代理根据上下文或用户请求相互转移控制权。 每个代理都可以通过适当的专业知识将对话“移交”到另一个代理,确保正确的代理处理任务的每个部分。 这在客户支持、专家系统或任何需要动态委派的方案中特别有用。
常见用例
客户支持代理处理一般查询,然后移交给技术专家代理进行故障排除,或者根据需要交给计费代理:
学习内容
- 如何定义代理及其移交关系
- 如何为动态代理路由设置转接协调流程
- 如何在对话环节中引入人
定义专用代理
每个代理都负责特定区域。 在此示例中,我们定义了会审代理、退款代理、订单状态代理和订单返回代理。 某些代理使用插件来处理特定任务。
小窍门
在此,使用了 ChatCompletionAgent
,但您可以使用任何 代理类型。
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.Agents.Orchestration;
using Microsoft.SemanticKernel.Agents.Orchestration.Handoff;
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
using Microsoft.SemanticKernel.ChatCompletion;
// Plugin implementations
public sealed class OrderStatusPlugin {
[KernelFunction]
public string CheckOrderStatus(string orderId) => $"Order {orderId} is shipped and will arrive in 2-3 days.";
}
public sealed class OrderReturnPlugin {
[KernelFunction]
public string ProcessReturn(string orderId, string reason) => $"Return for order {orderId} has been processed successfully.";
}
public sealed class OrderRefundPlugin {
[KernelFunction]
public string ProcessReturn(string orderId, string reason) => $"Refund for order {orderId} has been processed successfully.";
}
// Helper function to create a kernel with chat completion
public static Kernel CreateKernelWithChatCompletion(...)
{
...
}
ChatCompletionAgent triageAgent = new ChatCompletionAgent {
Name = "TriageAgent",
Description = "Handle customer requests.",
Instructions = "A customer support agent that triages issues.",
Kernel = CreateKernelWithChatCompletion(...),
};
ChatCompletionAgent statusAgent = new ChatCompletionAgent {
Name = "OrderStatusAgent",
Description = "A customer support agent that checks order status.",
Instructions = "Handle order status requests.",
Kernel = CreateKernelWithChatCompletion(...),
};
statusAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderStatusPlugin()));
ChatCompletionAgent returnAgent = new ChatCompletionAgent {
Name = "OrderReturnAgent",
Description = "A customer support agent that handles order returns.",
Instructions = "Handle order return requests.",
Kernel = CreateKernelWithChatCompletion(...),
};
returnAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderReturnPlugin()));
ChatCompletionAgent refundAgent = new ChatCompletionAgent {
Name = "OrderRefundAgent",
Description = "A customer support agent that handles order refund.",
Instructions = "Handle order refund requests.",
Kernel = CreateKernelWithChatCompletion(...),
};
refundAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromObject(new OrderRefundPlugin()));
设置交接关系
使用 OrchestrationHandoffs
指定哪个代理可以向哪个代理进行移交,以及在什么情况下进行。
var handoffs = OrchestrationHandoffs
.StartWith(triageAgent)
.Add(triageAgent, statusAgent, returnAgent, refundAgent)
.Add(statusAgent, triageAgent, "Transfer to this agent if the issue is not status related")
.Add(returnAgent, triageAgent, "Transfer to this agent if the issue is not return related")
.Add(refundAgent, triageAgent, "Transfer to this agent if the issue is not refund related");
观察代理响应
可以创建一个回调,通过ResponseCallback
属性在会话进行时捕获代理的响应。
ChatHistory history = [];
ValueTask responseCallback(ChatMessageContent response)
{
history.Add(response);
return ValueTask.CompletedTask;
}
循环中的人类
交接业务流程的一个关键功能是使人能够参与对话。 这可以通过提供一个 InteractiveCallback
来实现,每当代理需要用户输入时将调用它。 在实际应用程序中,这会提示用户输入;在示例中,可以使用响应队列。
// Simulate user input with a queue
Queue<string> responses = new();
responses.Enqueue("I'd like to track the status of my order");
responses.Enqueue("My order ID is 123");
responses.Enqueue("I want to return another order of mine");
responses.Enqueue("Order ID 321");
responses.Enqueue("Broken item");
responses.Enqueue("No, bye");
ValueTask<ChatMessageContent> interactiveCallback()
{
string input = responses.Dequeue();
Console.WriteLine($"\n# INPUT: {input}\n");
return ValueTask.FromResult(new ChatMessageContent(AuthorRole.User, input));
}
设置交接协调流程
创建一个 HandoffOrchestration
对象,传入代理、交接关系和回调。
HandoffOrchestration orchestration = new HandoffOrchestration(
handoffs,
triageAgent,
statusAgent,
returnAgent,
refundAgent)
{
InteractiveCallback = interactiveCallback,
ResponseCallback = responseCallback,
};
启动运行时
需要运行时才能管理代理的执行。 在这里,我们在调用业务流程之前使用 InProcessRuntime
并启动它。
InProcessRuntime runtime = new InProcessRuntime();
await runtime.StartAsync();
调用编排
使用初始任务(例如,“我是一个需要订单帮助的客户”)调用编排。 代理将根据需要路由会话,必要时引入人工干预。
string task = "I am a customer that needs help with my orders";
var result = await orchestration.InvokeAsync(task, runtime);
收集结果
等待编排完成并获取最终输出。
string output = await result.GetValueAsync(TimeSpan.FromSeconds(300));
Console.WriteLine($"\n# RESULT: {output}");
Console.WriteLine("\n\nORCHESTRATION HISTORY");
foreach (ChatMessageContent message in history)
{
// Print each message
Console.WriteLine($"# {message.Role} - {message.AuthorName}: {message.Content}");
}
可选:停止运行时
处理完成后,停止运行时以清理资源。
await runtime.RunUntilIdleAsync();
示例输出
# RESULT: Handled order return for order ID 321 due to a broken item, and successfully processed the return.
ORCHESTRATION HISTORY
# Assistant - TriageAgent: Could you please specify what kind of help you need with your orders? Are you looking to check the order status, return an item, or request a refund?
# Assistant - OrderStatusAgent: Could you please tell me your order ID?
# Assistant - OrderStatusAgent: Your order with ID 123 has been shipped and will arrive in 2-3 days. Anything else I can assist you with?
# Assistant - OrderReturnAgent: I can help you with that. Could you please provide the order ID and the reason you'd like to return it?
# Assistant - OrderReturnAgent: Please provide the reason for returning the order with ID 321.
# Assistant - OrderReturnAgent: The return for your order with ID 321 has been successfully processed due to the broken item. Anything else I can assist you with?
小窍门
此处提供了完整的示例代码
定义专用代理
每个代理都负责特定区域。 例如:
- 分诊客服:处理客户的初始请求,并决定涉及哪些专家。
- RefundAgent:处理退款请求。
- OrderStatusAgent:检查订单状态。
- OrderReturnAgent:处理订单退货。
插件
首先,我们需要定义将在代理中使用的插件。 这些插件将包含用于处理特定任务的逻辑。
from semantic_kernel.functions import kernel_function
class OrderStatusPlugin:
@kernel_function
def check_order_status(self, order_id: str) -> str:
"""Check the status of an order."""
# Simulate checking the order status
return f"Order {order_id} is shipped and will arrive in 2-3 days."
class OrderRefundPlugin:
@kernel_function
def process_refund(self, order_id: str, reason: str) -> str:
"""Process a refund for an order."""
# Simulate processing a refund
print(f"Processing refund for order {order_id} due to: {reason}")
return f"Refund for order {order_id} has been processed successfully."
class OrderReturnPlugin:
@kernel_function
def process_return(self, order_id: str, reason: str) -> str:
"""Process a return for an order."""
# Simulate processing a return
print(f"Processing return for order {order_id} due to: {reason}")
return f"Return for order {order_id} has been processed successfully."
代理人
接下来,我们定义将使用这些插件的代理。
小窍门
此处 ChatCompletionAgent
与 Azure OpenAI 一起使用,但可以使用任何 代理类型 或 模型服务。
from semantic_kernel.agents import ChatCompletionAgent
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
support_agent = ChatCompletionAgent(
name="TriageAgent",
description="A customer support agent that triages issues.",
instructions="Handle customer requests.",
service=OpenAIChatCompletion(),
)
refund_agent = ChatCompletionAgent(
name="RefundAgent",
description="A customer support agent that handles refunds.",
instructions="Handle refund requests.",
service=OpenAIChatCompletion(),
plugins=[OrderRefundPlugin()],
)
order_status_agent = ChatCompletionAgent(
name="OrderStatusAgent",
description="A customer support agent that checks order status.",
instructions="Handle order status requests.",
service=OpenAIChatCompletion(),
plugins=[OrderStatusPlugin()],
)
order_return_agent = ChatCompletionAgent(
name="OrderReturnAgent",
description="A customer support agent that handles order returns.",
instructions="Handle order return requests.",
service=OpenAIChatCompletion(),
plugins=[OrderReturnPlugin()],
)
定义交接关系
使用 OrchestrationHandoffs
指定哪个代理可以向哪个代理进行移交,以及在什么情况下进行。
from semantic_kernel.agents import OrchestrationHandoffs
handoffs = (
OrchestrationHandoffs()
.add_many( # Use add_many to add multiple handoffs to the same source agent at once
source_agent=support_agent.name,
target_agents={
refund_agent.name: "Transfer to this agent if the issue is refund related",
order_status_agent.name: "Transfer to this agent if the issue is order status related",
order_return_agent.name: "Transfer to this agent if the issue is order return related",
},
)
.add( # Use add to add a single handoff
source_agent=refund_agent.name,
target_agent=support_agent.name,
description="Transfer to this agent if the issue is not refund related",
)
.add(
source_agent=order_status_agent.name,
target_agent=support_agent.name,
description="Transfer to this agent if the issue is not order status related",
)
.add(
source_agent=order_return_agent.name,
target_agent=support_agent.name,
description="Transfer to this agent if the issue is not order return related",
)
)
观察代理响应
可以定义一个回调,以在对话进行时打印每个代理的消息。
from semantic_kernel.contents import ChatMessageContent
def agent_response_callback(message: ChatMessageContent) -> None:
print(f"{message.name}: {message.content}")
循环中的人类
交接业务流程的一个关键功能是使人能够参与对话。 这是通过提供 human_response_function
回调来实现的,每当代理需要用户输入时调用该回调。
from semantic_kernel.contents import AuthorRole, ChatMessageContent
def human_response_function() -> ChatMessageContent:
user_input = input("User: ")
return ChatMessageContent(role=AuthorRole.USER, content=user_input)
设置交接协调流程
创建一个 HandoffOrchestration
对象,传入代理、交接关系和回调。
from semantic_kernel.agents import HandoffOrchestration
handoff_orchestration = HandoffOrchestration(
members=[
support_agent,
refund_agent,
order_status_agent,
order_return_agent,
],
handoffs=handoffs,
agent_response_callback=agent_response_callback,
human_response_function=human_response_function,
)
启动运行时
启动运行时以管理代理执行。
from semantic_kernel.agents.runtime import InProcessRuntime
runtime = InProcessRuntime()
runtime.start()
调用编排
使用初始任务来启动协调(例如,“客户正在通话中。”) 代理将根据需要路由会话,必要时引入人工干预。
orchestration_result = await handoff_orchestration.invoke(
task="A customer is on the line.",
runtime=runtime,
)
收集结果
等待编排完成。
value = await orchestration_result.get()
print(value)
可选:停止运行时
处理完成后,停止运行时以清理资源。
await runtime.stop_when_idle()
示例输出
TriageAgent: Hello! Thank you for reaching out. How can I assist you today?
User: I'd like to track the status of my order
OrderStatusAgent: Sure, I can help you with that. Could you please provide me with your order ID?
User: My order ID is 123
OrderStatusAgent: Your order with ID 123 has been shipped and is expected to arrive in 2-3 days. Is there anything else I can assist you with?
User: I want to return another order of mine
OrderReturnAgent: I can help you with returning your order. Could you please provide the order ID for the return and the reason you'd like to return it?
User: Order ID 321
OrderReturnAgent: Please provide the reason for returning the order with ID 321.
User: Broken item
OrderReturnAgent: The return for your order with ID 321 has been successfully processed due to the broken item. Is there anything else I can assist you with?
User: No, bye
Task is completed with summary: Handled order return for order ID 321 due to a broken item, and successfully processed the return.
小窍门
此处提供了完整的示例代码。
注释
代理协调功能在 Java SDK 中尚未可用。