如何从BotFramework中的LuisIntent中解雇FormFlow

时间:2017-10-13 20:05:25

标签: c# botframework luis

我在C#中使用Microsoft的BotFramework。我有一个LUIS Intent,从那里我想开一个FormFlow,但老实说我不知道​​怎么做。

[LuisModel("35554cdf-92ae-4413-*", "*")]
[Serializable]
public class LuisIntegration : LuisDialog<Object>
{
    public BuildFormDelegate<Cotizacion> _configurecotizacion;
    public BuildFormDelegate<Cotizacion> LuisDialog(BuildFormDelegate<Cotizacion> configureCotizacion) => _configurecotizacion = configureCotizacion;

    [LuisIntent("Cotizar")]
    public async Task CotizarAsync(IDialogContext context, LuisResult result)
    {
        var entitiesArray = result.Entities;

        var form = new FormDialog<Cotizacion>(new Cotizacion(), Cotizacion.BuildForm, FormOptions.PromptInStart, result.Entities);

        context.Call(new FormDialog<Cotizacion>(new Cotizacion(), this._configurecotizacion, FormOptions.PromptInStart), ResumeAfterCallback);
    }

    private async Task ResumeAfterCallback(IDialogContext context, IAwaitable<Cotizacion> result)
    {
        Cotizacion coti = null;

        try
        {
            coti = await result;
        }
        catch (OperationCanceledException)
        {
            await context.PostAsync("Cancelaste la cotización.");
            return;
        }

        //context.Wait(MessageReceived);
    }
}


public static IForm<Cotizacion> BuildForm()
    {
        return new FormBuilder<Cotizacion>()
                .Message("¡Listo! Necesito algunos datos para cotizar, empecemos.")
                .Field(nameof(Nombre))
                .Field(nameof(Apellido))
                .Field(nameof(Provincia))
                .Field(nameof(Localidad))
                .Field(nameof(Edad))
                .Field(new FieldReflector<Cotizacion>(nameof(Marca))
                    .SetType(null)
                    .SetDefine(async (state, field) =>
                    {
                        foreach (var prod in await Gets.ObtenerMarcasAsync())
                            field
                                .AddDescription(prod, prod)
                                .AddTerms(prod, prod);

                        return await Task.FromResult(true);
                    }))
                .Field(new FieldReflector<Cotizacion>(nameof(Modelo))
                    .SetType(null)
                    .SetDefine(async (state, field) =>
                    {
                        foreach (var prod in await Gets.ObtenerModelosAsync(state.Marca))
                            field
                                .AddDescription(prod, prod)
                                .AddTerms(prod, prod);

                        return await Task.FromResult(true);
                    }))
                .Field(nameof(Anio))
                .Field(nameof(Version))
                .Field(nameof(Email))
                .Field(nameof(Telefono))
                .Field(nameof(Sexo))
                .Confirm("Estamos a punto de cotizar tu auto, ¿está correcta la información que ingresaste?")
                .OnCompletion(async (context, state) => { ... }

FormFlow单独工作,问题是当我添加LuisIntent时。

我修复了调用FormFlow的问题,现在的问题是没有提示确认,因此没有完成。它挂在表单的最后一个属性中。我更新了代码。

编辑2:

private async Task ResumeAfterCallback(IDialogContext context, IAwaitable<Cotizacion> result)
    {
        Cotizacion coti = null;

        try
        {
            coti = await result;
        }
        catch (OperationCanceledException)
        {
            await context.PostAsync("Cancelaste la cotización.");
            return;
        }

        context.Wait(MessageReceived);
    }

编辑3:

public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
    {
        if (activity.Type == ActivityTypes.Message)
        {
            await Conversation.SendAsync(activity, () => new LuisIntegration());
        }
        else
        {
            HandleSystemMessage(activity);
        }
        var response = Request.CreateResponse(HttpStatusCode.OK);
        return response;
    }

1 个答案:

答案 0 :(得分:0)

更新:(最终)问题出现在FieldReflector的DefineAsyncDelegate方法的SetDefine参数定义中:

public delegate Task<bool> DefineAsyncDelegate<T>(T state, Field<T> field) where T : class;

没有明确要求它是async方法,但由于上面的实现在其中使用异步调用('Gets.ObtenerXXXAsync()'),该方法应该返回一个bool而不是一个包裹的{{ 1}}。

如果省略Task.FromResult<bool>,并且使用Task.Run(...)调用了Gets.ObtenerXXXAsync()。例如,结果返回Task.FromResult是正确的(真)。

...

也许你的机器人迷恋'Sexo'...... :)。

为什么需要async成员变量?您的BuildFormDelegate<Cotizacion>方法可能如下所示:

CotizarAsync

只是将 [LuisIntent("Cotizar")] public async Task CotizarAsync(IDialogContext context, IAwaitable<IMessageActivity> activity, LuisResult result) { context.Call(new FormDialog<Cotizacion>(new Cotizacion(), Cotizacion.BuildForm, FormOptions.PromptInStart, result.Entities), ResumeAfterCallback); } 传递给FormDialog构造函数。

我在我的LUIS机器人中尝试了一个简化版本(Cotizacion.BuildForm只有NombreApellido)并且工作正常 - Cotizacion被成功调用。