Semantic Kernel中如何指定邮件Agent的正确规划步骤?
解决Semantic Kernel Planner生成错误邮件规划步骤的问题
问题核心
当前Planner生成1→3步骤的原因是大模型未意识到“获取最新邮件”必须先完成排序,且自定义规划函数未被Planner主动调用。以下是具体修复方案:
方案1:优化函数描述,引导大模型正确推理
通过强化函数的描述信息,明确步骤间的依赖关系,让大模型能正确判断执行顺序:
修改EmailPlugin.cs中的函数描述:
[KernelFunction] [Description("获取所有邮件列表,是后续排序和筛选操作的基础")] public async Task<List<EmailMessage>> GetEmailsAsync() { // 原有代码不变 } [KernelFunction] [Description("将邮件列表按日期降序排序,这是获取最新邮件的必要前置步骤,未排序的列表无法筛选出最新邮件")] public async Task<List<EmailMessage>> SortEmailsDescendingAsync( [Description("需要排序的邮件列表")] List<EmailMessage> emails ) { // 原有代码不变 } [KernelFunction] [Description("从已按日期降序排序的邮件列表中取前x封;若列表未排序,返回的结果不是最新邮件")] public Task<List<EmailMessage>> GetFirstEmails( [Description("已按日期降序排序的邮件列表")] List<EmailMessage> emails, [Description("要获取的邮件数量")] int amount ) { return Task.FromResult(emails.Take(amount).ToList()); }
方案2:封装组合函数,强制固定步骤
如果依赖大模型推理不可靠,可直接封装一个组合函数,将三个步骤硬编码,Planner会直接调用该函数,无需拆分步骤:
在EmailPlugin.cs中添加新函数:
[KernelFunction] [Description("获取最新的x封邮件,自动执行「获取邮件→按日期降序排序→取前x封」的完整流程")] public async Task<List<EmailMessage>> GetLatestEmailsAsync( [Description("要获取的最新邮件数量")] int amount ) { var emails = await GetEmailsAsync(); var sortedEmails = await SortEmailsDescendingAsync(emails); return await GetFirstEmails(sortedEmails, amount); }
修改后,用户输入"Give me the latest 3 E-Mails"时,Planner会直接调用GetLatestEmailsAsync(3),确保步骤完全符合预期。
方案3:触发自定义规划函数
要让EmailsPlanner.cs中的函数生效,需引导Planner先调用它获取步骤,再生成执行计划:
调整Program.cs中的规划逻辑:
// 替换原有的CreatePlanAsync逻辑 // 先提取用户请求中的邮件数量(示例中固定为3,实际可通过大模型解析) var amount = 3; // 调用自定义规划函数获取步骤 var stepInstructions = await kernel.InvokeAsync<string>("EmailsPlanner", "RequiredStepsForFetchingMailsAsync", new KernelArguments() { ["amount"] = amount }); // 基于步骤指令生成执行计划 var plan = await planner.CreatePlanAsync(kernel, stepInstructions);
方案4:自定义HandlebarsPlanner提示模板
通过修改Planner的提示模板,强制要求处理邮件排序:
var planner = new HandlebarsPlanner(new HandlebarsPlannerOptions() { AllowLoops = true, PromptTemplate = @" 你是严格的任务规划者,处理邮件请求时必须遵循规则: 1. 用户请求「最新x封邮件」时,必须执行三个步骤:获取邮件→按日期降序排序→取前x封 2. 不得跳过任何步骤 3. 使用提供的Kernel函数完成每个步骤 用户目标:{{$goal}} " });
内容的提问来源于stack exchange,提问作者CrazyEight
相关产品推荐
相关产品推荐

