我在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;
}
答案 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
只有Nombre
和Apellido
)并且工作正常 - Cotizacion
被成功调用。