Я создаю бота, используя Bot Framework V4, в котором я использовал службы QnA с несколькими запросами (многооборотные). Мое требование: когда пользователь достигает последнего вопроса или конкретного c вопроса, появляется настраиваемая подсказка, в которой задается его / ее имя и сохраняется значение в базе данных. Я очень не понимаю, как использовать диалоги. Пожалуйста, помогите мне.
Bot.cs
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Schema;
using Microsoft.Extensions.Logging;
namespace Microsoft.BotBuilderSamples.Bots
{
public class QnABot<T> : ActivityHandler where T : Microsoft.Bot.Builder.Dialogs.Dialog
{
protected readonly BotState ConversationState;
protected readonly Microsoft.Bot.Builder.Dialogs.Dialog Dialog;
protected readonly BotState UserState;
public QnABot(ConversationState conversationState, UserState userState, T dialog)
{
ConversationState = conversationState;
UserState = userState;
Dialog = dialog;
}
public override async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
{
await base.OnTurnAsync(turnContext, cancellationToken);
if (turnContext.Activity.Type == ActivityTypes.Message)
{
}
// Save any state changes that might have occured during the turn.
await ConversationState.SaveChangesAsync(turnContext, false, cancellationToken);
await UserState.SaveChangesAsync(turnContext, false, cancellationToken);
}
private static async Task SendIntroCardAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
var card = new HeroCard();
card.Title = "Hi! I am your personnel Chatbot.";
card.Text = @"How can I help you today, you can choose from menu and get started.";
card.Buttons = new List<CardAction>()
{
new CardAction(ActionTypes.PostBack, "Looking for New Services", value: "selected: Looking for New Services"),
new CardAction(ActionTypes.PostBack, "Looking for Maintenance work", value: "selected: Looking for Maintenance work"),
new CardAction(ActionTypes.PostBack, "Need Technical Support", value: "selected: Need Technical Support"),
};
var response = MessageFactory.Attachment(card.ToAttachment());
await turnContext.SendActivityAsync(response, cancellationToken);
}
protected override async Task OnMessageActivityAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken) =>
// Run the Dialog with the new message Activity.
await Dialog.RunAsync(turnContext, ConversationState.CreateProperty<DialogState>(nameof(DialogState)), cancellationToken);
protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
{
foreach (var member in membersAdded)
{
if (member.Id != turnContext.Activity.Recipient.Id)
{
await SendIntroCardAsync(turnContext, cancellationToken);
}
}
}
}
}
RootDialog.cs
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.AI.QnA;
using Microsoft.Bot.Builder.AI.QnA.Dialogs;
using Microsoft.Bot.Builder.Dialogs;
namespace Microsoft.BotBuilderSamples.Dialog
{
/// <summary>
/// This is an example root dialog. Replace this with your applications.
/// </summary>
public class RootDialog : ComponentDialog
{
/// <summary>
/// QnA Maker initial dialog
/// </summary>
private const string InitialDialog = "initial-dialog";
/// <summary>
/// Initializes a new instance of the <see cref="RootDialog"/> class.
/// </summary>
/// <param name="services">Bot Services.</param>
public RootDialog(IBotServices services)
: base("root")
{
AddDialog(new QnAMakerBaseDialog(services));
AddDialog(new WaterfallDialog(InitialDialog)
.AddStep(InitialStepAsync));
// The initial child Dialog to run.
InitialDialogId = InitialDialog;
}
private async Task<DialogTurnResult> InitialStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
{
return await stepContext.BeginDialogAsync(nameof(QnAMakerDialog), null, cancellationToken);
}
}
}
QnAMakerBaseDialog .cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Bot.Builder.AI.QnA;
using Microsoft.Bot.Builder.AI.QnA.Dialogs;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Schema;
namespace Microsoft.BotBuilderSamples.Dialog
{
/// <summary>
/// QnAMaker action builder class
/// </summary>
public class QnAMakerBaseDialog : QnAMakerDialog
{
// Dialog Options parameters
public const string DefaultNoAnswer = "No QnAMaker answers found.";
public const string DefaultCardTitle = "Did you mean:";
public const string DefaultCardNoMatchText = "None of the above.";
public const string DefaultCardNoMatchResponse = "Thanks for the feedback.";
private readonly IBotServices _services;
/// <summary>
/// Initializes a new instance of the <see cref="QnAMakerBaseDialog"/> class.
/// Dialog helper to generate dialogs.
/// </summary>
/// <param name="services">Bot Services.</param>
public QnAMakerBaseDialog(IBotServices services): base()
{
this._services = services;
}
protected async override Task<IQnAMakerClient> GetQnAMakerClientAsync(DialogContext dc)
{
return this._services?.QnAMakerService;
}
protected override Task<QnAMakerOptions> GetQnAMakerOptionsAsync(DialogContext dc)
{
return Task.FromResult(new QnAMakerOptions
{
ScoreThreshold = DefaultThreshold,
Top = DefaultTopN,
QnAId = 0,
RankerType = "Default",
IsTest = false
});
}
protected async override Task<QnADialogResponseOptions> GetQnAResponseOptionsAsync(DialogContext dc)
{
var noAnswer = (Activity)Activity.CreateMessageActivity();
noAnswer.Text = DefaultNoAnswer;
var cardNoMatchResponse = (Activity)MessageFactory.Text(DefaultCardNoMatchResponse);
var responseOptions = new QnADialogResponseOptions
{
ActiveLearningCardTitle = DefaultCardTitle,
CardNoMatchText = DefaultCardNoMatchText,
NoAnswer = noAnswer,
CardNoMatchResponse = cardNoMatchResponse,
};
return responseOptions;
}
}
}