Получить полную сущность LUIS DateTimeV2 из распознавателя - PullRequest
0 голосов
/ 31 октября 2018

Я использую Microsoft Bot Framework v4 для довольно простого распознавания даты и диапазона дат.

Самое простое использование распознавателя LUIS, которое используется в большинстве примеров и используется в корпоративном шаблоне, не возвращает полную структуру DateTimeV2. Пример ниже для "прошлой недели", соответствующей диапазону дат. Эти результаты находятся в распознавателе.result.entities:

{
  "$instance": {
    "datetime": [
      {
        "startIndex": 8,
        "endIndex": 17,
        "text": "last week",
        "type": "builtin.datetimeV2.daterange"
      }
    ]
  },
  "datetime": [
    {
      "type": "daterange",
      "timex": [
        "2018-W43"
      ]
    }
  ]
}

Обратите внимание, что для диапазона дат нет начальных / конечных тегов. Это кажется неполной версией спецификации DateTime2. https://docs.microsoft.com/en-us/azure/cognitive-services/LUIS/luis-reference-prebuilt-datetimev2

Если я использую определенный преобразователь DateTime, я получаю более подробную информацию о начале и конце, которую я хочу.

[timex, 2018-W43]
[type, daterange]
[start, 2018-10-22]
[end, 2018-10-29]

Кажется, что эти шаги почти избыточны, так как более общий подход возвращает строку в формате Timex, которая содержит начальную и конечную информацию, но не в легко используемом формате.

Полагаю, мне не хватает чего-то принципиального в настройке LUIS и распознавателей.

Фрагмент кода ниже является модифицированной версией примера csharp_dotnetcore / 12.nlp-with-luis (https://github.com/Microsoft/BotBuilder-Samples/tree/master/samples/csharp_dotnetcore/12.nlp-with-luis)

Я добавил один предварительно созданный объект DateTimeV2 в luis.ai.

public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default(CancellationToken))
{
    IList<Dictionary<string, string>> resolutionValues = null;

    if (turnContext.Activity.Type == ActivityTypes.Message)
    {

        // Use the more generic approach.
        var recognizerResult = await _services.LuisServices[LuisKey].RecognizeAsync(turnContext, cancellationToken);
        var topIntent = recognizerResult?.GetTopScoringIntent();
        if (topIntent != null && topIntent.HasValue && topIntent.Value.intent != "None")
        {
            await turnContext.SendActivityAsync($"==>LUIS Top Scoring Intent: {topIntent.Value.intent}, Score: {topIntent.Value.score}\n");
            if (recognizerResult.Entities != null)
            {
                await turnContext.SendActivityAsync($"==>LUIS Entities Found: {recognizerResult.Entities.ToString()}\n");
            }
        }
        else
        {
            var msg = @"No LUIS intents were found. Try show me last week.";
            await turnContext.SendActivityAsync(msg);
        }

        // Check LUIS model using specific DateTime Recognizer.
        var culture = Culture.English;
        var r = DateTimeRecognizer.RecognizeDateTime(turnContext.Activity.Text, culture);
        if (r.Count > 0 && r.First().TypeName.StartsWith("datetimeV2"))
        {
            var first = r.First();
            resolutionValues = (IList<Dictionary<string, string>>)first.Resolution["values"];
            var asString = string.Join(";", resolutionValues[0]);
            await turnContext.SendActivityAsync($"==>LUIS: resolutions values: {asString}\n");
            var subType = first.TypeName.Split('.').Last();
            if (subType.Contains("date") && !subType.Contains("range"))
            {
                // a date (or date & time) or multiple
                var moment = resolutionValues.Select(v => DateTime.Parse(v["value"])).FirstOrDefault();
                await turnContext.SendActivityAsync($"==>LUIS DateTime Moment: {moment}\n");
            }
            else if (subType.Contains("date") && subType.Contains("range"))
            {
                // range
                var from = DateTime.Parse(resolutionValues.First()["start"]);
                var to = DateTime.Parse(resolutionValues.First()["end"]);
                await turnContext.SendActivityAsync($"==>LUIS DateTime Range: from: {from} to: {to}\n");
            }
        }
    }
    else if (turnContext.Activity.Type == ActivityTypes.ConversationUpdate)
    {
        // Send a welcome message to the user and tell them what actions they may perform to use this bot
        await SendWelcomeMessageAsync(turnContext, cancellationToken);
    }
    else
    {
        await turnContext.SendActivityAsync($"{turnContext.Activity.Type} event detected", cancellationToken: cancellationToken);
    }
}

Есть ли простой способ получить более полную сущность DateTimeV2 из более общего распознавателя? Возможно цепочки распознавателей?

1 Ответ

0 голосов
/ 02 ноября 2018

Чтобы увидеть весь результат API, есть опция, которую нужно установить при создании Luis Recognizer. includeApiResults по умолчанию имеет значение false, поэтому при установке этого параметра на true весь результат API будет включен в результат luis.

Итак, в BotServices.cs при создании службы Luis это будет выглядеть так:

case ServiceTypes.Luis:
     {
        var luis = service as LuisService;
        var luisApp = new LuisApplication(luis.AppId, luis.SubscriptionKey, luis.GetEndpoint());
        LuisServices.Add(service.Id, new TelemetryLuisRecognizer(luisApp, includeApiResults:true));
        break;
    }

Итак, теперь свойства объекта luis содержат как анализ настроений, так и весь ответ luis.

{{
  "query": "show me orders for last week",
  "alteredQuery": null,
  "topScoringIntent": {
    "intent": "Shopping.CheckOrderStatus",
    "score": 0.619710267
  },
  "intents": null,
  "entities": [
    {
      "entity": "last week",
      "type": "builtin.datetimeV2.daterange",
      "startIndex": 19,
      "endIndex": 27,
      "resolution": {
        "values": [
          {
            "timex": "2018-W43",
            "type": "daterange",
            "start": "2018-10-22",
            "end": "2018-10-29"
          }
        ]
      }
    }
  ],
  "compositeEntities": null,
  "sentimentAnalysis": {
    "label": "negative",
    "score": 0.241115928
  }
}}
...