你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure AI 个性化体验创建服务的本地推理 SDK 入门

重要

从 2023 年 9 月 20 日开始,将无法创建新的个性化体验创建服务资源。 个性化体验创建服务将于 2026 年 10 月 1 日停用。

个性化体验创建服务本地推理 SDK(预览版)将个性化体验创建服务模型下载到本地,从而通过消除网络调用显著降低了 Rank 调用的延迟。 客户端每分钟都会在后台下载最新的模型并将其用于推理。

本指南介绍如何使用个性化体验创建服务本地推理 SDK。

需要安装用于 .NET 的个性化体验创建服务客户端库,以便:

  • 使用 Azure 中的个性化体验创建服务资源对快速入门示例客户端进行身份验证。
  • 将上下文和操作功能发送到奖励 API,这将从个性化体验创建服务模型返回最佳操作
  • 将奖励分数发送到排名 API 并训练个性化体验创建服务模型。

参考文档 | 库源代码 | 包 (NuGet)

先决条件

  • Azure 订阅 - 免费创建订阅
  • .NET Core 的当前版本。
  • 拥有 Azure 订阅后,在 Azure 门户中创建个性化体验创建服务资源,获取密钥和终结点。 部署后,选择”转到资源”。
    • 需要从创建的资源获取密钥和终结点,以便将应用程序连接到个性化体验创建服务 API。 你稍后会在快速入门中将密钥和终结点粘贴到下方的代码中。
    • 可以使用免费定价层 (F0) 试用该服务,然后再升级到付费层进行生产。

设置

更改模型更新频率

在 Azure 门户中,转到个性化体验创建服务资源的“配置”页,并将“模型更新频率”更改为 30 秒。 此短暂持续时间可快速训练模型,使你可以看到建议的操作如何针对每次迭代而变化。

更改模型更新频率

更改奖励等待时间

在 Azure 门户中,转到个性化体验创建服务资源的“配置”页,并将“奖励等待时间”更改为 10 分钟。 这决定了在发送建议后模型将等待多长时间来接收来自该建议的奖励反馈。 在奖励等待时间过去之前,不会进行训练。

更改奖励等待时间

新建 C# 应用程序

在首选编辑器或 IDE 中创建新的 .NET Core 应用程序。

在控制台窗口(例如 CMD、PowerShell 或 Bash)中,使用 dotnet new 命令创建名为 personalizer-quickstart 的新控制台应用。 此命令将创建包含单个源文件的简单“Hello World”C# 项目:Program.cs

dotnet new console -n personalizer-quickstart

将目录更改为新创建的应用文件夹。 可使用以下代码生成应用程序:

dotnet build

生成输出不应包含警告或错误。

...
Build succeeded.
 0 Warning(s)
 0 Error(s)
...

安装客户端库

在应用程序目录中,使用以下命令安装适用于 .NET 的个性化体验创建服务客户端库:

dotnet add package Azure.AI.Personalizer --version 2.0.0-beta.2

提示

如果你使用的是 Visual Studio IDE,客户端库可用作可下载的 NuGet 包。

在偏好的编辑器或 IDE 中打开项目目录中的 Program.cs 文件。 添加以下 using 指令:

using Azure;
using Azure.AI.Personalizer;
using System;
using System.Collections.Generic;
using System.Linq;

对象模型

个性化体验创建服务客户端是一个 PersonalizerClient 对象,它使用包含你的密钥的 Azure.AzureKeyCredential 向 Azure 进行身份验证。

若要请求向用户展示单个最佳项,请创建一个 PersonalizerRankOptions,然后将其传递给 PersonalizerClient.Rank 方法。 Rank 方法返回 PersonalizerRankResult

若要向个性化体验创建服务发送奖励分数,请将事件 ID 和奖励分数传递给 PersonalizerClient.Reward 方法。

在本快速入门中,可以很容易地确定奖励评分。 在生产系统中,确定哪些因素会影响奖励评分以及影响程度可能是一个复杂的过程,你的判断可能会随时改变。 此设计决策应是个性化体验创建服务体系结构中的主要决策之一。

代码示例

这些代码片段演示如何使用适用于 .NET 的个性化体验创建服务客户端库执行以下任务:

验证客户端

在本部分中,你将执行以下两项操作:

  • 指定密钥和终结点
  • 创建个性化体验创建服务客户端

首先,将以下行添加到 Program 类。 请确保从个性化体验创建服务资源中添加密钥和终结点。

重要

转到 Azure 门户。 如果在“先决条件”部分中创建的个性化体验创建服务资源已成功部署,请单击“后续步骤”下的“转到资源”按钮 。 在资源的“密钥和终结点”页的“资源管理”下可以找到密钥和终结点 。

完成后,请记住将密钥从代码中删除,并且永远不要公开发布该密钥。 对于生产环境,请考虑使用安全的方法来存储和访问凭据。 例如,Azure 密钥保管库

private const string ServiceEndpoint  = "https://REPLACE-WITH-YOUR-PERSONALIZER-RESOURCE-NAME.cognitiveservices.azure.com";
private const string ResourceKey = "<REPLACE-WITH-YOUR-PERSONALIZER-KEY>";

接下来,构造排名和奖励 URL。 请注意,需要将 useLocalInference: true 设置为 PersonalizerClientOptions 的参数才能启用本地推理。

static PersonalizerClient InitializePersonalizerClient(Uri url)
{
    // Set the local inference flag to true when initializing the client.
    return new PersonalizerClient(url, new AzureKeyCredential(ResourceKey), new PersonalizerClientOptions(useLocalInference: true));
}

获取以操作形式表示的内容选项

