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

快速入门:语言理解 (LUIS) 客户端库和 REST API

重要

LUIS 将于 2025 年 10 月 1 日停用,从 2023 年 4 月 1 日开始,你将无法创建新的 LUIS 资源。 建议将 LUIS 应用程序迁移对话语言理解,以便从持续的产品支持和多语言功能中受益。

通过此快速入门,使用 C#、Python 或 JavaScript 创建并查询带有 LUIS SDK 客户端库的 Azure LUIS 人工智能 (AI) 应用。 还可以使用 cURL 来发送使用 REST API 的请求。

通过语言理解 (LUIS),你可在用户的自然语言对话文本中应用自然语言处理 (NLP),以预测整体含义并提炼出相关的详细信息。

  • 使用“创作”客户端库和 REST API,可以创建、编辑、训练和发布 LUIS 应用。
  • 使用“预测运行时”客户端库和 REST API,可以查询已发布的应用。

使用适用于 .NET 的语言理解 (LUIS) 客户端库执行以下操作:

  • 创建应用
  • 使用示例言语添加意向(机器学习实体)
  • 训练和发布应用
  • 查询预测运行时

参考文档 | 创作预测库源代码 | 创作预测 NuGet | C# 示例

先决条件

  • .NET Core.NET Core CLI 的当前版本。
  • Azure 订阅 - 免费创建订阅
  • 有了 Azure 订阅后,在 Azure 门户中创建语言理解创作资源,以获取创作密钥和终结点。 等待其部署并单击“转到资源”按钮。
    • 需要从创建的资源获取密钥和终结点,以便将应用程序连接到语言理解创作。 你稍后会在快速入门中将密钥和终结点粘贴到下方的代码中。 可以使用免费定价层 (F0) 来试用该服务。

设置

新建 C# 应用程序

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

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

    dotnet new console -n language-understanding-quickstart
    
  2. 将目录更改为新创建的应用文件夹。

    cd language-understanding-quickstart
    
  3. 可使用以下代码生成应用程序:

    dotnet build
    

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

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

安装 NuGet 库

在应用程序目录中,使用以下命令安装适用于 .NET 的语言理解 (LUIS) 客户端库:

dotnet add package Microsoft.Azure.CognitiveServices.Language.LUIS.Authoring --version 3.2.0-preview.3
dotnet add package Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime --version 3.1.0-preview.1

创作对象模型

语言理解 (LUIS) 创作客户端是对 Azure 进行身份验证的 LUISAuthoringClient 对象,其中包含创作密钥。

创作的代码示例

创建客户端后,可以使用此客户端访问如下所述的功能:

预测对象模型

语言理解 (LUIS) 预测运行时客户端是对 Azure 进行身份验证的 LUISRuntimeClient 对象,其中包含资源密钥。

预测运行时的代码示例

创建客户端后,可以使用此客户端访问如下所述的功能:

代码示例

以下代码片段演示如何使用适用于 Python 的语言理解 (LUIS) 客户端库来执行以下操作:

添加依赖项

在首选的编辑器或 IDE 中,从项目目录打开 Program.cs 文件。 将现有 using 代码替换为以下 using 指令:

using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.CognitiveServices.Language.LUIS.Authoring;
using Microsoft.Azure.CognitiveServices.Language.LUIS.Authoring.Models;
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime;
using Microsoft.Azure.CognitiveServices.Language.LUIS.Runtime.Models;
using Newtonsoft.Json;

添加样板代码

  1. 更改 Main 方法的签名以允许异步调用:

    public static async Task Main()
    
  2. 将其余代码添加到 Program 类的 Main 方法中(除非另有指定)。

为应用创建变量

创建两组变量:第一组为你更改的变量,第二组保留在代码示例中显示的状态。

重要

完成后,请记住将密钥从代码中删除,并且永远不要公开发布该密钥。 对于生产来说,请使用安全的方式存储和访问凭据,例如 Azure Key Vault。 有关详细信息,请参阅 Azure AI 服务安全性一文。

  1. 创建用于保存创作密钥和资源名称的变量。

    var key = "PASTE_YOUR_LUIS_AUTHORING_SUBSCRIPTION_KEY_HERE";
    
    var authoringEndpoint = "PASTE_YOUR_LUIS_AUTHORING_ENDPOINT_HERE";
    var predictionEndpoint = "PASTE_YOUR_LUIS_PREDICTION_ENDPOINT_HERE";
    
  2. 创建用于保存终结点、应用名称、版本和意向名称的变量。

    var appName = "Contoso Pizza Company";
    var versionId = "0.1";
    var intentName = "OrderPizzaIntent";
    

验证客户端

使用密钥创建 ApiKeyServiceClientCredentials 对象,并在终结点中使用该对象创建一个 LUISAuthoringClient 对象。

var credentials = new Microsoft.Azure.CognitiveServices.Language.LUIS.Authoring.ApiKeyServiceClientCredentials(key);
var client = new LUISAuthoringClient(credentials) { Endpoint = authoringEndpoint };

创建 LUIS 应用

LUIS 应用包含自然语言处理 (NLP) 模型,包括意向、实体和示例言语。

创建 ApplicationCreateObject。 名称和语言区域性是必需的属性。 调用 Apps.AddAsync 方法。 响应为应用 ID。

var newApp = new ApplicationCreateObject
{
    Culture = "en-us",
    Name = appName,
    InitialVersionId = versionId
};

var appId = await client.Apps.AddAsync(newApp);

为应用创建意向

LUIS 应用模型中的主要对象是意向。 意向与用户言语意向的分组相符。 用户可以提问,或者做出表述,指出希望机器人(或其他客户端应用程序)提供特定的有针对性响应。 意向的示例包括预订航班、询问目的地城市的天气,以及询问客户服务的联系信息。

使用唯一意向的名称创建 ModelCreateObject,然后将应用 ID、版本 ID 和 ModelCreateObject 传递给 Model.AddIntentAsync 方法。 响应为意向 ID。

intentName 值硬编码为 OrderPizzaIntent,作为intentName中变量的一部分。

await client.Model.AddIntentAsync(appId, versionId, new ModelCreateObject()
{
    Name = intentName
});

为应用创建实体

尽管实体不是必需的,但在大多数应用中都可以看到实体。 实体从用户言语中提取信息,只有使用这些信息才能实现用户的意向。 有多种类型的预生成实体和自定义实体,每种实体具有自身的数据转换对象 (DTO) 模型。 在应用中添加的常见预生成实体包括 numberdatetimeV2geographyV2ordinal

必须知道,实体不会使用意向进行标记。 它们可以并且通常应用到多个意向。 只会为特定的单个意向标记示例用户言语。

实体的创建方法属于 Model 类的一部分。 每个实体类型有自身的数据转换对象 (DTO) 模型,该模型通常在 model 命名空间中包含单词 model

实体创建代码会创建机器学习实体,其中包含子实体以及应用于 Quantity 子实体的功能。

Partial screenshot from portal showing the entity created, a machine-learning entity with subentities and features applied to the `Quantity` subentities.

// Add Prebuilt entity
await client.Model.AddPrebuiltAsync(appId, versionId, new[] { "number" });

// Define ml entity with children and grandchildren
var mlEntityDefinition = new EntityModelCreateObject
{
    Name = "Pizza order",
    Children = new[]
    {
        new ChildEntityModelCreateObject
        {
            Name = "Pizza",
            Children = new[]
            {
                new ChildEntityModelCreateObject { Name = "Quantity" },
                new ChildEntityModelCreateObject { Name = "Type" },
                new ChildEntityModelCreateObject { Name = "Size" }
            }
        },
        new ChildEntityModelCreateObject
        {
            Name = "Toppings",
            Children = new[]
            {
                new ChildEntityModelCreateObject { Name = "Type" },
                new ChildEntityModelCreateObject { Name = "Quantity" }
            }
        }
    }
};

// Add ML entity 
var mlEntityId = await client.Model.AddEntityAsync(appId, versionId, mlEntityDefinition); ;

// Add phraselist feature
var phraselistId = await client.Features.AddPhraseListAsync(appId, versionId, new PhraselistCreateObject
{
    EnabledForAllModels = false,
    IsExchangeable = true,
    Name = "QuantityPhraselist",
    Phrases = "few,more,extra"
});

// Get entity and subentities
var model = await client.Model.GetEntityAsync(appId, versionId, mlEntityId);
var toppingQuantityId = GetModelGrandchild(model, "Toppings", "Quantity");
var pizzaQuantityId = GetModelGrandchild(model, "Pizza", "Quantity");

