gpt4 book ai didi

c# - BotFramework 和 LUIS 的 JSON 序列化器错误

转载 作者:太空宇宙 更新时间:2023-11-03 19:46:47 26 4
gpt4 key购买 nike

StackOverflow 社区!

我有一个聊天机器人,并集成了 LUIS.ai 以使其更智能。其中一个对话是要与主管(老师)预约一切都运行良好,代码完全相同。几个小时前,我遇到了一些奇怪的错误。

 Exception: Type 'Newtonsoft.Json.Linq.JArray' in Assembly 'Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' is not marked as serializable.

如何重现错误?

如果用户输入中缺少两个实体(教师和日期),它可以正常工作,机器人会构建表单,询问缺少的输入并显示建议的 session 时间。

如果其中一个实体在输入中缺失,它将构建一个表单并询问缺失的日期或教师实体并显示建议的 session 时间。

但是

如果用户的输入同时包含实体:教师和日期,那么我会收到错误。

这是我的 WebApiConfig 类:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Json settings
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
Formatting = Newtonsoft.Json.Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
};

// Web API configuration and services

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

我只是在尝试从用户话语中获取实体时遇到此错误,这是一种 builtin.dateTimeV2 类型。

这个异步方法被称为:

    //From the LUIS.AI language model the entities
private const string EntityMeetingDate = "MeetingDate";
private const string EntityTeacher = "Teacher";

[LuisIntent("BookSupervision")]
public async Task BookAppointment(IDialogContext context, IAwaitable<IMessageActivity> activity, LuisResult result)
{
var message = await activity;
await context.PostAsync($"I am analysing your message: '{message.Text}'...");

var meetingsQuery = new MeetingsQuery();

EntityRecommendation teacherEntityRecommendation;
EntityRecommendation dateEntityRecommendation;

if (result.TryFindEntity(EntityTeacher, out teacherEntityRecommendation))
{
teacherEntityRecommendation.Type = "Name";
}
if (result.TryFindEntity(EntityMeetingDate, out dateEntityRecommendation))
{
dateEntityRecommendation.Type = "Date";
}

var meetingsFormDialog = new FormDialog<MeetingsQuery>(meetingsQuery, this.BuildMeetingsForm, FormOptions.PromptInStart, result.Entities);
context.Call(meetingsFormDialog, this.ResumeAfterMeetingsFormDialog);

}

构建表单的其他方法:

 private IForm<MeetingsQuery> BuildMeetingsForm()
{
OnCompletionAsyncDelegate<MeetingsQuery> processMeetingsSearch = async (context, state) =>
{
var message = "Searching for supervision slots";
if (!string.IsNullOrEmpty(state.Date))
{
message += $" at {state.Date}...";
}
else if (!string.IsNullOrEmpty(state.Name))
{
message += $" with professor {state.Name}...";
}
await context.PostAsync(message);
};

return new FormBuilder<MeetingsQuery>()
.Field(nameof(MeetingsQuery.Date), (state) => string.IsNullOrEmpty(state.Date))
.Field(nameof(MeetingsQuery.Name), (state) => string.IsNullOrEmpty(state.Name))
.OnCompletion(processMeetingsSearch)
.Build();
}

private async Task ResumeAfterMeetingsFormDialog(IDialogContext context, IAwaitable<MeetingsQuery> result)
{
try
{
var searchQuery = await result;

var meetings = await this.GetMeetingsAsync(searchQuery);

await context.PostAsync($"I found {meetings.Count()} available slots:");

var resultMessage = context.MakeMessage();
resultMessage.AttachmentLayout = AttachmentLayoutTypes.Carousel;
resultMessage.Attachments = new List<Attachment>();

foreach (var meeting in meetings)
{
HeroCard heroCard = new HeroCard()
{
Title = meeting.Teacher,
Subtitle = meeting.Location,
Text = meeting.DateTime,
Images = new List<CardImage>()
{
new CardImage() {Url = meeting.Image}
},
Buttons = new List<CardAction>()
{
new CardAction()
{
Title = "Book Appointment",
Type = ActionTypes.OpenUrl,
Value = $"https://www.bing.com/search?q=easj+roskilde+" + HttpUtility.UrlEncode(meeting.Location)
}
}
};

resultMessage.Attachments.Add(heroCard.ToAttachment());
}

await context.PostAsync(resultMessage);
}
catch (FormCanceledException ex)
{
string reply;

if (ex.InnerException == null)
{
reply = "You have canceled the operation.";
}
else
{
reply = $"Oops! Something went wrong :( Technical Details: {ex.InnerException.Message}";
}

await context.PostAsync(reply);
}
finally
{
context.Wait(DeconstructionOfDialog);
}
}


private async Task<IEnumerable<Meeting>> GetMeetingsAsync(MeetingsQuery searchQuery)
{
var meetings = new List<Meeting>();

//some random result manually for demo purposes
for (int i = 1; i <= 5; i++)
{
var random = new Random(i);
Meeting meeting = new Meeting()
{
DateTime = $" Available time: {searchQuery.Date} At building {i}",
Teacher = $" Professor {searchQuery.Name}",
Location = $" Elisagårdsvej 3, Room {random.Next(1, 300)}",
Image = $"https://placeholdit.imgix.net/~text?txtsize=35&txt=Supervision+{i}&w=500&h=260"
};

meetings.Add(meeting);
}

return meetings;
}

最奇怪的是,这段代码起作用了,我对 GitHub 上的社区表示赞赏和尊重,因为我认为这是一个很棒的平台,有大量的文档和示例。

最佳答案

这是已知问题(也报告了 herehere)。

长话短说,由于 BotBuilder 尚不支持 builtin.datetimeV2.* 实体,因此 EntityRecommendationResolution 字典以一个具有值的条目结束JArray 类型。当您将这些实体传递给 FormDialog 时,问题就出现了。由于实体是对话框中的私有(private)字段,当然,与任何其他对话框一样,正在序列化,因此抛出异常,因为 NewtonsoftJArray 类不是标记为可序列化。

添加对 datetimeV2 实体支持的请求是 here .

我现在能想到的解决方法是手动提取 DateTime 实体的值并将其分配给您传递给 MeetingsQuery 实例的 Date 字段FormDialog 并从 result.Entities 集合中删除 DateTime 实体,您将传递给 FormDialog

更新

如您在 this Pull Request 中所见,这已在 SDK 中得到修复.

关于c# - BotFramework 和 LUIS 的 JSON 序列化器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44552030/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com