2.14. semantic kernel中Planning
当你拥有多个插件时,接下来就需要一种方式让你的 AI 代理组合使用这些插件,来完成用户的请求——这就是**规划(Planning)**的用途。
1. Planning的演进
在 Semantic Kernel 的早期阶段,曾引入“Planner”的概念,使用提示词(Prompt)引导 AI 决定要调用哪些函数。但自那之后,OpenAI 引入了**原生函数调用(Function Calling)**功能;其他 AI 模型如 Gemini、Claude、Mistral 也将其作为核心功能支持,这使得函数调用成为一个跨模型通用特性。
因此,Semantic Kernel 也随之演进,将函数调用作为主要的任务规划与执行方式。
重要提示 函数调用仅适用于 OpenAI 模型 0613 或更新版本。如果你使用的是旧版本模型(如 0314),此功能将无法使用并返回错误。我们建议使用最新版本的 OpenAI 模型以充分利用此特性。
2. 函数调用是如何创建Planning的?
从本质上讲,函数调用只是 AI 以正确参数调用函数的一种方式。例如,用户希望打开一个灯泡:
🔵 User
请打开 1 号灯
🔴 Assistant (function call)
Lights.change_state(1, { "isOn": true })
🟢 Tool
{ "id": 1, "name": "台灯", "isOn": true, "brightness": 100, "hex": "FF0000" }
🔴 Assistant
灯已打开
但如果用户不知道灯的 ID 呢?或者用户希望同时打开所有灯?这时就需要**“规划”能力**。
现代 LLM 模型具备逐步调用函数并基于结果做出决策的能力。AI 可以先调用函数获取状态,再决定执行哪个动作。
例子:用户想“切换所有灯的状态”
🔵 User
请切换所有灯的状态
🔴 Assistant (function call)
Lights.get_lights()
🟢 Tool
{ lights: [{ id: 1, isOn: true }, { id: 2, isOn: false }] }
🔴 Assistant (function call)
Lights.change_state(1, { "isOn": false })
Lights.change_state(2, { "isOn": true })
🟢 Tool
灯状态更新成功
🔴 Assistant
所有灯的状态已切换
💡 说明:并行调用 上述例子展示了并行函数调用——AI 可同时发出多个函数调用请求。此功能从 OpenAI 模型 1106 版本开始支持,大大加快了处理复杂任务的效率。
3. 自动规划循环(Function Calling Loop)
如果不使用 Semantic Kernel,想要支持函数调用规划,你需要自己实现一个“调用循环”:
为每个函数创建 JSON schema
提供给 LLM 当前的聊天历史和函数 schema
解析 LLM 返回内容,判断是回复消息还是调用函数
如果是函数调用,提取函数名和参数
执行对应函数
将结果返回给 LLM
重复第 2~6 步,直到任务完成或需要用户输入
✅ Semantic Kernel 帮你自动完成这个循环 你只需专注于构建插件来满足用户需求,其余步骤由 Semantic Kernel 自动处理。
ℹ️ 想深入了解函数调用循环的执行机制,请参考 Function Calling 工作原理 文档。
4. 如何在 Semantic Kernel 中启用函数调用
你需要完成以下 3 步:
1. 注册插件
var builder = Kernel.CreateBuilder()
.AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey);
builder.Plugins.AddFromType<LightsPlugin>("Lights");
var kernel = builder.Build();
2. 启用自动函数调用
var settings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
3. 使用 ChatCompletion 启动交互
var chatService = kernel.GetRequiredService<IChatCompletionService>();
var history = new ChatHistory();
string? userInput;
do {
Console.Write("User > ");
userInput = Console.ReadLine();
history.AddUserMessage(userInput);
var result = await chatService.GetChatMessageContentAsync(
history,
executionSettings: settings,
kernel: kernel);
Console.WriteLine("Assistant > " + result);
history.AddMessage(result.Role, result.Content ?? string.Empty);
} while (userInput is not null);
✅ 所有函数调用过程和结果都会自动写入 ChatHistory,你可以随时查看 AI 调用了哪些函数以及它是如何得出最终结论的。
5. 什么情况废弃了旧的规划器?
Stepwise Planner 和 Handlebars Planner 这两个旧有的规划器已经被弃用并移除,不再支持 .NET / Python / Java。
请改用函数调用(Function Calling),它提供了更强大、可控、且简洁的开发体验。
🔁 如需将旧方案迁移到函数调用,请参考官方的 Stepwise Planner 迁移指南。
6. 结语
新项目Planning
使用函数调用 Function Calling
旧代码迁移
放弃 Stepwise / Handlebars Planner
多插件协调执行
利用函数调用实现自动规划和执行
多模型支持
兼容 OpenAI、Gemini、Claude、Mistral 等
Last updated