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

适用于 .NET 的 Azure 认知语言服务对话客户端库 - 版本 1.1.0

对话语言理解(简称 CLU)是一种基于云的对话 AI 服务,可提供许多语言理解功能,例如:

  • 对话应用:用于提取对话中的意向和实体
  • 工作流应用:充当业务流程协调程序,以选择分析对话的最佳候选项,以便从 Qna、Luis 和对话应用等应用获得最佳响应

源代码 | 包 (NuGet) | API 参考文档 | 样品 | 产品文档 | 分析 REST API 文档 | 创作 REST API 文档

入门

安装包

使用 NuGet 安装适用于 .NET 的 Azure 认知语言服务对话客户端库:

dotnet add package Azure.AI.Language.Conversations

先决条件

尽管可以使用此 SDK 创建和导入对话项目, 但 Language Studio 是创建项目的首选方法。

验证客户端

若要与 Conversations 服务交互,需要创建 类的 ConversationAnalysisClient 实例。 需要 一个终结点一个 API 密钥 来实例化客户端对象。 有关使用认知服务进行身份验证的详细信息,请参阅 对 Azure 认知服务的请求进行身份验证

获取 API 密钥

可以从 Azure 门户中的认知服务资源获取终结点API 密钥

或者,使用如下所示的 Azure CLI 命令从认知服务资源获取 API 密钥。

az cognitiveservices account keys list --resource-group <resource-group-name> --name <resource-name>

命名空间

首先导入 和 相关类的 ConversationAnalysisClient 命名空间:

using Azure.Core;
using Azure.AI.Language.Conversations;

创建 ConversationAnalysisClient

确定 终结点API 密钥 后,可以实例化 ConversationAnalysisClient

Uri endpoint = new Uri("https://myaccount.cognitiveservices.azure.com");
AzureKeyCredential credential = new AzureKeyCredential("{api-key}");

ConversationAnalysisClient client = new ConversationAnalysisClient(endpoint, credential);

创建 ConversationAuthoringClient

若要使用 ConversationAuthoringClient,除上述命名空间外,还使用以下命名空间(如果需要)。

using Azure.AI.Language.Conversations.Authoring;

使用 终结点API 密钥,可以实例化 ConversationAuthoringClient

Uri endpoint = new Uri("https://myaccount.cognitiveservices.azure.com");
AzureKeyCredential credential = new AzureKeyCredential("{api-key}");

ConversationAuthoringClient client = new ConversationAuthoringClient(endpoint, credential);

使用 Azure Active Directory 身份验证创建客户端

还可以创建 ConversationAnalysisClient 或使用 ConversationAuthoringClient Azure Active Directory (AAD) 身份验证。 必须为用户或服务主体分配“认知服务语言读取者”角色。 使用 DefaultAzureCredential ,可以使用托管标识或服务主体对服务进行身份验证、以开发人员身份处理应用程序等方式进行身份验证,而无需更改代码。

首先需要安装 Azure.Identity 包DefaultAzureCredential然后才能使用 或 Azure.Identity 中的任何凭据类型。

若要与客户端 ID 和机密一起使用 DefaultAzureCredential ,需要设置 AZURE_TENANT_IDAZURE_CLIENT_IDAZURE_CLIENT_SECRET 环境变量;或者,可以在 Azure.Identity 中将这些值传递给 ClientSecretCredential

请确保在源文件顶部使用 正确的命名空间 DefaultAzureCredential

using Azure.Identity;

然后,可以创建 的 DefaultAzureCredential 实例并将其传递给客户端的新实例:

Uri endpoint = new Uri("https://myaccount.cognitiveservices.azure.com");
DefaultAzureCredential credential = new DefaultAzureCredential();

ConversationAnalysisClient client = new ConversationAnalysisClient(endpoint, credential);

请注意,区域终结点不支持 AAD 身份验证。 请改为为资源 创建自定义域名 以使用 AAD 身份验证。

关键概念

ConversationAnalysisClient

ConversationAnalysisClient是使用已部署的对话模型进行预测的主要接口。 它提供同步 API 和异步 API 来提交查询。

线程安全

我们保证所有客户端实例方法都是线程安全的,并且相互独立, (准则) 。 这可确保重用客户端实例的建议始终是安全的,即使跨线程也是如此。

其他概念

客户端选项 | 访问响应 | 长时间运行的操作 | 处理失败 | 诊断 | 嘲笑 | 客户端生存期

示例

Azure.AI.Language.Conversations 客户端库提供同步和异步 API。

以下示例演示了使用 client上面创建的 的常见方案。

分析对话

若要分析对话,可以调用 AnalyzeConversation() 方法:

string projectName = "Menu";
string deploymentName = "production";

var data = new
{
    analysisInput = new
    {
        conversationItem = new
        {
            text = "Send an email to Carol about tomorrow's demo",
            id = "1",
            participantId = "1",
        }
    },
    parameters = new
    {
        projectName,
        deploymentName,

        // Use Utf16CodeUnit for strings in .NET.
        stringIndexType = "Utf16CodeUnit",
    },
    kind = "Conversation",
};

