简体   繁体   中英

Passing entities with Luis to FormFlow

I'm using Luis to recognize if the user starts the flow with some entities, for example: he can say " Report " or " I want to report in London " or " I want to report place x in London "

    [LuisIntent("Report")]
    public async Task ReportCompleteIntent(IDialogContext context, LuisResult result)
    {
        EntityRecommendation location;
        EntityRecommendation POS;

        result.TryFindEntity("Weather.Location", out location);
        result.TryFindEntity("POS", out POS);

        //I tried with passing entities (it doesn't recognize the entities in formBuild)
        context.Call(Chain.From(() => new FormDialog<OutOfStockReport>(new OutOfStockReport(), buildForm: OutOfStockReport.BuildForm, options: FormOptions.PromptInStart, entities: result.Entities)), OOSDialogComplete);
        //Also tried prepopulating the state
        context.Call(Chain.From(() => new FormDialog<OutOfStockReport>(new OutOfStockReport() { LocalizationId = location?.Entity }, buildForm: OutOfStockReport.BuildForm, options: FormOptions.PromptInStart)), OOSDialogComplete);
    }

This is the class and the buildform:

[Serializable]
[Template(TemplateUsage.NavigationFormat, "{&}")]
public class OutOfStockReport
{
    public string LocalizationId;
    public string PositionId;     

    public static IForm<OutOfStockReport> BuildForm()
    {
        return FormBuilderHelper.CreateCustomForm<OutOfStockReport>()
            .Message("Welcome!")         
            .Field(new FieldReflector<OutOfStockReport>(nameof(LocalizationId))
                .SetType(null)
                .SetActive(hasLocation)
                .SetDefine(async (state, field) =>
                {
                    var cities = new City().GetCities();

                    foreach (var option in cities)
                    {
                        var description = new DescribeAttribute($"{option.Name}", message: $"{option.Name}", title: $"{option.Name}");
                        field.AddDescription(option.Id, description);
                        field.AddTerms(option.Id, Language.GenerateTerms(Language.CamelCase(option.Name), 3));
                    }

                    return true;
                })
                .SetValidate(async (state, response) =>
                {
                    state.PositionId = null;

                    var result = new ValidateResult { IsValid = true, Value = response };

                    return result;

                }))
            .Field(new FieldReflector<OutOfStockReport>(nameof(PositionId))
                .SetType(null)
                .SetActive((state) => !string.IsNullOrEmpty(state.LocalizationId))
                .SetDefine(async (state, field) =>
                {
                    field.RemoveValues();

                    var localizedOptions = new Position().GetPositions(state.LocalizationId);

                    foreach (var option in localizedOptions)
                    {
                        var description = new DescribeAttribute($"{option.Name}", message: $"{option.Name}", title: $"{option.Name}");
                        field.AddDescription(option.Id, description);
                        field.AddTerms(option.Id, Language.GenerateTerms(Language.CamelCase($"{option.Id} {option.Name} {option.Direction}"), 3));
                    }

                    return true;
                }))
            .AddRemainingFields()       
            .Confirm("Are you sure of your selection?{||}")
            .OnCompletion(async (context, state) => await context.PostAsync($"Thanks, the task is complete."))                    
            .Build();

If adding an ActiveDelegate hasLocation I can control if the field LocationId must be shown or not. This works but after that the bot breaks with " Sorry, my bot code is having an issue "

Example with wrong text 错误文字的例子

Example with right text 带有正确文字的示例

EDIT

The classes that are used in the form:

Class BaseModel

public class BaseModel
{
    public string Id{ get; set; }
}

Class City

public class City : BaseModel
{
    public string Name { get; set; }
}

Class Position

public class Position : BaseModel
{
    public string Name { get; set; }
    public string Direction { get; set; }
    public string CityId { get; set; }
}

A simple approach would be to parse the Luis result and get the entity value from the result and pass the result to formflow.

LuisDialog

[LuisIntent("Report")]
public async Task ReportCompleteIntent(IDialogContext context, LuisResult result)
{
        OutOfStockReport form = new OutOfStockReport();
        EntityRecommendation location;
        EntityRecommendation POS;

        if(result.TryFindEntity("Weather.Location", out location))
        {
        //Here you are initializing the form with values.
        //If you have written any validation code for this field then
        //formflow will check the validation when the form is called

             form.Location = location.Entity;
        }
        if(result.TryFindEntity("POS", out POS))
        {
             form.POS = POS.Entity;
        }

        context.Call(form,OutOfStockReport.BuildForm, FormOptions.PromptInStart,OOSDialogComplete);

}

If you have to process the Entity before assigning it to the field in formflow you will have to do it in the Luis Dialog method itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM