C# 表单流bot自定义问题

C# 表单流bot自定义问题,c#,botframework,formflow,qnamaker,C#,Botframework,Formflow,Qnamaker,我想建立一个机器人,可以利用QNAAPI和谷歌驱动器的搜索api。我将询问用户是要查询知识库还是要搜索驱动器中的文件。为此,我选择了bot框架的表单流bot模板。在这种情况下,如果用户选择查询QNAAPI,那么我想将问题发布到QNAAPI。如何在我的bot中实现这一点?我在哪里可以找到用户在流中的选择 这里是MessageController.cs public async Task<HttpResponseMessage> Post([FromBody]Activi

我想建立一个机器人,可以利用QNAAPI和谷歌驱动器的搜索api。我将询问用户是要查询知识库还是要搜索驱动器中的文件。为此,我选择了bot框架的表单流bot模板。在这种情况下,如果用户选择查询QNAAPI,那么我想将问题发布到QNAAPI。如何在我的bot中实现这一点?我在哪里可以找到用户在流中的选择

这里是MessageController.cs

        public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                await Conversation.SendAsync(activity, MakeRootDialog);
            }
            else
            {
                HandleSystemMessage(activity);
            }
            var response = Request.CreateResponse(HttpStatusCode.OK);
            return response;
        }

        private Activity HandleSystemMessage(Activity message)
        {
            if (message.Type == ActivityTypes.DeleteUserData)
            {
                // Implement user deletion here
                // If we handle user deletion, return a real message
            }
            else if (message.Type == ActivityTypes.ConversationUpdate)
            {
                // Handle conversation state changes, like members being added and removed
                // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
                // Not available in all channels
            }
            else if (message.Type == ActivityTypes.ContactRelationUpdate)
            {
                // Handle add/remove from contact lists
                // Activity.From + Activity.Action represent what happened
            }
            else if (message.Type == ActivityTypes.Typing)
            {
                // Handle knowing tha the user is typing
            }
            else if (message.Type == ActivityTypes.Ping)
            {
            }

            return null;
        }
        internal static IDialog<UserIntent> MakeRootDialog()
        {
            return Chain.From(() => FormDialog.FromForm(UserIntent.BuildForm));
        }
公共异步任务发布([FromBody]活动)
{
if(activity.Type==ActivityTypes.Message)
{
等待对话。SendAsync(活动,MakeRootDialog);
}
其他的
{
HandleSystemMessage(活动);
}
var response=Request.CreateResponse(HttpStatusCode.OK);
返回响应;
}
私有活动HandleSystemMessage(活动消息)
{
if(message.Type==ActivityTypes.DeleteUserData)
{
//在此处执行用户删除
//如果我们处理用户删除,返回一条真实的消息
}
else if(message.Type==ActivityTypes.ConversationUpdate)
{
//处理会话状态更改,如添加和删除成员
//使用Activity.MembersAdded和Activity.MembersRemoved以及Activity.Action获取信息
//并非所有频道都可用
}
else if(message.Type==ActivityTypes.ContactRelationUpdate)
{
//处理联系人列表中的添加/删除
//Activity.From+Activity.Action表示发生了什么
}
else if(message.Type==ActivityTypes.Typing)
{
//处理知道用户正在键入的内容
}
else if(message.Type==ActivityTypes.Ping)
{
}
返回null;
}
内部静态IDialog MakeRootDialog()
{
返回链.From(()=>FormDialog.FromForm(UserIntent.BuildForm));
}
表单生成器

public static IForm<UserIntent> BuildForm()
 {
   return new FormBuilder<UserIntent>()
     .Message("Welcome to the bot!")
     .OnCompletion(async (context, profileForm) =>
      {
         await context.PostAsync("Thank you");
      }).Build();
 }
publicstaticiformbuildform()
{
返回新的FormBuilder()
.Message(“欢迎使用bot!”)
.OnCompletion(异步(上下文、配置文件格式)=>
{
等待上下文。PostAsync(“谢谢”);
}).Build();
}

首先,您需要在LUIS门户上创建您的LUIS应用程序,在那里添加您的意图和话语,例如:-意图是“知识库”,您可以在其中创建尽可能多的话语,以返回此意图

在应用程序内部,创建一个LUISDialog类并从BuildForm调用它:-

    await context.Forward(new MyLuisDialog(), ResumeDialog, activity, CancellationToken.None);
路易斯Dialog类:-

  public class MyLuisDialog : LuisDialog<object>
{
    private static ILuisService GetLuisService()
    {
        var modelId = //Luis modelID;
        var subscriptionKey = //Luis subscription key
        var staging = //whether point to staging or production LUIS
        var luisModel = new LuisModelAttribute(modelId, subscriptionKey) { Staging = staging };
        return new LuisService(luisModel);
    }

    public MyLuisDialog() : base(GetLuisService())
    {

    }