Response response = client.AnalyzeConversation(RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(response.ContentStream);
JsonElement conversationalTaskResult = result.RootElement;
JsonElement conversationPrediction = conversationalTaskResult.GetProperty("result").GetProperty("prediction");

Console.WriteLine($"Top intent: {conversationPrediction.GetProperty("topIntent").GetString()}");

Console.WriteLine("Intents:");
foreach (JsonElement intent in conversationPrediction.GetProperty("intents").EnumerateArray())
{
    Console.WriteLine($"Category: {intent.GetProperty("category").GetString()}");
    Console.WriteLine($"Confidence: {intent.GetProperty("confidenceScore").GetSingle()}");
    Console.WriteLine();
}

Console.WriteLine("Entities:");
foreach (JsonElement entity in conversationPrediction.GetProperty("entities").EnumerateArray())
{
    Console.WriteLine($"Category: {entity.GetProperty("category").GetString()}");
    Console.WriteLine($"Text: {entity.GetProperty("text").GetString()}");
    Console.WriteLine($"Offset: {entity.GetProperty("offset").GetInt32()}");
    Console.WriteLine($"Length: {entity.GetProperty("length").GetInt32()}");
    Console.WriteLine($"Confidence: {entity.GetProperty("confidenceScore").GetSingle()}");
    Console.WriteLine();

    if (entity.TryGetProperty("resolutions", out JsonElement resolutions))
    {
        foreach (JsonElement resolution in resolutions.EnumerateArray())
        {
            if (resolution.GetProperty("resolutionKind").GetString() == "DateTimeResolution")
            {
                Console.WriteLine($"Datetime Sub Kind: {resolution.GetProperty("dateTimeSubKind").GetString()}");
                Console.WriteLine($"Timex: {resolution.GetProperty("timex").GetString()}");
                Console.WriteLine($"Value: {resolution.GetProperty("value").GetString()}");
                Console.WriteLine();
            }
        }
    }
}

可以传递其他选项, AnalyzeConversation 例如启用更详细的输出:

string projectName = "Menu";
string deploymentName = "production";

var data = new
{
    analysisInput = new
    {
        conversationItem = new
        {
            text = "Send an email to Carol about tomorrow's demo",
            id = "1",
            participantId = "1",
        }
    },
    parameters = new
    {
        projectName,
        deploymentName,
        verbose = true,

        // Use Utf16CodeUnit for strings in .NET.
        stringIndexType = "Utf16CodeUnit",
    },
    kind = "Conversation",
};

Response response = client.AnalyzeConversation(RequestContent.Create(data));

分析其他语言的对话

language属性可以设置为指定会话的语言:

string projectName = "Menu";
string deploymentName = "production";

var data = new
{
    analysisInput = new
    {
        conversationItem = new
        {
            text = "Enviar un email a Carol acerca de la presentación de mañana",
            language = "es",
            id = "1",
            participantId = "1",
        }
    },
    parameters = new
    {
        projectName,
        deploymentName,
        verbose = true,

        // Use Utf16CodeUnit for strings in .NET.
        stringIndexType = "Utf16CodeUnit",
    },
    kind = "Conversation",
};

Response response = client.AnalyzeConversation(RequestContent.Create(data));

使用业务流程项目分析对话

若要使用业务流程项目分析会话,可以像调用会话项目一样调用 AnalyzeConversation() 方法。

string projectName = "DomainOrchestrator";
string deploymentName = "production";

var data = new
{
    analysisInput = new
    {
        conversationItem = new
        {
            text = "How are you?",
            id = "1",
            participantId = "1",
        }
    },
    parameters = new
    {
        projectName,
        deploymentName,

        // Use Utf16CodeUnit for strings in .NET.
        stringIndexType = "Utf16CodeUnit",
    },
    kind = "Conversation",
};

Response response = client.AnalyzeConversation(RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(response.ContentStream);
JsonElement conversationalTaskResult = result.RootElement;
JsonElement orchestrationPrediction = conversationalTaskResult.GetProperty("result").GetProperty("prediction");

问答预测

如果对话是通过问答分析的,它将包括一个意向(甚至包括顶级意向),你可以从中检索答案:

string respondingProjectName = orchestrationPrediction.GetProperty("topIntent").GetString();
JsonElement targetIntentResult = orchestrationPrediction.GetProperty("intents").GetProperty(respondingProjectName);

if (targetIntentResult.GetProperty("targetProjectKind").GetString() == "QuestionAnswering")
{
    Console.WriteLine($"Top intent: {respondingProjectName}");

    JsonElement questionAnsweringResponse = targetIntentResult.GetProperty("result");
    Console.WriteLine($"Question Answering Response:");
    foreach (JsonElement answer in questionAnsweringResponse.GetProperty("answers").EnumerateArray())
    {
        Console.WriteLine(answer.GetProperty("answer").GetString());
    }
}

对话式摘要

若要总结会话,可以使用 AnalyzeConversation 返回 Operation<BinaryData>的方法重载:

var data = new
{
    analysisInput = new
    {
        conversations = new[]
        {
            new
            {
                conversationItems = new[]
                {
                    new
                    {
                        text = "Hello, how can I help you?",
                        id = "1",
                        role = "Agent",
                        participantId = "Agent_1",
                    },
                    new
                    {
                        text = "How to upgrade Office? I am getting error messages the whole day.",
                        id = "2",
                        role = "Customer",
                        participantId = "Customer_1",
                    },
                    new
                    {
                        text = "Press the upgrade button please. Then sign in and follow the instructions.",
                        id = "3",
                        role = "Agent",
                        participantId = "Agent_1",
                    },
                },
                id = "1",
                language = "en",
                modality = "text",
            },
        }
    },
    tasks = new[]
    {
        new
        {
            taskName = "Issue task",
            kind = "ConversationalSummarizationTask",
            parameters = new
            {
                summaryAspects = new[]
                {
                    "issue",
                }
            },
        },
        new
        {
            taskName = "Resolution task",
            kind = "ConversationalSummarizationTask",
            parameters = new
            {
                summaryAspects = new[]
                {
                    "resolution",
                }
            },
        },
    },
};

Operation<BinaryData> analyzeConversationOperation = client.AnalyzeConversations(WaitUntil.Completed, RequestContent.Create(data));

using JsonDocument result = JsonDocument.Parse(analyzeConversationOperation.Value.ToStream());
JsonElement jobResults = result.RootElement;
foreach (JsonElement task in jobResults.GetProperty("tasks").GetProperty("items").EnumerateArray())
{
    Console.WriteLine($"Task name: {task.GetProperty("taskName").GetString()}");
    JsonElement results = task.GetProperty("results");
    foreach (JsonElement conversation in results.GetProperty("conversations").EnumerateArray())
    {
        Console.WriteLine($"Conversation: #{conversation.GetProperty("id").GetString()}");
        Console.WriteLine("Summaries:");
        foreach (JsonElement summary in conversation.GetProperty("summaries").EnumerateArray())
        {
            Console.WriteLine($"Text: {summary.GetProperty("text").GetString()}");
            Console.WriteLine($"Aspect: {summary.GetProperty("aspect").GetString()}");
        }
        Console.WriteLine();
    }
}

其他示例

浏览我们的 示例 ,获取有关如何分析对话的更多示例。

疑难解答

常规

使用 .NET SDK 与认知语言服务对话客户端库交互时,服务返回的错误对应于为 REST API 请求返回的相同 HTTP 状态代码。

例如,如果将陈述提交到不存在的项目,则会返回指示 400 “错误请求”的错误。

try
{
    var data = new
    {
        analysisInput = new
        {
            conversationItem = new
            {
                text = "Send an email to Carol about tomorrow's demo",
                id = "1",
                participantId = "1",
            }
        },
        parameters = new
        {
            projectName = "invalid-project",
            deploymentName = "production",

            // Use Utf16CodeUnit for strings in .NET.
            stringIndexType = "Utf16CodeUnit",
        },
        kind = "Conversation",
    };

    Response response = client.AnalyzeConversation(RequestContent.Create(data));
}
catch (RequestFailedException ex)
{
    Console.WriteLine(ex.ToString());
}

你会注意到会记录其他信息,例如操作的客户端请求 ID。

Azure.RequestFailedException: The input parameter is invalid.
Status: 400 (Bad Request)
ErrorCode: InvalidArgument

Content:
{
  "error": {
    "code": "InvalidArgument",
    "message": "The input parameter is invalid.",
    "innerError": {
      "code": "InvalidArgument",
      "message": "The input parameter \"payload\" cannot be null or empty."
    }
  }
}

Headers:
Transfer-Encoding: chunked
pragma: no-cache
request-id: 0303b4d0-0954-459f-8a3d-1be6819745b5
apim-request-id: 0303b4d0-0954-459f-8a3d-1be6819745b5
x-envoy-upstream-service-time: 15
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
x-content-type-options: nosniff
Cache-Control: no-store, proxy-revalidate, no-cache, max-age=0, private
Content-Type: application/json

设置控制台日志记录

查看日志的最简单方法是启用控制台日志记录。 若要创建将消息输出到控制台的 Azure SDK 日志侦听器, AzureEventSourceListener.CreateConsoleLogger 请使用 方法。

// Setup a listener to monitor logged events.
using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger();

若要详细了解其他日志记录机制,请参阅 此处

后续步骤

供稿

有关构建、测试和参与此库的详细信息,请参阅 CONTRIBUTING.md

本项目欢迎贡献和建议。 大多数贡献要求你同意贡献者许可协议 (CLA),并声明你有权(并且确实有权)授予我们使用你的贡献的权利。 有关详细信息,请访问 cla.microsoft.com

提交拉取请求时,CLA 机器人将自动确定你是否需要提供 CLA,并相应地修饰 PR(例如标签、注释)。 直接按机器人提供的说明操作。 只需使用 CLA 对所有存储库执行一次这样的操作。

此项目采用了 Microsoft 开放源代码行为准则。 有关详细信息,请参阅行为准则常见问题解答,或如果有任何其他问题或意见,请与 联系。