操作表示你希望个性化体验创建服务从中选择最佳内容项的内容选择。 将以下方法添加到 Program 类,以表示操作及其特征的集合。

static IList<PersonalizerRankableAction> GetActions()
{
    IList<PersonalizerRankableAction> actions = new List<PersonalizerRankableAction>
    {
        new PersonalizerRankableAction(
            id: "pasta",
            features: new List<object>() { new { taste = "salty", spiceLevel = "medium" }, new { nutritionLevel = 5, cuisine = "italian" } }
        ),

        new PersonalizerRankableAction(
            id: "ice cream",
            features: new List<object>() { new { taste = "sweet", spiceLevel = "none" }, new { nutritionalLevel = 2 } }
        ),

        new PersonalizerRankableAction(
            id: "juice",
            features: new List<object>() { new { taste = "sweet", spiceLevel = "none" }, new { nutritionLevel = 5 }, new { drink = true } }
        ),

        new PersonalizerRankableAction(
            id: "salad",
            features: new List<object>() { new { taste = "salty", spiceLevel = "low" }, new { nutritionLevel = 8 } }
        )
    };

    return actions;
}

获取上下文的用户首选项

将以下方法添加到 Program 类,以从命令行获取用户的日期时间输入及用户口味偏好。 它们将用作上下文特征。

static string GetTimeOfDayForContext()
{
    string[] timeOfDayFeatures = new string[] { "morning", "afternoon", "evening", "night" };

    Console.WriteLine("\nWhat time of day is it (enter number)? 1. morning 2. afternoon 3. evening 4. night");
    if (!int.TryParse(GetKey(), out int timeIndex) || timeIndex < 1 || timeIndex > timeOfDayFeatures.Length)
    {
        Console.WriteLine("\nEntered value is invalid. Setting feature value to " + timeOfDayFeatures[0] + ".");
        timeIndex = 1;
    }

    return timeOfDayFeatures[timeIndex - 1];
}
static string GetUsersTastePreference()
{
    string[] tasteFeatures = new string[] { "salty", "sweet" };
    var random = new Random();
    var taste = random.Next(1, 2);

    Console.WriteLine("\nWhat type of food would you prefer (enter number)? 1. salty 2. sweet");
    if (!int.TryParse(GetKey(), out int tasteIndex) || tasteIndex < 1 || tasteIndex > tasteFeatures.Length)
    {
        Console.WriteLine("\nEntered value is invalid. Setting feature value to " + tasteFeatures[0] + ".");
        tasteIndex = 1;
    }

    return tasteFeatures[taste - 1];
}

这两个方法都使用 GetKey 方法从命令行读取用户的选择。

private static string GetKey()
{
    return Console.ReadKey().Key.ToString().Last().ToString().ToUpper();
}
private static IList<object> GetContext(string time, string taste)
{
    return new List<object>()
    {
        new { time = time },
        new { taste = taste }
    };
}

创建学习循环

个性化体验创建服务学习循环是一个排名和奖励调用周期。 在本快速入门中,用于个性化内容的每个排名调用都后接一个奖励调用,该奖励调用让个性化体验创建服务知道该服务的表现如何。

以下代码会循环调用这样一个循环:通过命令行询问用户的首选项,将该信息发送给个性化体验创建服务来为每个槽选择最佳操作,向客户显示所选项以让他们从列表中进行选择,然后向个性化体验创建服务发送奖励评分,指出服务在做选择时的表现如何。

static void Main(string[] args)
{
    Console.WriteLine($"Welcome to this Personalizer Quickstart!\n" +
    $"This code will help you understand how to use the Personalizer APIs (rank and reward).\n" +
    $"Each iteration represents a user interaction and will demonstrate how context, actions, and rewards work.\n" +
    $"Note: Personalizer AI models learn from a large number of user interactions:\n" +
    $"You won't be able to tell the difference in what Personalizer returns by simulating a few events by hand.\n" +
    $"If you want a sample that focuses on seeing how Personalizer learns, see the Python Notebook sample.");

    int iteration = 1;
    bool runLoop = true;

    IList<PersonalizerRankableAction> actions = GetActions();
    PersonalizerClient client = InitializePersonalizerClient(new Uri(ServiceEndpoint));

    do
    {
        Console.WriteLine("\nIteration: " + iteration++);

        string timeOfDayFeature = GetTimeOfDayForContext();
        string deviceFeature = GetUsersTastePreference();

        IList<object> currentContext = GetContext(timeOfDayFeature, deviceFeature);

        string eventId = Guid.NewGuid().ToString();

        var rankOptions = new PersonalizerRankOptions(actions: actions, contextFeatures: currentContext, eventId: eventId);
        PersonalizerRankResult rankResult = client.Rank(rankOptions);

        Console.WriteLine("\nPersonalizer service thinks you would like to have: " + rankResult.RewardActionId + ". Is this correct? (y/n)");

        float reward = 0.0f;
        string answer = GetKey();

        if (answer == "Y")
        {
            reward = 1.0f;
            Console.WriteLine("\nGreat! Enjoy your food.");
        }
        else if (answer == "N")
        {
            reward = 0.0f;
            Console.WriteLine("\nYou didn't like the recommended food choice.");
        }
        else
        {
            Console.WriteLine("\nEntered choice is invalid. Service assumes that you didn't like the recommended food choice.");
        }

        client.Reward(rankResult.EventId, reward);

        Console.WriteLine("\nPress q to break, any other key to continue:");
        runLoop = !(GetKey() == "Q");

    } while (runLoop);
}

运行程序

从应用程序目录,使用 dotnet run 命令运行应用程序。

dotnet run

快速入门程序会提出一些问题来收集用户的偏好(称为“特征”),然后提供排名最高的操作。