Principy nativních funkcí

Dokončeno

Nativní funkce jsou funkce napsané v nativním kódu, které lze volat sadou SDK sémantického jádra ve vaší aplikaci. Jsou užitečné pro provádění úloh, které velké jazykové modely (LLM) nemůžou dělat samostatně. Můžete si představit nativní funkci, jako je dovednost, kterou může vaše aplikace provádět.

V pozdějších modulech se dozvíte, jak pomocí sémantického jádra automaticky vyvolat nativní funkce, které vytvoříte, a zkombinovat logiku s výzvami k LLM. Kombinování služeb dokončování chatu s funkčními dovednostmi umožňuje vytvořit agenta AI, který může provádět širokou škálu úloh. Prozatím se ale zaměříme na navrhování nativních funkcí.

Nativní funkce mají určitý formát a doporučenou strukturu souborů, kterou má jádro používat. Nativní funkce by měly v definicích používat KernelFunction dekorátor. Používají také Description pole pro parametry. Příklad:

[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
}

Nativní funkce můžete importovat do jádra jako modul plug-in. Třídy obsahující nativní funkce by měly být umístěny v adresáři Plugins. Související funkce by se měly umístit do stejného souboru, aby byl kód uspořádaný. K dalšímu uspořádání kódu můžete využít také podadresáře v adresáři Plugins.

Předpokládejme například, že máte aplikaci seznamu úkolů. Uživatel chce dokončit položku v seznamu úkolů. Velký jazykový model (LLM) nemá přímý přístup k seznamu úkolů uživatele, ale můžete napsat nativní funkci pro přístup k seznamu a označit položku jako dokončenou. Například soubor seznamu úkolů může obsahovat následující:

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

V adresáři Plugins můžete vytvořit soubor TodoListPlugin.cs s kódem, který označí dokončený úkol:

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 Všimněte si dekorátoru funkceCompleteTask. Tento dekorátor říká jádru, že k této funkci lze přistupovat. Dekorátor Description řekne jádru, co funkce dělá. Funkce přijímá jako task řetězec. Proměnné funkcí jádra by měly obsahovat popis, který vysvětluje, co je proměnná. Tato funkce také vrátí řetězec, který uživateli oznámí, že úkol byl označen jako dokončený.

Program.cs V souboru můžete importovat a volat tuto nativní funkci podobně, jako byste volali jeden z integrovaných modulů plug-in. Příklad:

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);

V tomto příkladu kernel.InvokeAsync se volá s názvem modulu plug-in, názvem funkce a argumenty. Argument task je nastavený na "Koupit potraviny". Funkce označí úkol jako dokončený v souboru seznamu úkolů a vrátí uživateli zprávu.

Agent AI teď může uživateli pomoct s dokončením úkolů v seznamu úkolů. Volitelně můžete zvolit, že chcete označit návratový typ funkce ve InvokeAsync volání. FunctionResult V opačném případě se vrátí objekt.

V dalším cvičení si procvičíte vytváření vlastních modulů plug-in s nativními funkcemi.