Виртуальный помощник.
C #
BotBuilder.Community.Adapters.Alexa, похоже, не работает с VA.
Следуйте инструкциям здесь: - https://github.com/BotBuilderCommunity/botbuilder-community-dotnet/tree/develop/libraries/Bot.Builder.Community.Adapters.Alexa
1) В Startup.cs я добавил следующие пакеты NuGet:
Bot.Builder.Community.Adapters.Alexa;
Bot.Builder.Community.Adapters.Alexa.Integration.AspNet.Core;
Bot.Builder.Community.Adapters.Alexa.Middleware;
Перед этим кодом
// Configure bot
services.AddTransient<IBot, DialogBot<MainDialog>>();
Я добавил:
// Registering the AlexaHttpAdapter
services.AddSingleton<IAlexaHttpAdapter>((sp) =>
{
var alexaHttpAdapter = new AlexaHttpAdapter(validateRequests: true)
{
OnTurnError = async (context, exception) =>
{
await context.SendActivityAsync("Sorry, something went wrong. Please try again later." + context + " Exception:" + exception);
},
ShouldEndSessionByDefault = true,
ConvertBotBuilderCardsToAlexaCards = false,
};
alexaHttpAdapter.Use(new AlexaIntentRequestToMessageActivityMiddleware());
return alexaHttpAdapter;
});
services.AddSingleton<AlexaIntentRequestToMessageActivityMiddleware>();
2) Создал контроллер Alexa:
using Bot.Builder.Community.Adapters.Alexa.Integration.AspNet.Core;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Bot.Builder;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace GuideDogs_VA.Controllers
{
[Route("api/skillrequests")]
[ApiController]
public class AlexaBotController : ControllerBase
{
private readonly IAlexaHttpAdapter _adapter;
private readonly IBot _bot;
public AlexaBotController(IAlexaHttpAdapter adapter, IBot bot)
{
_adapter = adapter;
_bot = bot;
}
[HttpPost]
public async Task PostAsync()
{
await _adapter.ProcessAsync(Request, Response, _bot);
}
}
}
3) Создал навык Alexa, используя следующий JSON:
{
"interactionModel": {
"languageModel": {
"invocationName": "guide dogs",
"intents": [
{
"name": "GetUserIntent",
"slots": [
{
"name": "phrase",
"type": "phrase"
}
],
"samples": [
"{phrase}"
]
},
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
}
],
"types": [
{
"name": "phrase",
"values": [
{
"name": {
"value": "hi there Alexa"
}
},
{
"name": {
"value": "you are just going to repeat what I said aren't you"
}
},
{
"name": {
"value": "what colour is the sky?"
}
}
]
}
]
}
}
}
При тестировании Alexa Skill через консоль разработчика Alexa или через устройство Alexa, чтобы он ответил, но, к сожалению, он вызывает OnEventSync (), даже если тип активности имеет тип сообщения.
Исключение System.NullReferenceException из файла MainDialog.cs:
Ответ виртуального устройства на Alexa (ответ, созданный из vityAsync: - await context.SendActivityAsync («Извините, что-то пошло не так. Повторите попытку позже.» + Context + «Exception:» + исключение):
{
"body": {
"version": "1.0",
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "Sorry, something went wrong. Please try again later.Microsoft.Bot.Builder.TurnContext Exception:System.NullReferenceException: Object reference not set to an instance of an object.\r\n at GuideDogs_VA.Dialogs.MainDialog.OnEventAsync(DialogContext dc, CancellationToken cancellationToken) in C:\\Users\\hussel\\source\\repos\\GuideDogs-VA\\GuideDogs_VA\\Dialogs\\MainDialog.cs:line 204\r\n at Microsoft.Bot.Builder.Solutions.Dialogs.RouterDialog.OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken)\r\n at Microsoft.Bot.Builder.Dialogs.ComponentDialog.BeginDialogAsync(DialogContext outerDc, Object options, CancellationToken cancellationToken)\r\n at Microsoft.Bot.Builder.Dialogs.DialogContext.BeginDialogAsync(String dialogId, Object options, CancellationToken cancellationToken)\r\n at Microsoft.Bot.Builder.Dialogs.DialogExtensions.RunAsync(Dialog dialog, ITurnContext turnContext, IStatePropertyAccessor`1 accessor, CancellationToken cancellationToken)\r\n at GuideDogs_VA.Bots.DialogBot`1.OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken) in C:\\Users\\hussel\\source\\repos\\GuideDogs-VA\\GuideDogs_VA\\Bots\\DialogBot.cs:line 39\r\n at Bot.Builder.Community.Adapters.Alexa.Middleware.AlexaIntentRequestToMessageActivityMiddleware.OnTurnAsync(ITurnContext context, NextDelegate next, CancellationToken cancellationToken)\r\n at Microsoft.Bot.Builder.MiddlewareSet.ReceiveActivityWithStatusAsync(ITurnContext turnContext, BotCallbackHandler callback, CancellationToken cancellationToken)\r\n at Microsoft.Bot.Builder.BotAdapter.RunPipelineAsync(ITurnContext turnContext, BotCallbackHandler callback, CancellationToken cancellationToken)"
},
"directives": [],
"shouldEndSession": true,
"type": "_DEFAULT_RESPONSE"
},
"sessionAttributes": {}
}
}
Вероятно, это вызвано реализацией RouterDialog по умолчанию. Один из вариантов, который можно попробовать, - переопределить метод ContinueDialogAsync в MainDialog желаемым поведением.
@samaea Я воспроизвел проблему. @ lauren-mills был прав, это связано с тем, что RouterDialog ищет значение для действия и рассматривает его как событие, а не как обычное сообщение.
Вы можете добавить следующее переопределение в свой MainDialog в качестве временного решения. Единственное изменение заключается в том, что мы проверяем, является ли идентификатор канала Alexa.
После добавления этого изменения я могу успешно получить ответ от VA через Alexa. Надеюсь, это решит вашу проблему.
protected override async Task<DialogTurnResult> OnContinueDialogAsync(DialogContext innerDc, CancellationToken cancellationToken = default)
{
var activity = innerDc.Context.Activity;
if (activity.IsStartActivity())
{
await OnStartAsync(innerDc);
}
switch (activity.Type)
{
case ActivityTypes.Message:
{
if (activity.Value != null && activity.ChannelId != "alexa")
{
await OnEventAsync(innerDc);
}
else if (!string.IsNullOrEmpty(activity.Text))
{
var result = await innerDc.ContinueDialogAsync();
switch (result.Status)
{
case DialogTurnStatus.Empty:
{
await RouteAsync(innerDc);
break;
}
case DialogTurnStatus.Complete:
{
await CompleteAsync(innerDc);
// End active dialog
await innerDc.EndDialogAsync();
break;
}
default:
{
break;
}
}
}
break;
}
case ActivityTypes.Event:
{
await OnEventAsync(innerDc);
break;
}
default:
{
await OnSystemMessageAsync(innerDc);
break;
}
}
return EndOfTurn;
}
Спасибо @garypretty! У меня есть открытая работа для следующего выпуска по рефакторингу RouterDialog для большего согласования с SDK, так что я могу учесть эту обратную связь и для этой работы.
Самый полезный комментарий
@samaea Я воспроизвел проблему. @ lauren-mills был прав, это связано с тем, что RouterDialog ищет значение для действия и рассматривает его как событие, а не как обычное сообщение.
Вы можете добавить следующее переопределение в свой MainDialog в качестве временного решения. Единственное изменение заключается в том, что мы проверяем, является ли идентификатор канала Alexa.
После добавления этого изменения я могу успешно получить ответ от VA через Alexa. Надеюсь, это решит вашу проблему.