Search code examples
c#botframeworkazure-language-understanding

How to deserialize luis entity in IRecognizerConvert


In Luis, I created a simple pattern with a simple entity like this:

list bots {Name}

where "Name" is my entity that I would like to get in C#. The pattern and intent works fine and I am getting that correctly.

I follow the official example and built a IRecognizerConvert class so I can deserialize the result. It deserialize the intent just fine but fail to deserialize the entity.

In the _Entities sub-class, I only have the "Name" variable that I am trying to deserialize and nothing else. I don't have any other partial class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Newtonsoft.Json;
using Microsoft.Bot.Builder.AI.Luis;

namespace EmptyBot1.Models
{
    public class ChatbotIntent : IRecognizerConvert
    {
        public string Text;
        public string AlteredText;
        public enum Intent
        {
            CreateBot,
            ListBots,
            ListAllBots,
            RunBot,
            Cancel,
            Greet,
            None
        };
        public Dictionary<Intent, IntentScore> Intents;

        public class _Entities
        {
            public string Name;
        }
        public _Entities Entities;

        [JsonExtensionData(ReadData = true, WriteData = true)]
        public IDictionary<string, object> Properties { get; set; }

        public void Convert(dynamic result)
        {
            var _result = JsonConvert.DeserializeObject<ChatbotIntent>(JsonConvert.SerializeObject(result, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));
            Text = _result.Text;
            AlteredText = _result.AlteredText;
            Intents = _result.Intents;
            Entities = _result.Entities;
            Properties = _result.Properties;
        }

        public (Intent intent, double score) TopIntent()
        {
            Intent maxIntent = Intent.None;
            var max = 0.0;
            foreach (var entry in Intents)
            {
                if (entry.Value.Score > max)
                {
                    maxIntent = entry.Key;
                    max = entry.Value.Score.Value;
                }
            }
            return (maxIntent, max);
        }
    }
}

In the previous snippet, the important part is the _Entities class which define how the entities look from coming back from Luis. Since I only have 1 simple string entity "Name", I thought this is sufficient.

        public class _Entities
        {
            public string Name;
        }

However when I run it and I give it an utterance like:

"list bots mybots"

Luis would correctly assign Name="mybots" and get the correct intent, but it crash on the JsonConvert.DeserializeObject line saying the json format is incorrect. I assume this is complaining about the class I made? And not the actual JSON result from luis?

What do I need to add to the _Entities class so the luis entity can be successfully deserialzied?


Solution

  • I know this is an old question but I'm facing the same situation now so I want to contribute with the step-by-step that worked for me. As @ranusharao and Bill said, you need to download LUISGen from GitHub. Start a CMD, go to your solution's directory

    cd C:\MySolutionFolder
    

    and run

    luis init
    

    if you haven't done yet. It will ask you for your App ID and information that you get in luis.ai. After that, go to luis.ai / Manage / Versions, click on your current version and click Export as Json. enter image description here Place your JSON file in your solution's folder. Once you have done that, run the following command in your console:

    LUISGen C:\MyJSONPath\MyBot.json -cs MyClassName -o C:\MySolutionFolder
    

    That -cs stands for C#, but if you are usign Typescript then change it for "-ts". So there you have it, you can access your class with something like:

    var result = await _luisRecognizerService._recognizer.RecognizeAsync<MyClassName>(turnContext, cancellationToken);
    Console.WriteLine(result.Entities.Producto);
    

    _luisRecognizerService is my instance of LuisRecognizer (dependency injection)