了解本机函数

已完成

本机函数是用本机代码编写的函数,在应用程序中语义内核 SDK 可调用此函数。 它们可用于执行大型语言模型 (LLM) 无法自行执行的任务。 你可以将本机函数视为应用程序可以执行的技能。

在后面的模块中,你将了解如何使用语义内核自动调用创建的本机函数,并将逻辑与 LLM 的提示相结合。 将聊天完成服务与功能技能相结合,可以创建可执行各种任务的 AI 代理。 但现在,让我们专注于设计本机函数。

本机函数具有特定格式和建议的文件结构,供内核使用。 本机函数应在其定义中使用KernelFunction修饰器。 他们还对参数使用Description字段。 例如:

[KernelFunction, Description("Convert an amount of currency to USD")]
public static string ConvertCurrency(
  [Description("The currency")] string currency, 
  [Description("The amount")] double amount)
{
  // Code to convert currency
}

可以将本机函数作为插件导入内核。 包含本机函数的类应置于“插件”目录中。 相关函数应置于同一文件中,以保持代码有序。 还可以利用“插件”目录中的子目录进一步组织代码。

例如,假设你有待办事项列表应用程序。 用户想要完成其待办事项列表中的一个项目。 大型语言模型 (LLM) 无法直接访问用户待办事项列表,但你可以编写本机函数以访问该列表并将项目标记为已完成。 例如,待办事项列表文件可能包含以下内容:

{
  "todoList": [
    {
      "task": "Complete coding exercise",
      "completed": false
    },
    {
      "task": "Practice Mandarin",
      "completed": false
    },
    {
      "task": "Buy groceries",
      "completed": false
    }
  ]
}

可以在“插件”目录中创建文件TodoListPlugin.cs,在其中使用一些代码来将任务标记为已完成:

using System.ComponentModel;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.SemanticKernel;

public class TodoListPlugin
{
    [KernelFunction, Description("Mark a todo list item as complete")]
    public static string CompleteTask([Description("The task to complete")] string task)
    {
        // Read the JSON file
        string jsonFilePath = $"{Directory.GetCurrentDirectory()}/todo.txt";
        string jsonContent = File.ReadAllText(jsonFilePath);

        // Parse the JSON content
        JsonNode todoData = JsonNode.Parse(jsonContent);

        // Find the task and mark it as complete
        JsonArray todoList = (JsonArray) todoData["todoList"];
        foreach (JsonNode taskNode in todoList)
        {
            if (taskNode["task"].ToString() == task)
            {
                taskNode["completed"] = true;
                break;
            }
        }

        // Save the modified JSON back to the file
        File.WriteAllText(jsonFilePath, JsonSerializer.Serialize(todoData));
        return $"Task '{task}' marked as complete.";
    }
}

请注意 KernelFunction 函数上的 CompleteTask 修饰器。 此修饰器告知内核可以访问此函数。 Description 修饰器告知内核函数的作用。 该函数接受task作为字符串。 内核函数的变量应包含说明,解释变量是什么。 此函数还返回字符串,告知用户任务已标记为已完成。

Program.cs 文件中,可以导入和调用此本机函数,方式类似于调用一个内置插件。 例如:

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Plugins.Core;

var builder = Kernel.CreateBuilder();
builder.AddAzureOpenAIChatCompletion(
  "your-deployment-name",
  "your-endpoint",
  "your-api-key",
  "deployment-model");
var kernel = builder.Build();
kernel.ImportPluginFromType<TodoListPlugin>();

var result = await kernel.InvokeAsync<string>(
  "TodoListPlugin", 
  "CompleteTask", 
  new() {{ "task", "Buy groceries" }}
);
Console.WriteLine(result);

在此示例中,使用插件名称、函数名称和参数调用kernel.InvokeAsynctask参数设置为“购买杂货”。 该函数会在待办事项列表文件中将任务标记为已完成,并将消息返回给用户。

现在,AI 代理可以帮助用户完成其待办事项列表中的任务。 (可选)可以选择在 InvokeAsync 调用中指示函数的返回类型。 否则返回 FunctionResult 对象。

在下一个练习中,你将练习使用本机函数创建自己的插件。