练习 - 创建货币换算器

已完成

在本练习中,你将创建一个插件,以便用户进行从一种货币到另一种货币的金额换算。 由于模型无法通过访问 Internet 来确定当前汇率,因此需要在插件中提供汇率。 在本练习中,你将使用现有的 currencies.txt 文件来提供汇率。

重要

在开始此练习之前,需要完成上一单元“准备”中的设置说明。

创建本机函数

在此任务中,你将创建一个本机函数,该函数可实现从基准货币到目标货币的金额换算。

  1. 在 Plugins/ConvertCurrency 文件夹中创建一个名为 CurrencyConverter.cs 的新文件

  2. CurrencyConverter.cs 文件中,添加以下代码以创建插件函数:

    using AITravelAgent;
    
    class CurrencyConverter
    {
        [KernelFunction, 
        Description("Convert an amount from one currency to another")]
        public static string ConvertAmount()
        {
            var currencyDictionary = Currency.Currencies;
        }
    }
    

    在此段代码中,你将使用 KernelFunction 修饰器来声明本机函数。 还将使用 Description 修饰器来添加函数功能的说明。 你可以使用 Currency.Currencies 来获取货币字典及其汇率。 接下来,添加一些逻辑来实现从一种货币到另一种货币的给定金额换算。

  3. 使用以下代码修改 ConvertAmount 函数:

    [KernelFunction, Description("Convert an amount from one currency to another")]
    public static string ConvertAmount(
        [Description("The target currency code")] string targetCurrencyCode, 
        [Description("The amount to convert")] string amount, 
        [Description("The starting currency code")] string baseCurrencyCode)
    {
        var currencyDictionary = Currency.Currencies;
    
        Currency targetCurrency = currencyDictionary[targetCurrencyCode];
        Currency baseCurrency = currencyDictionary[baseCurrencyCode];
    
        if (targetCurrency == null)
        {
            return targetCurrencyCode + " was not found";
        }
        else if (baseCurrency == null)
        {
            return baseCurrencyCode + " was not found";
        }
        else
        {
            double amountInUSD = Double.Parse(amount) * baseCurrency.USDPerUnit;
            double result = amountInUSD * targetCurrency.UnitsPerUSD;
            return @$"${amount} {baseCurrencyCode} is approximately 
                {result.ToString("C")} in {targetCurrency.Name}s ({targetCurrencyCode})";
        }
    }
    

    在此段代码中,你将使用 Currency.Currencies 字典来获取目标和基准货币的 Currency 对象。 然后使用 Currency 对象进行从基准货币到目标货币的金额换算。 最后,返回一个包含换算后的金额的字符串。 接下来,让我们测试插件。

    注意

    在自己的项目中使用语义内核 SDK 时,如果有权访问 RESTful API,则无需将数据硬编码到文件中。 相反,你可以使用 Plugins.Core.HttpClient 插件从 API 检索数据。

  4. Program.cs 文件中,请使用以下代码导入并调用新插件函数:

    kernel.ImportPluginFromType<CurrencyConverter>();
    kernel.ImportPluginFromType<ConversationSummaryPlugin>();
    var prompts = kernel.ImportPluginFromPromptDirectory("Prompts");
    
    var result = await kernel.InvokeAsync("CurrencyConverter", 
        "ConvertAmount", 
        new() {
            {"targetCurrencyCode", "USD"}, 
            {"amount", "52000"}, 
            {"baseCurrencyCode", "VND"}
        }
    );
    
    Console.WriteLine(result);
    

    在此段代码中,你将使用 ImportPluginFromType 方法来导入插件。 然后使用 InvokeAsync 方法来调用插件函数。 InvokeAsync 方法将采用插件名称、函数名称和参数字典。 最后,你会将结果打印到控制台。 接下来,请运行代码以确保其正常工作。

  5. 在终端中输入 dotnet run。 应会看到以下输出:

    $52000 VND is approximately $2.13 in US Dollars (USD)
    

    插件正常运行后,让我们创建一个可以检测用户想要换算的货币和金额的自然语言提示。

创建提示

在此任务中,你将创建一个提示来分析用户的输入,以确定目标货币、基准货币和要换算的金额。

  1. 在“Prompts”文件夹中创建一个名为 GetTargetCurrencies 的新文件夹

  2. GetTargetCurrencies 文件夹中,创建一个名为 config.json 的新文件

  3. config.json 文件中输入以下文本:

    {
        "schema": 1,
        "type": "completion",
        "description": "Identify the target currency, base currency, and amount to convert",
        "execution_settings": {
            "default": {
                "max_tokens": 800,
                "temperature": 0
            }
        },
        "input_variables": [
            {
                "name": "input",
                "description": "Text describing some currency amount to convert",
                "required": true
            }
        ]
    }
    
  4. GetTargetCurrencies 文件夹中,创建名为 skprompt.txt 的新文件

  5. skprompt.txt 文件中输入以下文本:

    <message role="system">Identify the target currency, base currency, and 
    amount from the user's input in the format target|base|amount</message>
    
    For example: 
    
    <message role="user">How much in GBP is 750.000 VND?</message>
    <message role="assistant">GBP|VND|750000</message>
    
    <message role="user">How much is 60 USD in New Zealand Dollars?</message>
    <message role="assistant">NZD|USD|60</message>
    
    <message role="user">How many Korean Won is 33,000 yen?</message>
    <message role="assistant">KRW|JPY|33000</message>
    
    <message role="user">{{$input}}</message>
    <message role="assistant">target|base|amount</message>
    

检查工作

在此任务中,你将运行应用程序并验证代码是否正常工作。

  1. 请使用以下代码来更新 Program.cs 文件,以测试新提示:

    kernel.ImportPluginFromType<CurrencyConverter>();
    var prompts = kernel.ImportPluginFromPromptDirectory("Prompts");
    
    var result = await kernel.InvokeAsync(prompts["GetTargetCurrencies"],
        new() {
            {"input", "How many Australian Dollars is 140,000 Korean Won worth?"}
        }
    );
    
    Console.WriteLine(result);
    
  2. 在终端中输入 dotnet run。 应会看到以下输出:

    AUD|KRW|140000
    

    注意

    如果代码未生成预期的输出,可以在“Solution”文件夹中查看代码。 你可能需要调整 skprompt.txt 文件中的提示,以生成更精确的结果。

现在,你有一个可以实现从一种货币到另一种货币的金额换算的插件,以及可用于将用户的输入分析为可供 ConvertAmount 函数使用的格式的提示。 在下一个练习中,你可以使用用户的意向来运行函数。