亲爱的朋友,你曾想象拥有一个能够协助你完成日常任务、提供实时建议的智能伙伴吗?今天,我将为大家介绍一个名为Semantic Kernel的先进框架,用以构建自己的智能代理——我会从副驾驶(copilot)开始步入这个令人兴奋的领域。
什么是Copilot?
副驾驶(copilot)是智能代理的一种,与用户并肩作战,不全自动运作,而是通过建议和推荐来辅助用户完成任务。一个典型例子就是撰写电子邮件:它能够提供建议内容,而用户可以选择接受或者拒绝。
为什么从Copilot开始?
建议初学者先构建副驾驶,因为它比较简单也更安全。用户始终在控制中,一步步熟悉后,副驾驶可以逐渐演进成为完全自动的智能代理。
构建智能代理的核心组成
智能代理由三个核心部件组成:插件(plugins)、规划器(planners)、以及角色(persona)。
插件:赋予你的代理技能
插件是代码形式,帮助你的代理学习技能。例如,创建一个发送邮件的插件,用以处理电子邮件的发送工作。
public class EmailPlugin
{
[KernelFunction]
[Description("向收件人发送电子邮件。")]
public async Task SendEmailAsync(
Kernel kernel,
string recipientEmails,
string subject,
string body
)
{
// 这里添加发送邮件的逻辑
Console.WriteLine("Email sent!");
}
}
这段代码演示了如何建立一个简易的邮件发送插件。
规划器:指引你的代理
规划器是用来生成完成任务的计划。举例来说,你可以创建一个专门用于撰写电子邮件的规划器。
public class AuthorEmailPlanner
{
[KernelFunction]
[Description("返回编写电子邮件所需的步骤。")]
[return: Description("编写电子邮件所需的步骤列表")]
public async Task<string> GenerateRequiredStepsAsync(
Kernel kernel,
[Description("用2-3句话描述邮件内容")] string topic,
[Description("收件人的说明")] string recipients
)
{
// 提示LLM生成完成任务的步骤列表
var result = await kernel.InvokePromptAsync($"""
我将代表用户向{recipients}发送一封关于{topic}的电子邮件。
在我这么做之前,你能简单地推荐我应该采取的前三个步骤吗?
我想确保我不会忘记任何有助于我的用户的电子邮件听起来更专业的东西。
""", new() {
{ "topic", topic },
{ "recipients", recipients }
});
// 将计划返回给代理
return result.ToString();
}
}
一个有效的规划器可以明确代理需要完成的步骤列表。
角色:让代理拥有个性
角色让软件开发人员可以影响代理与用户的互动方式。你可以使用个性改变代理的个性或是如何回应特定情境。
将这些组件结合起来,我们便能够开始构建我们的第一个智能代理,使用上述的插件与规划器,并添加个性特征,我们可以进行有效的对话。
为此,我们将将系统提示传递到包含角色的 ChatHistory 对象中。然后,每当我们向代理发出请求时,都会 ChatHistory 使用此对象,以便代理了解其角色以及它之前与用户进行的所有对话。
ChatHistory chatMessages = new ChatHistory("""
你是一个友好的助手,喜欢遵守规则。您将完成所需的步骤
并在采取任何后续行动之前请求批准。如果用户不提供
足够的信息让你完成一项任务,你会一直问问题,直到你有
足够的信息来完成任务。
""");
将多个部分组合在一起
现在我们了解了代理的核心构建块,现在可以将它们组合在一起来构建我们的第一个代理。为此,我们将使用插件、规划器和角色初始化我们的 Kernel 对象。之后,我们将使用该 Kernel 对象生成一个计划,然后执行该计划。
// 创建内核
var builder = Kernel.CreateBuilder();
builder.Services.AddLogging(c => c.SetMinimumLevel(LogLevel.Trace).AddDebug());
builder.Services.AddChatCompletionService(kernelSettings);
builder.Plugins.AddFromType<AuthorEmailPlanner>();
builder.Plugins.AddFromType<EmailPlugin>();
Kernel kernel = builder.Build();
// 从内核检索聊天完成服务
IChatCompletionService chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
// 创建聊天历史记录
ChatHistory chatMessages = new ChatHistory("""
你是一个友好的助手,喜欢遵守规则。您将完成所需的步骤
并在采取任何后续行动之前请求批准。如果用户不提供
足够的信息让你完成一项任务,你会一直问问题,直到你有
足够的信息来完成任务。
""");
// 开始对话
while (true)
{
// 获取用户输入
System.Console.Write("User > ");
chatMessages.AddUserMessage(Console.ReadLine()!);
// 获取聊天完成
OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
{
FunctionCallBehavior = FunctionCallBehavior.AutoInvokeKernelFunctions
};
var result = chatCompletionService.GetStreamingChatMessageContentsAsync(
chatMessages,
executionSettings: openAIPromptExecutionSettings,
kernel: kernel);
// 流式传输结果
string fullMessage = "";
await foreach (var content in result)
{
if (content.Role.HasValue)
{
System.Console.Write("Assistant > ");
}
System.Console.Write(content.Content);
fullMessage += content.Content;
}
System.Console.WriteLine();
// 将来自代理的消息添加到聊天历史记录中
chatMessages.AddAssistantMessage(fullMessage);
}
测试你的代理
下面是一个典型的对话示例,在帮助用户撰写针对老板的业绩更新邮件过程中,智能代理可以给出详尽的步骤计划,甚至可以根据用户反馈实时调整邮件草稿。
//用户
你能帮我给老板写封电子邮件吗?
//助理
当然,我很乐意帮你给老板写封电子邮件。你能不能
请提供更多详细信息?具体来说,我需要知道:
1.电子邮件的主题或目的。
2.你老板的电子邮件地址。
//用户
我想向他介绍一下上个月的最新销售情况。我们打破了一堆记录
我想和他分享一下,但我们在销售X产品时确实遇到了挑战。
//助理
这听起来是一个很好的电子邮件主题。你能给我提供你的
老板的电子邮件地址,这样我可以进一步帮助你吗?
//用户
是的,他的邮箱是boss@163.com
//助理
太棒了以下是您的电子邮件计划:
1.**以清晰的主题和问候语开始**:主题应该是
简洁且信息丰富,如“上月销售X产品的最新情况及挑战”。
以专业的问候语开始电子邮件,比如“Dear Boss”。
2.**在单独的段落中强调成就和挑战**:从
关于破纪录成就的积极消息。使用特定数据和举例说明成功。
然后,通过X产品。对问题要诚实、清晰,但也要提出潜在的建议
为应对这些挑战而采取的解决方案或步骤。
3.**以行动呼吁和专业收尾结束**:如果你需要Boss
采取任何行动,在电子邮件末尾清楚地说明这一点。这可能是
征求他的意见,召开会议进一步讨论,或采取任何其他相关行动。
用“问候”或“真诚”这样的短语专业地关闭电子邮件,
然后是你的名字。
记得校对电子邮件中的任何语法错误或不清楚的陈述
发送之前。这将有助于确保邮件专业且易于发送
你想让我根据这些步骤为你起草电子邮件吗?
//用户
是的,请起草吧
//助理
当然,这是一个基于我们讨论的步骤的草案:
主题:上月销售和X产品挑战的最新情况
亲爱的Boss:,
我希望这封邮件能让你感觉良好。我写信是为了向您介绍我们的销售情况
过去一个月的表现。
我很高兴地报告,我们上个月打破了几项销售记录。我们团队的
辛勤的工作和奉献精神得到了回报,使我们的整体业绩显著增长
销售数字[在这里,您可以添加特定的数据或打破记录的示例]
然而,X产品确实给我们带来了一些挑战。尽管我们尽了最大努力,
这种产品的销售量没有达到我们的预期。[在这里,你可以解释更多
关于所面临的挑战]
我们目前正在制定提高X产品销量的策略。
[在这里,您可以提及解决该问题的任何具体步骤或计划]
我将感谢你对此事的意见。如果您愿意,我们可以安排
会议对此进行进一步讨论。
感谢您的持续支持和指导。
顺致敬意,
[您的姓名]
请审阅这份草案,如果你想做任何修改,请告诉我
在我发送之前。
//用户
你能补充一下我们的收入增加了20%吗?您也可以分享X产品
由于大多数客户升级到Y5000型号,所以销量不佳,但事实并非如此
太糟糕了,因为这有助于增加我们的收入。
//助理
当然,这是最新的草案:
主题:上月销售和X产品挑战的最新情况
亲爱的Boss:,
我希望这封邮件能让你感觉良好。我写信是为了向您介绍我们的销售业绩
过去一个月。
我很高兴地报告,我们上个月打破了几项销售记录。我们的团队很辛苦
工作和奉献精神得到了回报,使我们的
整体收入。这一增长证明了我们团队的承诺和质量
我们的产品。
然而,X产品确实给我们带来了一些挑战。尽管我们尽了最大努力,
这种型号的销售量没有达到我们的预期。有趣的是,大多数客户
升级到Y5000型号,这对我们的收入增长做出了重大贡献。
虽然我们的目标是提高所有车型的销量,但客户偏好的转变
并不是完全否定的。
我们目前正在分析这一趋势,并制定策略来利用它
未来销售。非常感谢您的见解和建议。
感谢您的持续支持和指导。
顺致敬意,
[您的姓名]
请查看此更新草案,如果您想进行任何更改,请告诉我
在我发送之前。
//用户
请与Stephen签字,然后你可以继续把它寄给Boss
//功能
邮件已发送!
//助理
电子邮件已发送给Boss。如果你还有什么需要帮助的,
请随意提问!
通过此示例,我们可以体验到智能代理如何实时交互,并在用户完全控制下辅助完成任务。
结语:通过Semantic Kernel,即使你不是人工智能专家,也可以轻松构建起智能代理。从副驾驶(copilot)入手,循序渐进,你将能发挥无限创意,创制出更加复杂、高度自动化的智能助手。现在,让我们开始这激动人心的AI编程之旅吧!