// add model as feature to subentity model
await client.Features.AddEntityFeatureAsync(appId, versionId, pizzaQuantityId, new ModelFeatureInformation { ModelName = "number", IsRequired = true });
await client.Features.AddEntityFeatureAsync(appId, versionId, toppingQuantityId, new ModelFeatureInformation { ModelName = "number"});

// add phrase list as feature to subentity model
await client.Features.AddEntityFeatureAsync(appId, versionId, toppingQuantityId, new ModelFeatureInformation { FeatureName = "QuantityPhraselist" });

对该类使用以下方法,查找 Quantity 子实体的 ID,以便将功能分配给该子实体。

static Guid GetModelGrandchild(NDepthEntityExtractor model, string childName, string grandchildName)
{
    return model.Children.
        Single(c => c.Name == childName).
        Children.
        Single(c => c.Name == grandchildName).Id;
}

将示例言语添加到意向

为了确定言语的意向并提取实体,应用需要言语示例。 这些示例需要针对特定的单个意向,并且应该标记所有自定义实体。 无需标记预生成实体。

通过创建 ExampleLabelObject 对象的列表来添加示例言语(每个示例言语对应于一个对象)。 每个示例应使用实体名称和实体值的名称/值对字典来标记所有实体。 实体值应与示例言语文本中显示的值完全相同。

Partial screenshot showing the labeled example utterance in the portal.

结合应用 ID、版本 ID 和示例调用 Examples.AddAsync

// Define labeled example
var labeledExampleUtteranceWithMLEntity = new ExampleLabelObject
{
    Text = "I want two small seafood pizzas with extra cheese.",
    IntentName = intentName,
    EntityLabels = new[]
    {
        new EntityLabelObject
        {
            StartCharIndex = 7,
            EndCharIndex = 48,
            EntityName = "Pizza order",
            Children = new[]
            {
                new EntityLabelObject
                {
                    StartCharIndex = 7,
                    EndCharIndex = 30,
                    EntityName = "Pizza",
                    Children = new[]
                    {
                        new EntityLabelObject { StartCharIndex = 7, EndCharIndex = 9, EntityName = "Quantity" },
                        new EntityLabelObject { StartCharIndex = 11, EndCharIndex = 15, EntityName = "Size" },
                        new EntityLabelObject { StartCharIndex = 17, EndCharIndex = 23, EntityName = "Type" }
                    }
                },
                new EntityLabelObject
                {
                    StartCharIndex = 37,
                    EndCharIndex = 48,
                    EntityName = "Toppings",
                    Children = new[]
                    {
                        new EntityLabelObject { StartCharIndex = 37, EndCharIndex = 41, EntityName = "Quantity" },
                        new EntityLabelObject { StartCharIndex = 43, EndCharIndex = 48, EntityName = "Type" }
                    }
                }
            }
        },
    }
};

// Add an example for the entity.
// Enable nested children to allow using multiple models with the same name.
// The quantity subentity and the phraselist could have the same exact name if this is set to True
await client.Examples.AddAsync(appId, versionId, labeledExampleUtteranceWithMLEntity, enableNestedChildren: true); 

训练应用

创建模型后,需要为此模型版本训练 LUIS 应用。 训练后的模型可在容器中使用,或者将其发布到过渡槽或生产槽。

Train.TrainVersionAsync 方法需要应用 ID 和版本 ID。

极小的模型(如本快速入门中所示的模型)很快就能完成训练。 对于生产级应用程序,应用的训练应该包括轮询调用 GetStatusAsync 方法以确定训练何时或者是否成功。 响应是一个 ModelTrainingInfo 对象列表,其中分别列出了每个对象的状态。 所有对象必须成功,才能将训练视为完成。

await client.Train.TrainVersionAsync(appId, versionId);
while (true)
{
    var status = await client.Train.GetStatusAsync(appId, versionId);
    if (status.All(m => m.Details.Status == "Success"))
    {
        // Assumes that we never fail, and that eventually we'll always succeed.
        break;
    }
}

将应用发布到生产槽

使用 PublishAsync 方法发布 LUIS 应用。 这会将当前已训练的版本发布到终结点上的指定槽。 客户端应用程序使用此终结点发送用户言语,以预测意向和提取实体。

await client.Apps.PublishAsync(appId, new ApplicationPublishObject { VersionId = versionId, IsStaging=false});

对预测运行时客户端进行身份验证

ApiKeyServiceClientCredentials 对象和密钥一起使用,并在终结点中使用该对象创建一个 LUISRuntimeClient 对象。

注意

此快速入门使用创作密钥作为运行时凭据的一部分。 允许创作密钥通过几个查询来查询运行时。 对于暂存和生产级别的代码,请将创作密钥替换为预测运行时密钥。

var runtimeClient = new LUISRuntimeClient(credentials) { Endpoint = predictionEndpoint };

从运行时获取预测

添加以下代码以创建对预测运行时的请求。

用户言语是 PredictionRequest 对象的一部分。

GetSlotPredictionAsync 方法需要多个参数,如应用 ID、槽名称、用于满足请求的预测请求对象。 其他选项(如详细、显示所有意向和日志)都是可选的。

// Production == slot name
var request = new PredictionRequest { Query = "I want two small pepperoni pizzas with more salsa" };
var prediction = await runtimeClient.Prediction.GetSlotPredictionAsync(appId, "Production", request);
Console.Write(JsonConvert.SerializeObject(prediction, Formatting.Indented));

预测响应是一个 JSON 对象,其中包括意向和找到的所有实体。

