规划器 #
概述 #
规划器(Planner)是 Semantic Kernel 的智能编排组件,能够自动将复杂的用户请求分解为一系列可执行的步骤,并协调执行这些步骤。
规划器架构 #
text
┌─────────────────────────────────────────────────────────────┐
│ 规划器工作流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 用户请求 │
│ "帮我查询北京的天气,然后写一首关于天气的诗" │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 1. 理解意图 │ │
│ │ 分析用户想要完成的任务 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 2. 生成计划 │ │
│ │ Step 1: WeatherPlugin.GetWeather("北京") │ │
│ │ Step 2: PoemPlugin.WritePoem(weather_info) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 3. 执行计划 │ │
│ │ 按顺序执行每个步骤 │ │
│ │ 将上一步输出传递给下一步 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 4. 返回结果 │ │
│ │ 最终生成的诗歌 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
规划器类型 #
FunctionCallingStepwisePlanner #
这是推荐的规划器,使用 LLM 的函数调用能力来规划和执行任务。
csharp
using Microsoft.SemanticKernel.Planning;
var planner = new FunctionCallingStepwisePlanner();
var result = await planner.ExecuteAsync(
kernel,
"帮我查询北京的天气,然后写一首关于天气的诗"
);
Console.WriteLine(result);
配置选项 #
csharp
var options = new FunctionCallingStepwisePlannerOptions
{
MaxIterations = 10,
MaxTokens = 4000
};
var planner = new FunctionCallingStepwisePlanner(options);
使用规划器 #
基本使用 #
csharp
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Planning;
var builder = Kernel.CreateBuilder();
builder.AddOpenAIChatCompletion("gpt-4", "api-key");
var kernel = builder.Build();
// 注册插件
kernel.Plugins.AddFromType<WeatherPlugin>("Weather");
kernel.Plugins.AddFromType<PoemPlugin>("Poem");
// 创建规划器
var planner = new FunctionCallingStepwisePlanner();
// 执行任务
var result = await planner.ExecuteAsync(
kernel,
"查询北京今天的天气,如果天气晴朗就写一首阳光的诗,否则写一首雨天的诗"
);
Console.WriteLine(result);
带初始参数 #
csharp
var arguments = new KernelArguments
{
["city"] = "北京",
["style"] = "现代诗"
};
var result = await planner.ExecuteAsync(
kernel,
"根据指定的城市和风格写诗",
arguments
);
指定可用插件 #
csharp
var options = new FunctionCallingStepwisePlannerOptions
{
// 只使用指定的插件
GetAvailableFunctionsAsync = (kernel) => Task.FromResult(
kernel.Plugins.GetFunctionsMetadata()
.Where(f => f.PluginName == "Weather" || f.PluginName == "Poem")
)
};
var planner = new FunctionCallingStepwisePlanner(options);
规划器执行流程 #
详细执行过程 #
csharp
var planner = new FunctionCallingStepwisePlanner();
// 执行并获取详细结果
var result = await planner.ExecuteAsync(
kernel,
"计算 5 加 3,然后乘以 2"
);
// 查看执行步骤
if (result.Iterations != null)
{
foreach (var iteration in result.Iterations)
{
Console.WriteLine($"步骤: {iteration.FunctionName}");
Console.WriteLine($"参数: {string.Join(", ", iteration.Arguments)}");
Console.WriteLine($"结果: {iteration.Result}");
}
}
获取中间结果 #
csharp
public class StepResult
{
public string FunctionName { get; set; }
public string PluginName { get; set; }
public Dictionary<string, object> Arguments { get; set; }
public string Result { get; set; }
}
// 自定义规划器以捕获中间结果
public class ObservablePlanner
{
private readonly FunctionCallingStepwisePlanner _planner;
public List<StepResult> Steps { get; } = new();
public ObservablePlanner()
{
_planner = new FunctionCallingStepwisePlanner();
}
public async Task<string> ExecuteAsync(Kernel kernel, string goal)
{
// 添加事件监听
kernel.FunctionInvoking += (s, e) =>
{
Console.WriteLine($"[调用] {e.Function.PluginName}.{e.Function.Name}");
};
kernel.FunctionInvoked += (s, e) =>
{
Steps.Add(new StepResult
{
PluginName = e.Function.PluginName,
FunctionName = e.Function.Name,
Result = e.Result.ToString()
});
};
return await _planner.ExecuteAsync(kernel, goal);
}
}
高级配置 #
配置最大迭代次数 #
csharp
var options = new FunctionCallingStepwisePlannerOptions
{
MaxIterations = 5 // 限制最大执行步骤数
};
var planner = new FunctionCallingStepwisePlanner(options);
配置系统提示词 #
csharp
var options = new FunctionCallingStepwisePlannerOptions
{
SystemPrompt = """
你是一个智能助手,可以帮助用户完成各种任务。
可用的工具:
{{$available_functions}}
请根据用户的请求,选择合适的工具来完成任务。
"""
};
var planner = new FunctionCallingStepwisePlanner(options);
自定义函数选择 #
csharp
var options = new FunctionCallingStepwisePlannerOptions
{
GetAvailableFunctionsAsync = async (kernel) =>
{
var allFunctions = kernel.Plugins.GetFunctionsMetadata();
// 过滤敏感函数
return allFunctions.Where(f =>
!f.Name.Contains("Delete") &&
!f.Name.Contains("Remove"));
}
};
实战示例 #
示例 1:数据处理流程 #
csharp
// 注册插件
kernel.Plugins.AddFromType<DataPlugin>("Data");
kernel.Plugins.AddFromType<AnalysisPlugin>("Analysis");
kernel.Plugins.AddFromType<ReportPlugin>("Report");
var planner = new FunctionCallingStepwisePlanner();
var result = await planner.ExecuteAsync(
kernel,
"从数据库获取销售数据,分析趋势,然后生成一份中文报告"
);
示例 2:多步骤工作流 #
csharp
kernel.Plugins.AddFromType<EmailPlugin>("Email");
kernel.Plugins.AddFromType<CalendarPlugin>("Calendar");
kernel.Plugins.AddFromType<TaskPlugin>("Task");
var planner = new FunctionCallingStepwisePlanner();
var result = await planner.ExecuteAsync(
kernel,
"""
执行以下任务:
1. 查找明天下午空闲的时间段
2. 创建一个会议邀请
3. 发送邮件通知所有参会者
"""
);
示例 3:条件执行 #
csharp
kernel.Plugins.AddFromType<WeatherPlugin>("Weather");
kernel.Plugins.AddFromType<NotificationPlugin>("Notification");
kernel.Plugins.AddFromType<CalendarPlugin>("Calendar");
var planner = new FunctionCallingStepwisePlanner();
var result = await planner.ExecuteAsync(
kernel,
"""
检查明天的天气预报:
- 如果下雨,发送提醒带伞的通知
- 如果晴天,安排户外活动
"""
);
规划器最佳实践 #
1. 提供清晰的函数描述 #
csharp
public class WeatherPlugin
{
[KernelFunction("get_weather")]
[Description("""
获取指定城市的天气信息。
参数:
- city: 城市名称,如"北京"、"上海"
返回:
- 天气信息,包括温度、天气状况、湿度等
""")]
public async Task<string> GetWeather(
[Description("城市名称")] string city)
{
// 实现
}
}
2. 限制可用函数 #
csharp
// 只暴露必要的函数给规划器
var options = new FunctionCallingStepwisePlannerOptions
{
GetAvailableFunctionsAsync = (kernel) => Task.FromResult(
kernel.Plugins.GetFunctionsMetadata()
.Where(f => f.PluginName is "Weather" or "Email" or "Calendar")
)
};
3. 设置合理的迭代限制 #
csharp
var options = new FunctionCallingStepwisePlannerOptions
{
MaxIterations = 10 // 防止无限循环
};
4. 处理执行失败 #
csharp
try
{
var result = await planner.ExecuteAsync(kernel, goal);
}
catch (KernelException ex)
{
Console.WriteLine($"规划执行失败: {ex.Message}");
// 回退方案
}
5. 监控执行过程 #
csharp
kernel.FunctionInvoking += (s, e) =>
{
Console.WriteLine($"[开始] {e.Function.PluginName}.{e.Function.Name}");
};
kernel.FunctionInvoked += (s, e) =>
{
Console.WriteLine($"[完成] {e.Function.Name}");
Console.WriteLine($"[结果] {e.Result}");
};
var result = await planner.ExecuteAsync(kernel, goal);
规划器与其他组件协作 #
与记忆系统协作 #
csharp
// 保存规划结果到记忆
var result = await planner.ExecuteAsync(kernel, goal);
await kernel.Memory.SaveInformationAsync(
"planning_history",
text: $"目标: {goal}\n结果: {result}",
id: Guid.NewGuid().ToString()
);
与过滤器协作 #
csharp
public class PlanningFilter : IFunctionFilter
{
public async Task OnFunctionInvocationAsync(
FunctionInvocationContext context,
Func<FunctionInvocationContext, Task> next)
{
// 记录规划步骤
LogStep(context);
await next(context);
// 验证结果
ValidateResult(context);
}
}
kernel.FunctionFilters.Add(new PlanningFilter());
调试规划器 #
启用详细日志 #
csharp
using Microsoft.Extensions.Logging;
var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
builder.SetMinimumLevel(LogLevel.Debug);
});
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4", "api-key")
.Build();
kernel.LoggerFactory = loggerFactory;
查看生成的计划 #
csharp
// 使用事件查看规划决策
kernel.FunctionInvoking += (s, e) =>
{
Console.WriteLine($"调用: {e.Function.PluginName}.{e.Function.Name}");
foreach (var arg in e.Arguments)
{
Console.WriteLine($" {arg.Key}: {arg.Value}");
}
};
下一步 #
现在你已经掌握了规划器,接下来学习 提示词模板,了解如何设计高效的提示词!
最后更新:2026-04-04