AI框架SemanticKernel系列随笔(5) -- Planner

本文介绍了SK框架中Planner的作用,使用前需将所有Function注册到Kernel并附上说明。目前SK框架提供了HandlebarsPlanner和FunctionCallingStepwisePlanner两种Planner,前者制定并执行计划,后者逐步执行计划并根据结果调整任务,还给出了二者的源码及简单示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在SK框架中,Planner用于根据输入创建执行计划。SK框架会自动搜索注册到kernel中的所有可用的function,然后阅读这些function的说明,最后利用这些function搭建可用的执行计划。注意,在使用Planner之前,必须先把所有Function(不管是Native Function还是 SK Function)先注册到Kernel,并附上相应的function说明以便于AI识别。

其中,Native Function采用System.ComponentModel.DescriptionAttribute来标注函数和参数说明,SK Function则在config中定义。参考定义如下:

{
   
   
  "schema": 1,
  "description": "Generate a funny limerick about a person",
  "execution_settings": {
   
   
    "default": {
   
   
      "max_tokens": 100,
      "temperature": 0.7,
      "top_p": 0,
      "presence_penalty": 0,
      "frequency_penalty": 0
    }
  },
  "input_variables": [
    {
   
   
      "name": "name",
      "description": "",
      "default": "Bob"
    },
    {
   
   
      "name": "input",
      "description": "",
      "default": "Dogs"
    }
  ]
}

SK框架中,目前提供了两种Planner: HandlebarsPlanner 和 FunctionCallingStepwisePlanner,前者用于根据目标制定一系列执行计划并执行。后者是逐步执行器,他将逐步执行生成的计划,并参考过程中的执行结果,调整执行任务。

HandlebarsPlanner

HandlebarsPlanner源码如下:

// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using HandlebarsDotNet.Helpers.Enums;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;
using Microsoft.SemanticKernel.Text;

namespace Microsoft.SemanticKernel.Planning.Handlebars;

/// <summary>
/// Represents a Handlebars planner.
/// </summary>
public sealed class HandlebarsPlanner
{
   
   
    /// <summary>
    /// Represents static options for all Handlebars Planner prompt templates.
    /// </summary>
    public static readonly HandlebarsPromptTemplateOptions PromptTemplateOptions = new()
    {
   
   
        // Options for built-in Handlebars helpers
        Categories = new Category[] {
   
    Category.DateTime },
        UseCategoryPrefix = false,

        // Custom helpers
        RegisterCustomHelpers = HandlebarsPromptTemplateExtensions.RegisterCustomCreatePlanHelpers,
    };

    /// <summary>
    /// Initializes a new instance of the <see cref="HandlebarsPlanner"/> class.
    /// </summary>
    /// <param name="options">Configuration options for Handlebars Planner.</param>
    public HandlebarsPlanner(HandlebarsPlannerOptions? options = default)
    {
   
   
        this._options = options ?? new HandlebarsPlannerOptions();
        this._templateFactory = new HandlebarsPromptTemplateFactory(options: PromptTemplateOptions);
        this._options.ExcludedPlugins.Add("Planner_Excluded");
    }

    /// <summary>Creates a plan for the specified goal.</summary>
    /// <param name="kernel">The <see cref="Kernel"/> containing services, plugins, and other state for use throughout the operation.</param>
    /// <param name="goal">The goal for which a plan should be created.</param>
    /// <param name="arguments"> Optional. Context arguments to pass to the planner. </param>
    /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
    /// <returns>The created plan.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="goal"/> is null.</exception>
    /// <exception cref="ArgumentException"><paramref name="goal"/> is empty or entirely composed of whitespace.</exception>
    /// <exception cref="KernelException">A plan could not be created.</exception>
    public Task<HandlebarsPlan> CreatePlanAsync(Kernel kernel, string goal, KernelArguments? arguments = null, CancellationToken cancellationToken = default)
    {
   
   
        Verify.NotNullOrWhiteSpace(goal);

        var logger = kernel.LoggerFactory.CreateLogger(typeof(HandlebarsPlanner)) ?? NullLogger.Instance;

        return PlannerInstrumentation.CreatePlanAsync(
            static (HandlebarsPlanner planner, Kernel kernel, string goal, KernelArguments? arguments, CancellationToken cancellationToken)
                => planner.CreatePlanCoreAsync(kernel, goal, arguments, cancellationToken),
            this, kernel, goal, arguments, logger, cancellationToken);
    }

    #region private

    private readonly HandlebarsPlannerOptions _options;

    private readonly HandlebarsPromptTemplateFactory _templateFactory;

    private async Task<HandlebarsPlan> CreatePlanCoreAsync(Kernel kernel, string goal, KernelArguments? arguments, CancellationToken cancellationToken = default)
    {
   
   
        string? createPlanPrompt = null;
        ChatMessageContent? modelResults = null;

        try
        {
   
   
            // Get CreatePlan prompt template
            var functionsMetadata = await kernel.Plugins.GetFunctionsAsync(this._options, null, null, cancellationToken).ConfigureAwait(false);
            var availableFunctions = this.GetAvailableFunctionsManual(functionsMetadata, out var complexParameterTypes, out var complexParameterSchemas);
            createPlanPrompt = await this.GetHandlebarsTemplateAsync(kernel, goal, arguments, availableFunctions, complexParameterTypes, complexParameterSchemas, cancellationToken).ConfigureAwait(false);
            ChatHistory chatMessages = this.GetChatHistoryFromPrompt(createPlanPrompt);

            // Get the chat completion results
            var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();
            modelResults = await chatCompletionService.GetChatMessageContentAsync(chatMessages, executionSettings: this._options.ExecutionSettings, cancellationToken: cancellationToken).ConfigureAwait(false);

            // Regex breakdown:
            // (```\s*handlebars){1}\s*: Opening backticks, starting boundary for HB template
            // ((([^`]|`(?!``))+): Any non-backtick character or one backtick character not followed by 2 more consecutive backticks
            // (\s*```){1}: Closing backticks, closing boundary for HB template
            MatchCollection matches = Regex.Matches(modelResults.Content, @"(```\s*handlebars){1}\s*(([^`]|`(?!``))+)(\s*```){1}", RegexOptions.Multiline);
            if (matches.Count < 1)
            {
   
   
                throw new KernelException($"[{
     
     HandlebarsPlannerErrorCodes.InvalidTemplate}] Could not find the plan in the results. Additional helpers or input may be required.\n\nPlanner output:\n{
     
     modelResults.Content}");
            }
            else if (matches.Count > 1)
            {
   
   
                throw new KernelException($"[{
     
     HandlebarsPlannerErrorCodes.InvalidTemplate}] Identified multiple Handlebars templates in model response. Please try again.\n\nPlanner output:\n{
     
     modelResults.Content}");
            }

            var planTemplate = matches[0].Groups[2].Value.Trim();
            planTemplate = MinifyHandlebarsTemplate(planTemplate);

            return new HandlebarsPlan(planTemplate, createPlanPrompt);
        }
        catch (KernelException ex)
        {
   
   
            throw new PlanCreationException(
                "CreatePlan failed. See inner exception for details.",
                createPlanPrompt,
                modelResults,
                ex
            )
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萌新上路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值