【问题标题】:Passing entities with Luis to FormFlow将带有 Luis 的实体传递给 FormFlow
【发布时间】:2018-06-21 09:19:03
【问题描述】:

我正在使用 Luis 来识别用户是否使用某些实体启动流程,例如:他可以说“举报”或“我想在伦敦举报”或“我想举报伦敦的 x 地点”

    [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);
    }

这是类和构建形式:

[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();

如果添加 ActiveDelegate hasLocation 我可以控制是否必须显示字段 LocationId。这可行,但在此之后机器人会因“抱歉,我的机器人代码有问题”而中断

文本错误的示例

带有正确文本的示例

编辑

表单中使用的类:

类基础模型

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

类城市

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

班级位置

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

【问题讨论】:

  • 您要传递完整的实体列表,还是要使用从 luis 收到的实体填写表格?
  • 理想的做法是将 luis 实体作为响应传递给表单流(使用本机表单流验证和功能),但我不知道是否可能

标签: c# .net botframework azure-language-understanding formflow


【解决方案1】:

一种简单的方法是解析 Luis 结果并从结果中获取实体值并将结果传递给 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);

}

如果您必须在将实体分配给 formflow 中的字段之前对其进行处理,则必须在 Luis Dialog 方法本身中进行。

【讨论】:

  • 不可能让对话处理实体,就像用户一对一插入时他会定期做的那样?
  • 您能解释一下您在 luis 中收到的内容以及您在表格中填写的内容吗?
  • 例如,luis 收到“我想在伦敦报告”并将 London 传递给 FormFlow。 Luis 无法知道城市是否正确,并且表单流需要城市的 Id 才能继续(表单知道 London 是描述并使用 id 填充该字段)。城市字段使用具有 Name 和 Id 的类 City 来填充选项。
  • 因此,如果我理解,实体会直接进入状态,无需任何类型的绑定或验证,如 FormFlow 将在用户回答的情况下运行。因此,虽然通常“伦敦”将被验证并最终注册为 LocalizationId 中的 ID,但在传递预填充状态时,LocalizationId 最终只是“伦敦”。我对吗?我不知道是否有可能实现这种行为。 @安妮塔乔治
  • @StubbornElio 你的城市班是什么样的?
猜你喜欢
  • 1970-01-01
  • 2014-05-14
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
相关资源
最近更新 更多