{
    "query": "I want two small pepperoni pizzas with more salsa",
    "prediction": {
        "topIntent": "OrderPizzaIntent",
        "intents": {
            "OrderPizzaIntent": {
                "score": 0.753606856
            },
            "None": {
                "score": 0.119097039
            }
        },
        "entities": {
            "Pizza order": [
                {
                    "Pizza": [
                        {
                            "Quantity": [
                                2
                            ],
                            "Type": [
                                "pepperoni"
                            ],
                            "Size": [
                                "small"
                            ],
                            "$instance": {
                                "Quantity": [
                                    {
                                        "type": "builtin.number",
                                        "text": "two",
                                        "startIndex": 7,
                                        "length": 3,
                                        "score": 0.968156934,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Type": [
                                    {
                                        "type": "Type",
                                        "text": "pepperoni",
                                        "startIndex": 17,
                                        "length": 9,
                                        "score": 0.9345611,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Size": [
                                    {
                                        "type": "Size",
                                        "text": "small",
                                        "startIndex": 11,
                                        "length": 5,
                                        "score": 0.9592077,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ]
                            }
                        }
                    ],
                    "Toppings": [
                        {
                            "Type": [
                                "salsa"
                            ],
                            "Quantity": [
                                "more"
                            ],
                            "$instance": {
                                "Type": [
                                    {
                                        "type": "Type",
                                        "text": "salsa",
                                        "startIndex": 44,
                                        "length": 5,
                                        "score": 0.7292897,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Quantity": [
                                    {
                                        "type": "Quantity",
                                        "text": "more",
                                        "startIndex": 39,
                                        "length": 4,
                                        "score": 0.9320932,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ]
                            }
                        }
                    ],
                    "$instance": {
                        "Pizza": [
                            {
                                "type": "Pizza",
                                "text": "two small pepperoni pizzas",
                                "startIndex": 7,
                                "length": 26,
                                "score": 0.812199831,
                                "modelTypeId": 1,
                                "modelType": "Entity Extractor",
                                "recognitionSources": [
                                    "model"
                                ]
                            }
                        ],
                        "Toppings": [
                            {
                                "type": "Toppings",
                                "text": "more salsa",
                                "startIndex": 39,
                                "length": 10,
                                "score": 0.7250252,
                                "modelTypeId": 1,
                                "modelType": "Entity Extractor",
                                "recognitionSources": [
                                    "model"
                                ]
                            }
                        ]
                    }
                }
            ],
            "$instance": {
                "Pizza order": [
                    {
                        "type": "Pizza order",
                        "text": "two small pepperoni pizzas with more salsa",
                        "startIndex": 7,
                        "length": 42,
                        "score": 0.769223332,
                        "modelTypeId": 1,
                        "modelType": "Entity Extractor",
                        "recognitionSources": [
                            "model"
                        ]
                    }
                ]
            }
        }
    }
}

运行应用程序

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

dotnet run

使用适用于 Node.js 的语言理解 (LUIS) 客户端库来执行以下操作:

  • 创建应用
  • 使用示例言语添加意向(机器学习实体)
  • 训练和发布应用
  • 查询预测运行时

参考文档 | 创作预测 NPM | 示例

先决条件

  • Node.js
  • Azure 订阅 - 免费创建订阅
  • 有了 Azure 订阅后,在 Azure 门户中创建语言理解创作资源,以获取创作密钥和终结点。 等待其部署并单击“转到资源”按钮。
    • 需要从创建的资源获取密钥和终结点,以便将应用程序连接到语言理解创作。 你稍后会在快速入门中将密钥和终结点粘贴到下方的代码中。 可以使用免费定价层 (F0) 来试用该服务。

设置

创建新的 JavaScript 应用程序

  1. 在控制台窗口中,为应用程序创建一个新目录,并将其移动到该目录中。

    mkdir quickstart-sdk && cd quickstart-sdk
    
  2. 通过创建 package.json 文件,将该目录初始化为 JavaScript 应用程序。

    npm init -y
    
  3. 为 JavaScript 代码创建名为 index.js 的文件。

    touch index.js
    

安装 NPM 库

在应用程序目录中,使用以下命令安装依赖项,每次执行一行:

npm install @azure/ms-rest-js
npm install @azure/cognitiveservices-luis-authoring
npm install @azure/cognitiveservices-luis-runtime

package.json 应如下所示:

{
  "name": "quickstart-sdk",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@azure/cognitiveservices-luis-authoring": "^4.0.0-preview.3",
    "@azure/cognitiveservices-luis-runtime": "^5.0.0",
    "@azure/ms-rest-js": "^2.0.8"
  }
}

创作对象模型

语言理解 (LUIS) 创作客户端是对 Azure 进行身份验证的 LUISAuthoringClient 对象,其中包含创作密钥。

创作的代码示例

创建客户端后,可以使用此客户端访问如下所述的功能:

预测对象模型

语言理解 (LUIS) 创作客户端是对 Azure 进行身份验证的 LUISAuthoringClient 对象,其中包含创作密钥。

预测运行时的代码示例

创建客户端后,可以使用此客户端访问如下所述的功能:

代码示例

以下代码片段演示如何使用适用于 Python 的语言理解 (LUIS) 客户端库来执行以下操作:

添加依赖项

在首选编辑器或 IDE 中打开 index.js 文件,并添加以下依赖项。

const msRest = require("@azure/ms-rest-js");
const LUIS_Authoring = require("@azure/cognitiveservices-luis-authoring");
const LUIS_Prediction = require("@azure/cognitiveservices-luis-runtime");

添加样板代码

  1. 添加 quickstart 方法及其调用。 此方法保存大部分剩余代码。 在文件末尾调用此方法。

    const quickstart = async () => {
    
        // add calls here
    
    
    }
    quickstart()
        .then(result => console.log("Done"))
        .catch(err => {
            console.log(`Error: ${err}`)
            })
    
  2. 在 quickstart 方法中添加剩余代码(除非另有指定)。

为应用创建变量

创建两组变量:第一组为你更改的变量,第二组保留在代码示例中显示的状态。

重要

完成后,请记住将密钥从代码中删除,并且永远不要公开发布该密钥。 对于生产来说,请使用安全的方式存储和访问凭据,例如 Azure Key Vault。 有关详细信息,请参阅 Azure AI 服务安全性一文。

  1. 创建用于保存创作密钥和资源名称的变量。

    const authoringKey = 'PASTE_YOUR_LUIS_AUTHORING_SUBSCRIPTION_KEY_HERE';
    
    const authoringEndpoint = "PASTE_YOUR_LUIS_AUTHORING_ENDPOINT_HERE";
    const predictionEndpoint = "PASTE_YOUR_LUIS_PREDICTION_ENDPOINT_HERE";
    
  2. 创建用于保存终结点、应用名称、版本和意向名称的变量。

    const appName = "Contoso Pizza Company";
    const versionId = "0.1";
    const intentName = "OrderPizzaIntent";
    

验证客户端

使用密钥创建 CognitiveServicesCredentials 对象,并在终结点中使用该对象创建一个 LUISAuthoringClient 对象。

const luisAuthoringCredentials = new msRest.ApiKeyCredentials({
    inHeader: { "Ocp-Apim-Subscription-Key": authoringKey }
});
const client = new LUIS_Authoring.LUISAuthoringClient(
    luisAuthoringCredentials,
    authoringEndpoint
);

创建 LUIS 应用

LUIS 应用包含自然语言处理 (NLP) 模型,包括意向、实体和示例言语。

创建 AppsOperation 对象的 add 方法,用于创建应用。 名称和语言区域性是必需的属性。

const create_app_payload = {
    name: appName,
    initialVersionId: versionId,
    culture: "en-us"
};

const createAppResult = await client.apps.add(
    create_app_payload
);

const appId = createAppResult.body

为应用创建意向

LUIS 应用模型中的主要对象是意向。 意向与用户言语意向的分组相符。 用户可以提问,或者做出表述,指出希望机器人(或其他客户端应用程序)提供特定的有针对性响应。 意向的示例包括预订航班、询问目的地城市的天气,以及询问客户服务的联系信息。

model.add_intent 方法与唯一意向的名称配合使用,然后传递应用 ID、版本 ID 和新的意向名称。

intentName 值硬编码为 OrderPizzaIntent,作为intentName中变量的一部分。

await client.model.addIntent(
    appId,
    versionId,
    { name: intentName }
);

为应用创建实体

尽管实体不是必需的,但在大多数应用中都可以看到实体。 实体从用户言语中提取信息,只有使用这些信息才能实现用户的意向。 有多种类型的预生成实体和自定义实体,每种实体具有自身的数据转换对象 (DTO) 模型。 在应用中添加的常见预生成实体包括 numberdatetimeV2geographyV2ordinal

必须知道,实体不会使用意向进行标记。 它们可以并且通常应用到多个意向。 只会为特定的单个意向标记示例用户言语。

实体的创建方法属于 Model 类的一部分。 每个实体类型有自身的数据转换对象 (DTO) 模型。

实体创建代码会创建机器学习实体,其中包含子实体以及应用于 Quantity 子实体的功能。

Partial screenshot from portal showing the entity created, a machine-learning entity with subentities and features applied to the `Quantity` subentities.

// Add Prebuilt entity
await client.model.addPrebuilt(appId, versionId, ["number"]);

// Define ml entity with children and grandchildren
const mlEntityDefinition = {
    name: "Pizza order",
    children: [
        {
            name: "Pizza",
            children: [
                { name: "Quantity" },
                { name: "Type" },
                { name: "Size" }
            ]
        },
        {
            name: "Toppings",
            children: [
                { name: "Type" },
                { name: "Quantity" }
            ]
        }
    ]
};

// Add ML entity 
const response = await client.model.addEntity(appId, versionId, mlEntityDefinition);
const mlEntityId = response.body;

// Add phraselist feature
const phraselistResponse = await client.features.addPhraseList(appId, versionId, {
    enabledForAllModels: false,
    isExchangeable: true,
    name: "QuantityPhraselist",
    phrases: "few,more,extra"
});
const phraseListId = phraselistResponse.body;

// Get entity and subentities
const model = await client.model.getEntity(appId, versionId, mlEntityId);
const toppingQuantityId = getModelGrandchild(model, "Toppings", "Quantity");
const pizzaQuantityId = getModelGrandchild(model, "Pizza", "Quantity");

// add model as feature to subentity model
await client.features.addEntityFeature(appId, versionId, pizzaQuantityId, { modelName: "number", isRequired: true });
await client.features.addEntityFeature(appId, versionId, toppingQuantityId, { modelName: "number" });

// add phrase list as feature to subentity model
await client.features.addEntityFeature(appId, versionId, toppingQuantityId, { featureName: "QuantityPhraselist" });

将以下方法置于 quickstart 方法之上,查找 Quantity 子实体的 ID,以便将功能分配给该子实体。

const getModelGrandchild = (model, childName, grandchildName) => {

    return model.children.find(c => c.name == childName).children.find(c => c.name == grandchildName).id

}

将示例言语添加到意向

为了确定言语的意向并提取实体,应用需要言语示例。 这些示例需要针对特定的单个意向,并且应该标记所有自定义实体。 无需标记预生成实体。

通过创建 ExampleLabelObject 对象的列表来添加示例言语(每个示例言语对应于一个对象)。 每个示例应使用实体名称和实体值的名称/值对字典来标记所有实体。 实体值应与示例言语文本中显示的值完全相同。

Partial screenshot showing the labeled example utterance in the portal.

结合应用 ID、版本 ID 和示例调用 examples.add

// Define labeled example
const labeledExampleUtteranceWithMLEntity =
{
    text: "I want two small seafood pizzas with extra cheese.",
    intentName: intentName,
    entityLabels: [
        {
            startCharIndex: 7,
            endCharIndex: 48,
            entityName: "Pizza order",
            children: [
                {
                    startCharIndex: 7,
                    endCharIndex: 30,
                    entityName: "Pizza",
                    children: [
                        {
                            startCharIndex: 7,
                            endCharIndex: 9,
                            entityName: "Quantity"
                        },
                        {
                            startCharIndex: 11,
                            endCharIndex: 15,
                            entityName: "Size"
                        },
                        {
                            startCharIndex: 17,
                            endCharIndex: 23,
                            entityName: "Type"
                        }]
                },
                {
                    startCharIndex: 37,
                    endCharIndex: 48,
                    entityName: "Toppings",
                    children: [
                        {
                            startCharIndex: 37,
                            endCharIndex: 41,
                            entityName: "Quantity"
                        },
                        {
                            startCharIndex: 43,
                            endCharIndex: 48,
                            entityName: "Type"
                        }]
                }
            ]
        }
    ]
};

console.log("Labeled Example Utterance:", JSON.stringify(labeledExampleUtteranceWithMLEntity, null, 4 ));

// Add an example for the entity.
// Enable nested children to allow using multiple models with the same name.
// The quantity subentity and the phraselist could have the same exact name if this is set to True
await client.examples.add(appId, versionId, labeledExampleUtteranceWithMLEntity, { enableNestedChildren: true });

训练应用

创建模型后,需要为此模型版本训练 LUIS 应用。 训练后的模型可在容器中使用,或者将其发布到过渡槽或生产槽。

train.trainVersion 方法需要应用 ID 和版本 ID。

极小的模型(如本快速入门中所示的模型)很快就能完成训练。 对于生产级应用程序,应用的训练应该包括轮询调用 get_status 方法以确定训练何时成功或者是否成功。 响应是一个 ModelTrainingInfo 对象列表,其中分别列出了每个对象的状态。 所有对象必须成功,才能将训练视为完成。

await client.train.trainVersion(appId, versionId);
while (true) {
    const status = await client.train.getStatus(appId, versionId);
    if (status.every(m => m.details.status == "Success")) {
        // Assumes that we never fail, and that eventually we'll always succeed.
        break;
    }
}

将应用发布到生产槽

使用 app.publish 方法发布 LUIS 应用。 这会将当前已训练的版本发布到终结点上的指定槽。 客户端应用程序使用此终结点发送用户言语,以预测意向和提取实体。

await client.apps.publish(appId, { versionId: versionId, isStaging: false });

对预测运行时客户端进行身份验证

将 msRest.ApiKeyCredentials 对象与密钥一起使用,并在终结点中使用该对象创建一个 LUIS.LUISRuntimeClient 对象。

注意

此快速入门使用创作密钥作为运行时凭据的一部分。 允许创作密钥通过几个查询来查询运行时。 对于暂存和生产级别的代码,请将创作密钥替换为预测运行时密钥。

const luisPredictionClient = new LUIS_Prediction.LUISRuntimeClient(
    luisAuthoringCredentials,
    predictionEndpoint
);

从运行时获取预测

添加以下代码以创建对预测运行时的请求。 用户言语是 predictionRequest 对象的一部分。

luisRuntimeClient.prediction.getSlotPrediction 方法需要多个参数,如应用 ID、槽名称、用于满足请求的预测请求对象。 其他选项(如详细、显示所有意向和日志)都是可选的。

// Production == slot name
const request = { query: "I want two small pepperoni pizzas with more salsa" };
const response = await luisPredictionClient.prediction.getSlotPrediction(appId, "Production", request);
console.log(JSON.stringify(response.prediction, null, 4 ));

预测响应是一个 JSON 对象,其中包括意向和找到的所有实体。

{
    "query": "I want two small pepperoni pizzas with more salsa",
    "prediction": {
        "topIntent": "OrderPizzaIntent",
        "intents": {
            "OrderPizzaIntent": {
                "score": 0.753606856
            },
            "None": {
                "score": 0.119097039
            }
        },
        "entities": {
            "Pizza order": [
                {
                    "Pizza": [
                        {
                            "Quantity": [
                                2
                            ],
                            "Type": [
                                "pepperoni"
                            ],
                            "Size": [
                                "small"
                            ],
                            "$instance": {
                                "Quantity": [
                                    {
                                        "type": "builtin.number",
                                        "text": "two",
                                        "startIndex": 7,
                                        "length": 3,
                                        "score": 0.968156934,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Type": [
                                    {
                                        "type": "Type",
                                        "text": "pepperoni",
                                        "startIndex": 17,
                                        "length": 9,
                                        "score": 0.9345611,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Size": [
                                    {
                                        "type": "Size",
                                        "text": "small",
                                        "startIndex": 11,
                                        "length": 5,
                                        "score": 0.9592077,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ]
                            }
                        }
                    ],
                    "Toppings": [
                        {
                            "Type": [
                                "salsa"
                            ],
                            "Quantity": [
                                "more"
                            ],
                            "$instance": {
                                "Type": [
                                    {
                                        "type": "Type",
                                        "text": "salsa",
                                        "startIndex": 44,
                                        "length": 5,
                                        "score": 0.7292897,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Quantity": [
                                    {
                                        "type": "Quantity",
                                        "text": "more",
                                        "startIndex": 39,
                                        "length": 4,
                                        "score": 0.9320932,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ]
                            }
                        }
                    ],
                    "$instance": {
                        "Pizza": [
                            {
                                "type": "Pizza",
                                "text": "two small pepperoni pizzas",
                                "startIndex": 7,
                                "length": 26,
                                "score": 0.812199831,
                                "modelTypeId": 1,
                                "modelType": "Entity Extractor",
                                "recognitionSources": [
                                    "model"
                                ]
                            }
                        ],
                        "Toppings": [
                            {
                                "type": "Toppings",
                                "text": "more salsa",
                                "startIndex": 39,
                                "length": 10,
                                "score": 0.7250252,
                                "modelTypeId": 1,
                                "modelType": "Entity Extractor",
                                "recognitionSources": [
                                    "model"
                                ]
                            }
                        ]
                    }
                }
            ],
            "$instance": {
                "Pizza order": [
                    {
                        "type": "Pizza order",
                        "text": "two small pepperoni pizzas with more salsa",
                        "startIndex": 7,
                        "length": 42,
                        "score": 0.769223332,
                        "modelTypeId": 1,
                        "modelType": "Entity Extractor",
                        "recognitionSources": [
                            "model"
                        ]
                    }
                ]
            }
        }
    }
}

运行应用程序

在快速入门文件中使用 node index.js 命令运行应用程序。

node index.js

使用适用于 Python 的语言理解 (LUIS) 客户端库来执行以下操作:

  • 创建应用
  • 使用示例言语添加意向(机器学习实体)
  • 训练和发布应用
  • 查询预测运行时

参考文档 | 创作预测库源代码 | 包 (Pypi) | 示例

先决条件

  • 最新版本的 Python 3.x
  • Azure 订阅 - 免费创建订阅
  • 有了 Azure 订阅后,在 Azure 门户中创建语言理解创作资源,以获取创作密钥和终结点。 等待其部署并单击“转到资源”按钮。
    • 需要从创建的资源获取密钥和终结点,以便将应用程序连接到语言理解创作。 你稍后会在快速入门中将密钥和终结点粘贴到下方的代码中。 可以使用免费定价层 (F0) 来试用该服务。

设置

创建新的 Python 应用程序

  1. 在控制台窗口中,为应用程序创建一个新目录,并将其移动到该目录中。

    mkdir quickstart-sdk && cd quickstart-sdk
    
  2. 为 Python 代码创建名为 authoring_and_predict.py 的文件。

    touch authoring_and_predict.py
    

使用 Pip 安装客户端库

在应用程序目录中,使用以下命令安装适用于 python 的语言理解 (LUIS) 客户端库:

pip install azure-cognitiveservices-language-luis

创作对象模型

语言理解 (LUIS) 创作客户端是对 Azure 进行身份验证的 LUISAuthoringClient 对象,其中包含创作密钥。

创作的代码示例

创建客户端后,可以使用此客户端访问如下所述的功能:

预测对象模型

语言理解 (LUIS) 预测运行时客户端是对 Azure 进行身份验证的 LUISRuntimeClient 对象,其中包含资源密钥。

预测运行时的代码示例

创建客户端后,可以使用此客户端访问如下所述的功能:

代码示例

以下代码片段演示如何使用适用于 Python 的语言理解 (LUIS) 客户端库来执行以下操作:

添加依赖项

将客户端库添加到 python 文件中。

from azure.cognitiveservices.language.luis.authoring import LUISAuthoringClient
from azure.cognitiveservices.language.luis.authoring.models import ApplicationCreateObject
from azure.cognitiveservices.language.luis.runtime import LUISRuntimeClient
from msrest.authentication import CognitiveServicesCredentials
from functools import reduce

import json, time, uuid

添加样板代码

  1. 添加 quickstart 方法及其调用。 此方法保存大部分剩余代码。 在文件末尾调用此方法。

    def quickstart():
    
        # add calls here, remember to indent properly
    
    quickstart()
    
  2. 在 quickstart 方法中添加剩余代码(除非另有指定)。

为应用创建变量

创建两组变量:第一组为你更改的变量,第二组保留在代码示例中显示的状态。

重要

完成后,请记住将密钥从代码中删除,并且永远不要公开发布该密钥。 对于生产来说,请使用安全的方式存储和访问凭据,例如 Azure Key Vault。 有关详细信息,请参阅 Azure AI 服务安全性一文。

  1. 创建用于保存创作密钥和资源名称的变量。

    authoringKey = 'PASTE_YOUR_LUIS_AUTHORING_SUBSCRIPTION_KEY_HERE'
    authoringEndpoint = 'PASTE_YOUR_LUIS_AUTHORING_ENDPOINT_HERE'
    predictionKey = 'PASTE_YOUR_LUIS_PREDICTION_SUBSCRIPTION_KEY_HERE'
    predictionEndpoint = 'PASTE_YOUR_LUIS_PREDICTION_ENDPOINT_HERE'
    
  2. 创建用于保存终结点、应用名称、版本和意向名称的变量。

    # We use a UUID to avoid name collisions.
    appName = "Contoso Pizza Company " + str(uuid.uuid4())
    versionId = "0.1"
    intentName = "OrderPizzaIntent"
    

验证客户端

使用密钥创建 CognitiveServicesCredentials 对象,并在终结点中使用该对象创建一个 LUISAuthoringClient 对象。

client = LUISAuthoringClient(authoringEndpoint, CognitiveServicesCredentials(authoringKey))

创建 LUIS 应用

LUIS 应用包含自然语言处理 (NLP) 模型,包括意向、实体和示例言语。

创建 AppsOperation 对象的 add 方法,用于创建应用。 名称和语言区域性是必需的属性。

# define app basics
appDefinition = ApplicationCreateObject (name=appName, initial_version_id=versionId, culture='en-us')

# create app
app_id = client.apps.add(appDefinition)

# get app id - necessary for all other changes
print("Created LUIS app with ID {}".format(app_id))

为应用创建意向

LUIS 应用模型中的主要对象是意向。 意向与用户言语意向的分组相符。 用户可以提问,或者做出表述,指出希望机器人(或其他客户端应用程序)提供特定的有针对性响应。 意向的示例包括预订航班、询问目的地城市的天气,以及询问客户服务的联系信息。

model.add_intent 方法与唯一意向的名称配合使用,然后传递应用 ID、版本 ID 和新的意向名称。

intentName 值硬编码为 OrderPizzaIntent,作为intentName中变量的一部分。

client.model.add_intent(app_id, versionId, intentName)

为应用创建实体

尽管实体不是必需的,但在大多数应用中都可以看到实体。 实体从用户言语中提取信息,只有使用这些信息才能实现用户的意向。 有多种类型的预生成实体和自定义实体,每种实体具有自身的数据转换对象 (DTO) 模型。 在应用中添加的常见预生成实体包括 numberdatetimeV2geographyV2ordinal

必须知道,实体不会使用意向进行标记。 它们可以并且通常应用到多个意向。 只会为特定的单个意向标记示例用户言语。

实体的创建方法属于 ModelOperations 类的一部分。 每个实体类型有自身的数据转换对象 (DTO) 模型。

实体创建代码会创建机器学习实体,其中包含子实体以及应用于 Quantity 子实体的功能。

Partial screenshot from portal showing the entity created, a machine-learning entity with subentities and features applied to the `Quantity` subentities.

# Add Prebuilt entity
client.model.add_prebuilt(app_id, versionId, prebuilt_extractor_names=["number"])

# define machine-learned entity
mlEntityDefinition = [
{
    "name": "Pizza",
    "children": [
        { "name": "Quantity" },
        { "name": "Type" },
        { "name": "Size" }
    ]
},
{
    "name": "Toppings",
    "children": [
        { "name": "Type" },
        { "name": "Quantity" }
    ]
}]

# add entity to app
modelId = client.model.add_entity(app_id, versionId, name="Pizza order", children=mlEntityDefinition)

# define phraselist - add phrases as significant vocabulary to app
phraseList = {
    "enabledForAllModels": False,
    "isExchangeable": True,
    "name": "QuantityPhraselist",
    "phrases": "few,more,extra"
}

# add phrase list to app
phraseListId = client.features.add_phrase_list(app_id, versionId, phraseList)

# Get entity and subentities
modelObject = client.model.get_entity(app_id, versionId, modelId)
toppingQuantityId = get_grandchild_id(modelObject, "Toppings", "Quantity")
pizzaQuantityId = get_grandchild_id(modelObject, "Pizza", "Quantity")

# add model as feature to subentity model
prebuiltFeatureRequiredDefinition = { "model_name": "number", "is_required": True }
client.features.add_entity_feature(app_id, versionId, pizzaQuantityId, prebuiltFeatureRequiredDefinition)

# add model as feature to subentity model
prebuiltFeatureNotRequiredDefinition = { "model_name": "number" }
client.features.add_entity_feature(app_id, versionId, toppingQuantityId, prebuiltFeatureNotRequiredDefinition)

# add phrase list as feature to subentity model
phraseListFeatureDefinition = { "feature_name": "QuantityPhraselist", "model_name": None }
client.features.add_entity_feature(app_id, versionId, toppingQuantityId, phraseListFeatureDefinition)

将以下方法置于 quickstart 方法之上,查找 Quantity 子实体的 ID,以便将功能分配给该子实体。

def get_grandchild_id(model, childName, grandChildName):
    
    theseChildren = next(filter((lambda child: child.name == childName), model.children))
    theseGrandchildren = next(filter((lambda child: child.name == grandChildName), theseChildren.children))
    
    grandChildId = theseGrandchildren.id
    
    return grandChildId

将示例言语添加到意向

为了确定言语的意向并提取实体,应用需要言语示例。 这些示例需要针对特定的单个意向,并且应该标记所有自定义实体。 无需标记预生成实体。

通过创建 ExampleLabelObject 对象的列表来添加示例言语(每个示例言语对应于一个对象)。 每个示例应使用实体名称和实体值的名称/值对字典来标记所有实体。 实体值应与示例言语文本中显示的值完全相同。

Partial screenshot showing the labeled example utterance in the portal.

结合应用 ID、版本 ID 和示例调用 examples.add

# Define labeled example
labeledExampleUtteranceWithMLEntity = {
    "text": "I want two small seafood pizzas with extra cheese.",
    "intentName": intentName,
    "entityLabels": [
        {
            "startCharIndex": 7,
            "endCharIndex": 48,
            "entityName": "Pizza order",
            "children": [
                {
                    "startCharIndex": 7,
                    "endCharIndex": 30,
                    "entityName": "Pizza",
                    "children": [
                        {
                            "startCharIndex": 7,
                            "endCharIndex": 9,
                            "entityName": "Quantity"
                        },
                        {
                            "startCharIndex": 11,
                            "endCharIndex": 15,
                            "entityName": "Size"
                        },
                        {
                            "startCharIndex": 17,
                            "endCharIndex": 23,
                            "entityName": "Type"
                        }]
                },
                {
                    "startCharIndex": 37,
                    "endCharIndex": 48,
                    "entityName": "Toppings",
                    "children": [
                        {
                            "startCharIndex": 37,
                            "endCharIndex": 41,
                            "entityName": "Quantity"
                        },
                        {
                            "startCharIndex": 43,
                            "endCharIndex": 48,
                            "entityName": "Type"
                        }]
                }
            ]
        }
    ]
}

print("Labeled Example Utterance:", labeledExampleUtteranceWithMLEntity)

# Add an example for the entity.
# Enable nested children to allow using multiple models with the same name.
# The quantity subentity and the phraselist could have the same exact name if this is set to True
client.examples.add(app_id, versionId, labeledExampleUtteranceWithMLEntity, { "enableNestedChildren": True })

训练应用

创建模型后,需要为此模型版本训练 LUIS 应用。 训练后的模型可在容器中使用,或者将其发布到过渡槽或生产槽。

train.train_version 方法需要应用 ID 和版本 ID。

极小的模型(如本快速入门中所示的模型)很快就能完成训练。 对于生产级应用程序,应用的训练应该包括轮询调用 get_status 方法以确定训练何时成功或者是否成功。 响应是一个 ModelTrainingInfo 对象列表,其中分别列出了每个对象的状态。 所有对象必须成功,才能将训练视为完成。

client.train.train_version(app_id, versionId)
waiting = True
while waiting:
    info = client.train.get_status(app_id, versionId)

    # get_status returns a list of training statuses, one for each model. Loop through them and make sure all are done.
    waiting = any(map(lambda x: 'Queued' == x.details.status or 'InProgress' == x.details.status, info))
    if waiting:
        print ("Waiting 10 seconds for training to complete...")
        time.sleep(10)
    else: 
        print ("trained")
        waiting = False

将应用发布到生产槽

使用 app.publish 方法发布 LUIS 应用。 这会将当前已训练的版本发布到终结点上的指定槽。 客户端应用程序使用此终结点发送用户言语,以预测意向和提取实体。

# Mark the app as public so we can query it using any prediction endpoint.
# Note: For production scenarios, you should instead assign the app to your own LUIS prediction endpoint. See:
# https://docs.microsoft.com/en-gb/azure/cognitive-services/luis/luis-how-to-azure-subscription#assign-a-resource-to-an-app
client.apps.update_settings(app_id, is_public=True)

responseEndpointInfo = client.apps.publish(app_id, versionId, is_staging=False)

对预测运行时客户端进行身份验证

将凭据对象与密钥一起使用,并在终结点中使用该对象创建一个 LUISRuntimeClientConfiguration 对象。

注意

此快速入门使用创作密钥作为运行时凭据的一部分。 允许创作密钥通过几个查询来查询运行时。 对于暂存和生产级别的代码,请将创作密钥替换为预测运行时密钥。

runtimeCredentials = CognitiveServicesCredentials(predictionKey)
clientRuntime = LUISRuntimeClient(endpoint=predictionEndpoint, credentials=runtimeCredentials)

从运行时获取预测

添加以下代码以创建对预测运行时的请求。

用户言语是 prediction_request 对象的一部分。

get_slot_prediction 方法需要多个参数,如应用 ID、槽名称,以及用于履行请求的预测请求对象。 其他选项(如详细、显示所有意向和日志)都是可选的。 该请求返回 PredictionResponse 对象。

# Production == slot name
predictionRequest = { "query" : "I want two small pepperoni pizzas with more salsa" }

predictionResponse = clientRuntime.prediction.get_slot_prediction(app_id, "Production", predictionRequest)
print("Top intent: {}".format(predictionResponse.prediction.top_intent))
print("Sentiment: {}".format (predictionResponse.prediction.sentiment))
print("Intents: ")

for intent in predictionResponse.prediction.intents:
    print("\t{}".format (json.dumps (intent)))
print("Entities: {}".format (predictionResponse.prediction.entities))

预测响应是一个 JSON 对象,其中包括意向和找到的所有实体。

{
    "query": "I want two small pepperoni pizzas with more salsa",
    "prediction": {
        "topIntent": "OrderPizzaIntent",
        "intents": {
            "OrderPizzaIntent": {
                "score": 0.753606856
            },
            "None": {
                "score": 0.119097039
            }
        },
        "entities": {
            "Pizza order": [
                {
                    "Pizza": [
                        {
                            "Quantity": [
                                2
                            ],
                            "Type": [
                                "pepperoni"
                            ],
                            "Size": [
                                "small"
                            ],
                            "$instance": {
                                "Quantity": [
                                    {
                                        "type": "builtin.number",
                                        "text": "two",
                                        "startIndex": 7,
                                        "length": 3,
                                        "score": 0.968156934,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Type": [
                                    {
                                        "type": "Type",
                                        "text": "pepperoni",
                                        "startIndex": 17,
                                        "length": 9,
                                        "score": 0.9345611,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Size": [
                                    {
                                        "type": "Size",
                                        "text": "small",
                                        "startIndex": 11,
                                        "length": 5,
                                        "score": 0.9592077,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ]
                            }
                        }
                    ],
                    "Toppings": [
                        {
                            "Type": [
                                "salsa"
                            ],
                            "Quantity": [
                                "more"
                            ],
                            "$instance": {
                                "Type": [
                                    {
                                        "type": "Type",
                                        "text": "salsa",
                                        "startIndex": 44,
                                        "length": 5,
                                        "score": 0.7292897,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ],
                                "Quantity": [
                                    {
                                        "type": "Quantity",
                                        "text": "more",
                                        "startIndex": 39,
                                        "length": 4,
                                        "score": 0.9320932,
                                        "modelTypeId": 1,
                                        "modelType": "Entity Extractor",
                                        "recognitionSources": [
                                            "model"
                                        ]
                                    }
                                ]
                            }
                        }
                    ],
                    "$instance": {
                        "Pizza": [
                            {
                                "type": "Pizza",
                                "text": "two small pepperoni pizzas",
                                "startIndex": 7,
                                "length": 26,
                                "score": 0.812199831,
                                "modelTypeId": 1,
                                "modelType": "Entity Extractor",
                                "recognitionSources": [
                                    "model"
                                ]
                            }
                        ],
                        "Toppings": [
                            {
                                "type": "Toppings",
                                "text": "more salsa",
                                "startIndex": 39,
                                "length": 10,
                                "score": 0.7250252,
                                "modelTypeId": 1,
                                "modelType": "Entity Extractor",
                                "recognitionSources": [
                                    "model"
                                ]
                            }
                        ]
                    }
                }
            ],
            "$instance": {
                "Pizza order": [
                    {
                        "type": "Pizza order",
                        "text": "two small pepperoni pizzas with more salsa",
                        "startIndex": 7,
                        "length": 42,
                        "score": 0.769223332,
                        "modelTypeId": 1,
                        "modelType": "Entity Extractor",
                        "recognitionSources": [
                            "model"
                        ]
                    }
                ]
            }
        }
    }
}

运行应用程序

在快速入门文件中使用 python 命令运行应用程序。

python authoring_and_predict.py

在本快速入门中,将按顺序执行三次 REST 调用。

参考文档

先决条件

  • 免费的 LUIS 帐户。

  • 文本编辑器,如 Visual Studio Code

  • 命令行程序 cURL。 在 macOS、大多数 Linux 分发版和 Windows 10 版本 1803 及更高版本上已安装该 cURL 程序。

    若需要安装 cURL,可在 cURL 下载页中下载 cURL。

创建 Pizza 应用

创建披萨应用。

  1. 选择 pizza-app-for-luis-v6.json,打开 pizza-app-for-luis.json 文件的 GitHub 页面。
  2. 右键单击或长按“原始”按钮,然后选择“将链接另存为”,将 保存到计算机。
  3. 登录到 LUIS 门户
  4. 选择我的应用
  5. 在“我的应用”页面上,选择“+ 新建用于对话的应用” 。
  6. 选择“导入为 JSON”。
  7. 在“导入新应用”对话框中,选择“选择文件”按钮 。
  8. 选择下载的 pizza-app-for-luis.json 文件,然后选择“打开”。
  9. 在“导入新应用”对话框的“名称”字段中,输入 Pizza 应用的名称,然后选择“完成”按钮 。

随即导入应用。

如果看到一个对话框“如何创建有效的 LUIS 应用”,关闭该对话框。

训练并发布 Pizza 应用

Pizza 应用中应会显示“意向”页面,其中显示了一个意向列表。

  1. 在 LUIS 网站的右上方,选择“训练”按钮。

    Train button

  2. 当“训练”按钮处于禁用状态时,即表示训练完成。

若要在聊天机器人或其他客户端应用程序中接收 LUIS 预测,需要将应用发布到预测终结点。

  1. 在右上方的导航栏中选择“发布”。

    A screenshot of the button for publishing to the endpoint.

  2. 选择“生产”槽,然后选择“完成” 。

    A screenshot of LUIS publishing to the endpoint.

  3. 在通知中选择“访问终结点 URL”,以转到“Azure 资源”页 。 只有你拥有与应用关联的预测资源时,才能看到 URL。 还可以单击“管理”来找到“Azure 资源”页 。

    A screenshot of a message showing the app has been published.

向披萨应用添加创作资源

  1. 选择“管理”。
  2. 选择“Azure 资源”。
  3. 选择“创作资源”。
  4. 选择“更改创作资源”。

如果你有创作资源,请输入你的创作资源的租户名称、订阅名称以及 LUIS 资源名称。

如果你没有创作资源:

  1. 选择“新建资源”。
  2. 输入租户名称、资源名称、订阅名称和 Azure 资源组名称。

现在 Pizza 应用可以使用了。

记录 Pizza 应用的访问值

若要使用新的披萨应用,你需要该披萨应用的应用 ID、授权密钥和授权终结点。 若要获取预测,需要单独的预测终结点和预测密钥。

若要查找这些值:

  1. 在“意向”页面,选择“管理” 。
  2. 在“应用程序设置”页面,记录“应用 ID” 。
  3. 选择“Azure 资源”。
  4. 选择“创作资源”。
  5. 从“创作资源”和“预测资源”选项卡,记录“主键” 。 此值是你的创作密钥。
  6. 记录“终结点 URL”。 此值是你的创作终结点。

创建 JSON 文件来训练 Pizza 应用

若要创建包含三个示例言语的 JSON 文件,请将以下 JSON 数据保存到名为 ExampleUtterances.JSON 的文件中:

[
  {
    "text": "order a pizza",
    "intentName": "ModifyOrder",
    "entityLabels": [
      {
        "entityName": "Order",
        "startCharIndex": 6,
        "endCharIndex": 12
      }
    ]
  },
  {
    "text": "order a large pepperoni pizza",
    "intentName": "ModifyOrder",
    "entityLabels": [
      {
        "entityName": "Order",
        "startCharIndex": 6,
        "endCharIndex": 28
      },
      {
        "entityName": "FullPizzaWithModifiers",
        "startCharIndex": 6,
        "endCharIndex": 28
      },
      {
        "entityName": "PizzaType",
        "startCharIndex": 14,
        "endCharIndex": 28
      },
      {
        "entityName": "Size",
        "startCharIndex": 8,
        "endCharIndex": 12
      }
    ]
  },
  {
    "text": "I want two large pepperoni pizzas on thin crust",
    "intentName": "ModifyOrder",
    "entityLabels": [
      {
        "entityName": "Order",
        "startCharIndex": 7,
        "endCharIndex": 46
      },
      {
        "entityName": "FullPizzaWithModifiers",
        "startCharIndex": 7,
        "endCharIndex": 46
      },
      {
        "entityName": "PizzaType",
        "startCharIndex": 17,
        "endCharIndex": 32
      },
      {
        "entityName": "Size",
        "startCharIndex": 11,
        "endCharIndex": 15
      },
      {
        "entityName": "Quantity",
        "startCharIndex": 7,
        "endCharIndex": 9
      },
      {
        "entityName": "Crust",
        "startCharIndex": 37,
        "endCharIndex": 46
      }
    ]
  }
]`

示例言语 JSON 遵循特定格式。

text 字段包含示例话语的文本。 intentName 字段必须对应于 LUIS 应用中的现有意向名称。 entityLabels 字段是必填的。 如果不想标记任何实体,请提供一个空数组。

如果 entityLabels 数组不为空,则 startCharIndexendCharIndex 需要标记 entityName 字段中引用的实体。 该索引从零开始。 如果标签的起始或结尾位于文本中的空白处,则添加话语的 API 调用将失败。

添加示例话语

  1. 若要上传这批示例言语,请将以下命令复制到文本编辑器中:

    curl "***YOUR-AUTHORING-ENDPOINT***/luis/authoring/v3.0-preview/apps/***YOUR-APP-ID***/versions/***YOUR-APP-VERSION***/examples?verbose=true&show-all-intents=true" ^
          --request POST ^
          --header "Content-Type:application/json" ^
          --header "Ocp-Apim-Subscription-Key: ***YOUR-AUTHORING-KEY***" ^
          --data "@ExampleUtterances.JSON"
    
  2. 将以 ***YOUR- 开头的值替换为你自己的值。

    信息 目的
    ***YOUR-AUTHORING-ENDPOINT*** 创作 URL 终结点。 例如,"https://REPLACE-WITH-YOUR-RESOURCE-NAME.api.cognitive.microsoft.com/"。 在创建资源时设置资源名称。
    ***YOUR-APP-ID*** LUIS 应用 ID。
    ***YOUR-APP-VERSION*** LUIS 应用版本。 对于 Pizza 应用,版本号为“0.1”(不含引号)。
    ***YOUR-AUTHORING-KEY*** 32 字符创作密钥。

    分配的密钥和资源可以在 LUIS 门户的“Azure 资源”页上的“管理”部分中看到。 应用 ID 可以在“应用程序设置”页的同一“管理”部分中找到。

    重要

    完成后,请记住将密钥从代码中删除,并且永远不要公开发布该密钥。 对于生产来说,请使用安全的方式存储和访问凭据,例如 Azure Key Vault。 有关详细信息,请参阅 Azure AI 服务安全性一文。

  3. 启动命令提示符 (Windows) 或终端(macOS 和 Linux),并将目录更改为保存 ExampleUtterances.JSON 文件的目录。

  4. 从编辑器中复制 cURL 命令,并将其粘贴到命令提示符 (Windows) 或终端(macOS 和 Linux)中。 按 Enter 执行该命令。

    应会看到以下响应:

    [{"value":{"ExampleId":1255129706,"UtteranceText":"order a pizza"},"hasError":false},{"value":{"ExampleId":1255129707,"UtteranceText":"order a large pepperoni pizza"},"hasError":false},{"value":{"ExampleId":1255129708,"UtteranceText":"i want two large pepperoni pizzas on thin crust"},"hasError":false}]
    

    下面是为提高可读性而进行了格式设置的输出:

    [
      {
        "value": {
          "ExampleId": 1255129706,
          "UtteranceText": "order a pizza"
        },
        "hasError": false
      },
      {
        "value": {
          "ExampleId": 1255129707,
          "UtteranceText": "order a large pepperoni pizza"
        },
        "hasError": false
      },
      {
        "value": {
          "ExampleId": 1255129708,
          "UtteranceText": "i want two large pepperoni pizzas on thin crust"
        },
        "hasError": false
      }
    ]
    

训练 Pizza 应用模型

  1. 若要开启 Pizza 应用的训练会话,请将以下命令复制到文本编辑器中:

    curl "***YOUR-AUTHORING-ENDPOINT***/luis/authoring/v3.0-preview/apps/***YOUR-APP-ID***/versions/***YOUR-APP-VERSION***/train?verbose=true&show-all-intents=true" ^
          --data "" ^
          --request POST ^
          --header "Content-Type:application/json" ^
          --header "Ocp-Apim-Subscription-Key: ***YOUR-AUTHORING-KEY***"
    
  2. 与之前所做的操作一样,将以 ***YOUR- 开头的值替换为你自己的值。

  3. 从编辑器中复制 cURL 命令,并将其粘贴到命令提示符 (Windows) 或终端(macOS 和 Linux)中。 按 Enter 执行该命令。

    应会看到以下响应:

    {"statusId":2,"status":"UpToDate"}
    

    下面是为提高可读性而进行了格式设置的输出:

    {
      "statusId": 2,
      "status": "UpToDate"
    }
    

获取训练状态

  1. 若要获取训练会话的训练状态,请将以下命令复制到文本编辑器中:

    curl "***YOUR-AUTHORING-ENDPOINT***/luis/authoring/v3.0-preview/apps/***YOUR-APP-ID***/versions/***YOUR-APP-VERSION***/train?verbose=true&show-all-intents=true" ^
            --request GET ^
            --header "Content-Type:application/json" ^
            --header "Ocp-Apim-Subscription-Key: ***YOUR-AUTHORING-KEY***"
    
  2. 与之前所做的操作一样,将以 ***YOUR- 开头的值替换为你自己的值。

  3. 从编辑器中复制 cURL 命令,并将其粘贴到命令提示符 (Windows) 或终端(macOS 和 Linux)中。 按 Enter 执行该命令。

    应会看到以下响应:

    [{"modelId":"8eb7ad8f-5db5-4c28-819b-ca3905fffd80","details":{"statusId":2,"status":"UpToDate","exampleCount":171}},{"modelId":"6f53bc92-ae54-44ce-bc4e-010d1f8cfda0","details":{"statusId":2,"status":"UpToDate","exampleCount":171}},{"modelId":"6cb17888-ad6e-464c-82c0-d37fd1f2c4f8","details":{"statusId":2,"status":"UpToDate","exampleCount":171}},{"modelId":"a16fc4fd-1949-4e77-9de3-30369f16c3a5","details":{"statusId":2,"status":"UpToDate","exampleCount":171}},{"modelId":"6bacdb75-1889-4f93-8971-8c8995ff8960","details":{"statusId":2,"status":"UpToDate","exampleCount":171}},{"modelId":"be963f4c-4898-48d7-9eba-3c6af0867b9d","details":{"statusId":2,"status":"UpToDate","exampleCount":171}}]
    

    下面是为提高可读性而进行了格式设置的输出:

    [
      {
        "modelId": "8eb7ad8f-5db5-4c28-819b-ca3905fffd80",
        "details": {
          "statusId": 2,
          "status": "UpToDate",
          "exampleCount": 171
        }
      },
      {
        "modelId": "6f53bc92-ae54-44ce-bc4e-010d1f8cfda0",
        "details": {
          "statusId": 2,
          "status": "UpToDate",
          "exampleCount": 171
        }
      },
      {
        "modelId": "6cb17888-ad6e-464c-82c0-d37fd1f2c4f8",
        "details": {
          "statusId": 2,
          "status": "UpToDate",
          "exampleCount": 171
        }
      },
      {
        "modelId": "a16fc4fd-1949-4e77-9de3-30369f16c3a5",
        "details": {
          "statusId": 2,
          "status": "UpToDate",
          "exampleCount": 171
        }
      },
      {
        "modelId": "6bacdb75-1889-4f93-8971-8c8995ff8960",
        "details": {
          "statusId": 2,
          "status": "UpToDate",
          "exampleCount": 171
        }
      },
      {
        "modelId": "be963f4c-4898-48d7-9eba-3c6af0867b9d",
        "details": {
          "statusId": 2,
          "status": "UpToDate",
          "exampleCount": 171
        }
      }
    ]
    

从预测终结点获取意向

使用 cURL 查询预测终结点并获取预测结果。

注意

此命令使用预测终结点。

  1. 请将以下命令复制到自己的文本编辑器中:

    curl "https://***YOUR-PREDICTION-ENDPOINT***/luis/prediction/v3.0/apps/***YOUR-APP-ID***/slots/production/predict" ^
          --request GET ^
          --get ^
          --data "subscription-key=***YOUR-PREDICTION-KEY***" ^
          --data "verbose=true" ^
          --data "show-all-intents=true" ^
          --data-urlencode "query=I want two large pepperoni pizzas on thin crust please"
    
  2. 将以 ***YOUR- 开头的值替换为你自己的值。

    信息 目的
    ***YOUR-PREDICTION-ENDPOINT*** 预测 URL 终结点。 位于 LUIS 门户中,你的应用的“Azure 资源”页。
    例如,https://westus.api.cognitive.microsoft.com/
    ***YOUR-APP-ID*** 你的应用程序 ID。 位于 LUIS 门户中,你的应用的“应用程序设置”页。
    ***YOUR-PREDICTION-KEY*** 32 字符预测密钥。 位于 LUIS 门户中,你的应用的“Azure 资源”页。
  3. 将文本复制到控制台窗口并按 Enter 执行该命令:

  4. 查看以 JSON 形式返回的预测响应:

    {"query":"I want two large pepperoni pizzas on thin crust please","prediction":{"topIntent":"ModifyOrder","intents":{"ModifyOrder":{"score":1.0},"None":{"score":8.55E-09},"Greetings":{"score":1.82222226E-09},"CancelOrder":{"score":1.47272727E-09},"Confirmation":{"score":9.8125E-10}},"entities":{"Order":[{"FullPizzaWithModifiers":[{"PizzaType":["pepperoni pizzas"],"Size":[["Large"]],"Quantity":[2],"Crust":[["Thin"]],"$instance":{"PizzaType":[{"type":"PizzaType","text":"pepperoni pizzas","startIndex":17,"length":16,"score":0.9978157,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}],"Size":[{"type":"SizeList","text":"large","startIndex":11,"length":5,"score":0.9984481,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}],"Quantity":[{"type":"builtin.number","text":"two","startIndex":7,"length":3,"score":0.999770939,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}],"Crust":[{"type":"CrustList","text":"thin crust","startIndex":37,"length":10,"score":0.933985531,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}]}}],"$instance":{"FullPizzaWithModifiers":[{"type":"FullPizzaWithModifiers","text":"two large pepperoni pizzas on thin crust","startIndex":7,"length":40,"score":0.90681237,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}]}}],"ToppingList":[["Pepperoni"]],"$instance":{"Order":[{"type":"Order","text":"two large pepperoni pizzas on thin crust","startIndex":7,"length":40,"score":0.9047088,"modelTypeId":1,"modelType":"Entity Extractor","recognitionSources":["model"]}],"ToppingList":[{"type":"ToppingList","text":"pepperoni","startIndex":17,"length":9,"modelTypeId":5,"modelType":"List Entity Extractor","recognitionSources":["model"]}]}}}}
    

    已通过格式化提高可读性的 JSON 响应:

    {
      "query": "I want two large pepperoni pizzas on thin crust please",
      "prediction": {
        "topIntent": "ModifyOrder",
        "intents": {
          "ModifyOrder": {
            "score": 1.0
          },
          "None": {
            "score": 8.55e-9
          },
          "Greetings": {
            "score": 1.82222226e-9
          },
          "CancelOrder": {
            "score": 1.47272727e-9
          },
          "Confirmation": {
            "score": 9.8125e-10
          }
        },
        "entities": {
          "Order": [
            {
              "FullPizzaWithModifiers": [
                {
                  "PizzaType": [
                    "pepperoni pizzas"
                  ],
                  "Size": [
                    [
                      "Large"
                    ]
                  ],
                  "Quantity": [
                    2
                  ],
                  "Crust": [
                    [
                      "Thin"
                    ]
                  ],
                  "$instance": {
                    "PizzaType": [
                      {
                        "type": "PizzaType",
                        "text": "pepperoni pizzas",
                        "startIndex": 17,
                        "length": 16,
                        "score": 0.9978157,
                        "modelTypeId": 1,
                        "modelType": "Entity Extractor",
                        "recognitionSources": [
                          "model"
                        ]
                      }
                    ],
                    "Size": [
                      {
                        "type": "SizeList",
                        "text": "large",
                        "startIndex": 11,
                        "length": 5,
                        "score": 0.9984481,
                        "modelTypeId": 1,
                        "modelType": "Entity Extractor",
                        "recognitionSources": [
                          "model"
                        ]
                      }
                    ],
                    "Quantity": [
                      {
                        "type": "builtin.number",
                        "text": "two",
                        "startIndex": 7,
                        "length": 3,
                        "score": 0.999770939,
                        "modelTypeId": 1,
                        "modelType": "Entity Extractor",
                        "recognitionSources": [
                          "model"
                        ]
                      }
                    ],
                    "Crust": [
                      {
                        "type": "CrustList",
                        "text": "thin crust",
                        "startIndex": 37,
                        "length": 10,
                        "score": 0.933985531,
                        "modelTypeId": 1,
                        "modelType": "Entity Extractor",
                        "recognitionSources": [
                          "model"
                        ]
                      }
                    ]
                  }
                }
              ],
              "$instance": {
                "FullPizzaWithModifiers": [
                  {
                    "type": "FullPizzaWithModifiers",
                    "text": "two large pepperoni pizzas on thin crust",
                    "startIndex": 7,
                    "length": 40,
                    "score": 0.90681237,
                    "modelTypeId": 1,
                    "modelType": "Entity Extractor",
                    "recognitionSources": [
                      "model"
                    ]
                  }
                ]
              }
            }
          ],
          "ToppingList": [
            [
              "Pepperoni"
            ]
          ],
          "$instance": {
            "Order": [
              {
                "type": "Order",
                "text": "two large pepperoni pizzas on thin crust",
                "startIndex": 7,
                "length": 40,
                "score": 0.9047088,
                "modelTypeId": 1,
                "modelType": "Entity Extractor",
                "recognitionSources": [
                  "model"
                ]
              }
            ],
            "ToppingList": [
              {
                "type": "ToppingList",
                "text": "pepperoni",
                "startIndex": 17,
                "length": 9,
                "modelTypeId": 5,
                "modelType": "List Entity Extractor",
                "recognitionSources": [
                  "model"
                ]
              }
            ]
          }
        }
      }
    }
    

清理资源

可从 LUIS 门户删除应用并从 Azure 门户删除 Azure 资源。

如果使用 REST API,请在完成快速入门后从文件系统中删除 ExampleUtterances.JSON 文件。

疑难解答

  • 对客户端库进行身份验证 - 身份验证错误通常表明使用了错误的密钥和终结点。 为了方便起见,此快速入门使用预测运行时的创作密钥和终结点,但只有在不超出每月配额的情况下才有效。 如果无法使用创作密钥和终结点,则需要在访问预测运行时 SDK 客户端库时使用预测运行时密钥和终结点。
  • 创建实体 - 如果在创建本教程中使用的嵌套式机器学习实体时遇到错误,请确保已复制代码且未更改代码以创建其他实体。
  • 创建示例言语 - 如果在创建本教程中使用的标记示例言语时遇到错误,请确保已复制代码且未更改代码以创建其他标记示例。
  • 训练 - 如果收到一条训练错误,则通常表示该应用为空(没有带示例言语的意图),或表示该应用的意图或实体格式错误。
  • 杂项错误 - 由于代码使用文本和 JSON 对象调用客户端库,所以请确保你没有更改代码。

其他错误 - 如果遇到以上列表中未涵盖的错误,请在此页面底部提供反馈,告知我们。 包括所安装的客户端库的编程语言和版本。

后续步骤