 [LuisIntent("KnowledgeBase")]
    public async Task KnowledgeAPICall(IDialogContext context, LuisResult result)
    {
        //your code
    }
公共类MyLuisDialog:LuisDialog { 私有静态ILuisService GetLuisService() { var modelId=//路易斯modelId; var subscriptionKey=//路易斯订阅密钥 var staging=//是指向staging还是指向生产LUI var luisModel=new luisModel属性(modelId,subscriptionKey){Staging=Staging}; 返回新的LuisService(luisModel); } 公共MyLuisDialog():基(GetLuisService()) { } [LuisIntent(“知识库”)] 公共异步任务知识库(IDialogContext上下文,LuisResult结果) { //你的代码 }
要利用用户传递的消息,您可以从参数中的上下文中使用它。

FormFlow更适合引导对话流。在我看来,它似乎不符合您的要求。您只需使用PromptDialog获取用户对他们喜欢的搜索类型的答案,然后转发对应对话框的下一条消息。类似于:

[Serializable]
public class RootDialog : IDialog<object>
{
    const string QnAMakerOption = "QnA Maker";
    const string GoogleDriveOption = "Google Drive";
    const string QueryTypeDataKey = "QueryType";

    public Task StartAsync(IDialogContext context)
    {
        context.Wait(MessageReceivedAsync);

        return Task.CompletedTask;
    }

    private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var activity = await result as Activity;

        if(context.UserData.ContainsKey(QueryTypeDataKey))
        {
            var userChoice = context.UserData.GetValue<string>(QueryTypeDataKey);
            if(userChoice == QnAMakerOption)
                await context.Forward(new QnAMakerDialog(), ResumeAfterQnaMakerSearch, activity);
            else
                await context.Forward(new GoogleDialog(), ResumeAfterGoogleSearch, activity);
        }
        else
        {
            PromptDialog.Choice(
                  context: context,
                  resume: ChoiceReceivedAsync,
                  options: new[] { QnAMakerOption, GoogleDriveOption },
                  prompt: "Hi. How would you like to perform the search?",
                  retry: "That is not an option. Please try again.",
                  promptStyle: PromptStyle.Auto
            );
        }            
    }
    private Task ResumeAfterGoogleSearch(IDialogContext context, IAwaitable<object> result)
    {
        //do something after the google search dialog finishes
        return Task.CompletedTask;
    }
    private Task ResumeAfterQnaMakerSearch(IDialogContext context, IAwaitable<object> result)
    {
        //do something after the qnamaker dialog finishes
        return Task.CompletedTask;
    }

    private async Task ChoiceReceivedAsync(IDialogContext context, IAwaitable<object> result)
    {
        var userChoice = await result;
        context.UserData.SetValue(QueryTypeDataKey, userChoice);

        await context.PostAsync($"Okay, your preferred search is {userChoice}.  What would you like to search for?");
    }
}
[可序列化]
公共类RootDialog:IDialog
{
常量字符串QnAMakerOption=“QnA生成器”;
const string GoogleDriveOption=“Google Drive”;
常量字符串QueryTypeDataKey=“QueryType”;
公共任务StartSync(IDialogContext上下文)
{
Wait(MessageReceivedAsync);
返回Task.CompletedTask;
}
专用异步任务消息ReceivedAsync(IDialogContext上下文,IAwaitable结果)
{
var活动=等待作为活动的结果;
if(context.UserData.ContainsKey(QueryTypeDataKey))
{
var userChoice=context.UserData.GetValue(QueryTypeDataKey);
if(userChoice==QnAMakerOption)
wait context.Forward(新的QnAMakerDialog(),在qnamakersearch之后恢复,活动);
其他的
wait context.Forward(new GoogleDialog(),resumeafthegooglesearch,activity);
}
其他的
{
提示对话框。选择(
上下文:上下文,
简历:ChoiceReceivedAsync,
选项:新[]{QnAMakerOption,GoogleDriveOption},
提示:“您好,您希望如何执行搜索?”,
重试:“这不是一个选项。请重试。”,
promptStyle:promptStyle.Auto
);
}            
}
Google搜索后的私人任务恢复(IDialogContext上下文,IAwaitable结果)
{
//在谷歌搜索对话框结束后做些什么
返回Task.CompletedTask;
}
QNAMAKERSEARCH(IDialogContext上下文,IAwaitable结果)之后的私有任务ResumeAfterQnaMakerSearch(IDialogContext上下文,IAwaitable结果)
{
//在qnamaker对话框完成后执行某些操作
返回Task.CompletedTask;
}
专用异步任务ChoiceReceivedAsync(IDialogContext上下文,IAwaitable结果)
{
var userChoice=等待结果;
context.UserData.SetValue(QueryTypeDataKey,userChoice);
wait context.PostAsync($“好的,您首选的搜索是{userChoice}。您想搜索什么?”);
}
}

如何调用
wait context.Forward(新建MyLuisDialog(),ResumeDialog,活动