将智能应用提升到新水平:使用 Azure 机器学习实现高级功能(第 2 部分)
在这个由四部分组成的系列中,您将学习如何使用 Azure 容器应用创建智能应用。在第四个也是最后一个部分中,您将探索如何将自定义模型集成到智能应用中,通过专门的 AI 增强应用功能。
在本四部分系列的第一和第二篇文章中,我们探讨了如何使用Azure 容器应用构建智能应用,其中整合了Azure AI来对用户反馈进行情感分析。在第三篇文章中,我们使用目标数据训练了一个自定义 AI 模型。
在本教程的第四部分也是最后一部分中,我们将把这些在 Azure 机器学习 (ML) 中训练的自定义模型集成到我们创建的智能应用中。我们将部署并利用一个端点来充分利用这种集成。您的应用用户将受益于快速确定记录的情感,从而能够及时采取行动。
必备组件
要遵循本教程,我们需要:
- 已下载第一部分中创建的项目
- 一个 Azure 账户
- Docker Desktop 3.5.1 或更高版本
- 已安装 Visual Studio。本演示使用 Community Edition 2022。
- 我们在第三部分训练的自定义 AI 模型。
要查看最终应用程序的概览,请查看完整的项目代码。
让我们开始吧。
准备测试和验证增强型智能应用
设置端点环境
要将我们的模型与应用程序一起使用,我们首先需要将其注册以用于托管端点。为此,请单击“模型”菜单项以查看环境中的模型列表。
如果您没有训练模型,或者更喜欢预构建的模型,请将示例模型文件解压缩到其自己的目录中,然后选择“从本地文件”。确保模型类型为“MLflow”,这与我们训练的模型类型匹配。
从解压缩的文件夹中上传所有这些文件。您的文件夹应该简单且不含空格,因为您稍后需要在代码中引用它。为您的模型选择一个名称和版本并注册它。
对于某些模型,您可以使用内置的端点创建过程。但是,在撰写本文时,我们的模型在启动之前需要对端点和环境进行一些自定义。
首先,让我们使用最小的端点容器构建一个自定义环境。转到左侧菜单中的“环境”。您会发现两种环境类型选项:“策展”和“自定义”。在本教程中,我们将策展镜像转换为自定义镜像,因此单击“策展”选项卡。找到最小推理服务器镜像。在撰写本文时,它被称为`minimal-ubuntu20.04-py38-cpu-inference`,但版本可能已更改。它是一个支持某些管道的 ML 端点的最小 Docker 镜像。
单击图像的“上下文”选项卡以获取其 Dockerfile 和 Conda 依赖文件。使用“下载内容”选项下载这些配置文件。这将下载一个包含这些文件的*.zip*存档,因此请解压缩它们并将它们放在自己的目录中以进行自定义。
返回环境屏幕中的“自定义”选项卡,然后点击“创建”以创建新的自定义环境。为该环境命名。对于“选择环境源”,选择“上传现有 docker 上下文”并选择您之前下载的最小服务器文件夹。
单击“下一步”。Azure ML 将允许您修改环境。要添加依赖项,请更新第 8 行下的列表。配置文件的外观应如下所示
name: minimal
channels:
- anaconda
- conda-forge
dependencies:
- python=3.8.13
- pip=22.1.2
- pip:
- torch
- pandas==1.1.5
- psutil>=5.2.2,<6.0.0
- mlflow-skinny
- inference-schema
- azureml-defaults~=1.51.0
- azureml.automl.dnn.nlp
由于这是一个 YAML 文件,我们需要确保每行项目上的制表符都是正确的。这个更新的配置文件为我们的模型添加了基本的 Python 数据科学库,包括:
mlflow-skinny
,一个 MLFlow 机器学习库的“运行时”版本inference-schema
,它驱动我们推理服务器的输入和输出azureml-defaults
,其中包括一些默认代码和库来运行 AzureML 库azureml.automl.dnn.nlp
,我们用它来训练我们的模型
创建端点
环境设置好后,我们现在可以为我们的应用程序创建端点。打开“端点”菜单,然后点击“创建”以创建一个新端点。在第一个窗口中,选择您之前注册的模型,然后点击“选择”。然后,点击“更多选项”来配置端点。为您的端点命名,保持“托管”选项已选中,并确保在下一个窗口中选择了您的模型。
部署屏幕允许您调整实时探测、评分超时和更改其他配置。但目前,让我们坚持使用默认设置。
接下来,我们可以自定义我们的环境和评分脚本。选择切换按钮以启用自定义,选择您创建的环境,并添加一个评分脚本——当您向端点发送数据时运行的自定义代码。
创建一个名为 score.py 的新脚本并粘贴此代码
from cmath import log
import logging
import os
import json
import mlflow
from io import StringIO
from mlflow.pyfunc.scoring_server import infer_and_parse_json_input, predictions_to_json
def init():
global model
global input_schema
model_path = os.getenv("AZUREML_MODEL_DIR") + "/ReviewSentiment"
model = mlflow.pyfunc.load_model(model_path)
input_schema = model.metadata.get_input_schema()
def run(raw_data):
json_data = json.loads(raw_data)
if "review" not in json_data.keys():
raise Exception("Request must contain a top level key named 'review'")
serving_input = { "inputs": json_data["review"] }
data = infer_and_parse_json_input(serving_input, input_schema)
predictions = model.predict(data)
return predictions
此代码包含两个函数:`init`,用于加载和准备模型;`run`,用于对模型使用我们的数据输入。
在 `init` 函数中,我们使用环境变量“`AZUREML_MODEL_DIR`”来引用 Azure ML 存储模型文件的位置。您还应该在此变量之后看到一个附加文件夹——这是我们上传或检索模型作业时存储模型文件的基本文件夹。
接下来,我们使用 `mlflow` 库中的 `load_model` 函数和输入 schema 加载模型,这启用了输入验证。这会预加载端点的所有组件,因此当客户端请求分析时,我们无需等待项目启动。
现在,让我们看看 `run` 函数。它接收原始数据作为 JSON 对象,将其加载到一个名为 `json_data` 的变量中,并检查 JSON 数据是否包含 review 键,这允许您对输入进行基本审查。
接下来,我们需要根据 `mlflow` 模型的要求格式化我们的输入。在这种情况下,我们期望 API 接受以下格式的对象
{ "inputs": <JSON-Object> }.
我们使用 `infer_and_parse_json_input` 方法将此输入发送到模型进行预测。
评分脚本已准备就绪,环境也已选择,现在是选择“计算”来运行我们的端点容器的时候了。在此演示中,我们使用内存优化型计算实例,以便端点有足够的空间来加载和使用模型。根据模型,您可能需要不同的计算大小,特别是如果您没有使用预训练模型。如果在部署期间遇到资源错误,请根据需要调整大小。
我们还可以定义发送到此部署的流量。Azure ML 为具有多个部署的托管端点设置负载均衡器,通常用于 A/B 测试或推出新模型版本等任务。
配置完成后,点击“创建”开始部署。这大约需要五到十分钟,期间 Azure ML 会组装资源和环境。
测试有效载荷
部署端点后,我们可以测试模型可以评分的有效载荷。正如我们的代码中引用的那样,我们需要确保此输入采用名为 `review` 的键/值对,并且输入类型预计为数组。
让我们尝试一个简单的例子。打开端点,点击“测试”,然后在“输入数据以测试端点”框中输入以下代码
{
"review": ["This Product was so awesome"]
}
运行此测试后,您应该会收到一个 JSON 对象,其中包含一个 `predictions` 键,其中包含一个值为 `True` 的数组,表示我们刚刚留下的正面评价。
尽管我们的端点用于实时使用,但我们仍然可以通过在输入数组中指定请求来批量处理请求。但如果实时性能不重要,我们可以按设定的时间间隔(例如每 15 分钟)收集评论,并将其转换为异步工作流。
为了演示,我们尝试一个更大的有效负载。输入以下测试数据
{
"review": [
"This Product was so awesome",
"I really did like this product",
"I'm a little bit disappointed by this item"
]
}
这一次,端点响应所需时间会稍长一些,但数组中应包含两个积极(`True`)和一个消极(`False`)。
您可以通过查看部署日志来观察这些预测的实际效果。
从您的应用访问机器学习端点
模型训练完成且端点就绪后,我们现在可以从现有应用程序调用端点。首先,为数据库添加一个新字段以存储新的模型预测。在 Visual Studio 中打开项目,并在 `Models` 目录中的 `Review.cs` 文件中添加以下行
public string CustomSentiment { get; set; }
接下来,在开发人员 PowerShell 终端窗口中,从项目文件夹运行这些命令以更新数据库
dotnet ef migrations add NewReviewField
dotnet ef database update
有了这个新字段,请通过添加 `CustomSentinent` 值来更新您的 Review `Index.cshtml` 页面,当我们在 URL `/reviews` 上访问时,该值会列出我们的评论。
<td>
@Html.DisplayFor(modelItem => item.CustomSentiment)
</td>
现在,让我们将端点的样板代码集成到我们的应用程序中以处理评论。
返回 Azure ML Studio,从左侧菜单打开“端点”,单击您已部署的端点,然后选择“使用”。您将看到 Python、C# 和 R 的代码片段。从 `InvokeRequestResponseService` 方法复制所有内容,然后切换回您的应用程序。将代码粘贴到 `Review` 控制器中的 `Create` 方法中,紧接在从 Azure AI 服务 API 检索情感之后。
现在,将代码精简如下
var handler = new HttpClientHandler()
{
ClientCertificateOptions = ClientCertificateOption.Manual,
ServerCertificateCustomValidationCallback =
(httpRequestMessage, cert, cetChain, policyErrors) => { return true; }
};
using (var client = new HttpClient(handler))
{
var reviewModel = new AIModel();
reviewModel.review.Add(review.ReviewText);
var requestBody = JsonConvert.SerializeObject(reviewModel);
const string apiKey = "endpoint-key";
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", apiKey);
client.BaseAddress =
new Uri("https://userreviewsentimentendpoint.eastus.inference.ml.azure.com/score");
var content = new StringContent(requestBody);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await client.PostAsync("", content);
if (response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
var data = JsonConvert.DeserializeObject<List<string>>(result);
review.CustomSentiment = data.First();
}
}
通过对样板代码进行这些修改和清理,此块现在可以:
- 使用我们的评论文本填充一个新类 `AIModel`
- 创建标准的 .NET HTTP 客户端
- 将评论信息发送到端点
- 等待值数组并传递以写入数据库
现在,为了确保模型接收到 API 期望的相同类型的值(一个字符串数组),我们需要创建 `AIModel` 类,如下所示:
public class AIModel
{
public List<string> review { get; set; }
public AIModel()
{
review = new List<string>();
}
}
这将向模型发送一个 JSON 转换的评论字符串数组。
测试和验证增强型智能应用
最后,让我们构建并运行我们的应用程序以测试结果。当网页打开时,导航到 `/Reviews/Create` 并输入一个示例评论,让应用程序从 Azure AI 服务和我们的自定义 AI 端点生成响应。选择一个类别并输入文本“This product is awesome.”
点击“创建”。这次过程会稍微长一些,因为我们同时调用了 Azure AI 服务 API 和我们的自定义 AI API。但是一旦过程完成并返回到评论屏幕,您将看到 Azure AI 分析和自定义情感都被标记为积极(`True`)。
比较我们教程示例的结果,您可能会注意到 Azure AI 模型和我们自定义模型之间存在可忽略不计的差异。这可能是由于各种原因造成的。
- 我们使用的短语非常笼统,没有提供太多细节。
- 我们用于训练模型的数据非常广泛,类似于 Azure AI。
- 该数据是开源的,也可能被用于训练 Azure AI 模型。
然而,对于我们的演示,我们期望更长、更具体的评论。所以,让我们尝试一个类似于真实反馈的评论:“这本可以是一个好产品,但电池寿命存在一些问题。不过,交货时间很快,价格也合理。”
这次,我们的自定义模型显示情感为真,而 Azure AI 将其归类为混合。多亏了我们使用的训练数据,我们的模型在评论情感方面做出了更清晰的决定。
我们再试一个:“价格便宜,也完成了任务,但我应该买更大的型号。”
现在,Azure AI 将此评论分析为基本中性,而我们的 AI 服务将其分析为负面。Azure AI 和我们自定义训练的模型都为文本提供了出色的情感分析。然而,自定义模型还可以根据随时间收集的数据提供专门的分析或附加功能。
如果您的应用程序具有更广泛的功能和数据,您可以构建更复杂的模型,分析多列数据或根据历史操作做出决策,从而进一步将 AI 集成到您的工作流程中。
结论
在本文中,我们通过整合自定义 AI 模型扩展了我们的应用程序。我们还将自定义构建的模型与 Azure AI 进行了比较。
虽然现成的解决方案提供通用功能,但自定义模型的能力允许针对特定任务进行微调。例如,您可以使用这些知识为小众电商平台创建定制的推荐系统,迎合传统模型可能忽略的细微购买模式。凭借训练定制模型的能力,您已准备好超越通用解决方案,释放 AI 在专业应用中的真正潜力。
查看Azure Machine Learning,集成更高级的 AI 功能,并将您的智能应用程序提升到新的水平。