我正在使用Bot Framework V4构建一个机器人,其中我使用了多重提示(Multi-Turn)QnA服务,我的需求是当用户到达最后一个问题或特定的问题时,会出现一个自定义的提示,询问他的名字,并将其值存储在数据库中,我对如何使用对话框非常困惑,请帮助我。
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;
}
}
}
你可以参考 这个 文档,其中规定了如何创建自己的提示来收集用户的输入。机器人和用户之间的对话通常包括向用户询问(提示)信息,解析用户的回应,然后根据这些信息采取行动。
该文档基于以下示例 44.prompt-users-for-input.机器人维护对话状态,以跟踪和引导对话并向用户提问。机器人维护用户状态,跟踪用户的回答。
希望能帮到你!