问题
i have created a bot in bot framework using also luis.ai.
In my luis account i have created two app with different language culture. One app in english and other in french. Both have their intents.
In my code i call one time english dialog, and other time french luis dialog .
My problem is that when i start conversation in english facebook channel ( messenger ) i get the right answer. Inside this bot and channel when i type in french , my bot don't call french dialog .
When i start conversation in french version of facebook ...the bot can't recognize the right dialog ...but catch an error : "Ooops! There are some problems with our system
I try to type english utterance and then i get : Ooops! Too many attemps :(. But don't worry, I'm handling that exception and you can try again!
My idea is that : when i'm inside facebook in english language and click : Get Started ...my conversation to start in english dialog ( AlltheBot.cs). If i type french word like : salut, demarrer the bot can forward to french dialog ( FrenchLuis.cs) . And the other way around, when i'm in facebook in french version my conversation when i click on Demarrer to start in french , and then if i type hello to forward in english dialog.
My code is here :
MessageController.cs
namespace MultiDialogsBot
{
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Http;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
using FirstBotApplication.Dialogs;
using System.Linq;
using System;
[BotAuthentication]
public class MessagesController : ApiController
{
/// <summary>
/// POST: api/Messages
/// Receive a message from a user and reply to it
/// </summary>
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
await Conversation.SendAsync(activity, () => new RootDialog());
}
else
{
this.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
IConversationUpdateActivity update = message;
var client = new ConnectorClient(new Uri(message.ServiceUrl),
new MicrosoftAppCredentials());
if (update.MembersAdded != null && update.MembersAdded.Any())
{
foreach (var newMember in update.MembersAdded)
{
if (newMember.Id != message.Recipient.Id && newMember.Id
!= message.Conversation.Id)
{
var reply = message.CreateReply();
reply.Text = $"Welcome" + " " +
message.Recipient.Name + " ! You are a new member! If you want to see
help menu , type : help";
client.Conversations.ReplyToActivityAsync(reply);
}
}
}
// 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;
}
}
}
RootDialog.cs
namespace FirstBotApplication.Dialogs
{
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Connector;
[Serializable]
public class RootDialog : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(this.MessageReceivedAsync);
}
public virtual async Task MessageReceivedAsync(IDialogContext context,
IAwaitable<IMessageActivity> result)
{
var message = await result;
if (message.Text.ToLower().Contains("Get Started") ||
message.Text.ToLower().Contains("hello") ||
message.Text.ToLower().Contains("hi"))
{
context.Call(new AllTheBot (), this.ResumeAfterOptionDialog);
}
else if (message.Text.ToLower().Contains("Démarrer") ||
message.Text.ToLower().Contains("salut") ||
message.Text.ToLower().Contains("french"))
{
context.Call(new FrenchLuis(), this.ResumeAfterOptionDialog);
}
else
{
await context.PostAsync($"Ooops! There are some problems with our system");
}
}
private async Task ResumeAfterOptionDialog(IDialogContext context,
IAwaitable<object> result)
{
await context.PostAsync($"Ooops! Too many attemps :(. But don't
worry, I'm handling that exception and you can try again!");
}
}
}
FrenchLuis.cs
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace FirstBotApplication
{
// [LuisModel("Please Enter Your LUIS Model ID", "Please Enter Your
LUIS
Subscription Key")]
[Serializable]
[LuisModel("aaaaaaa", "xxxxxxxxx")]
public class FrenchLuis : LuisDialog<object>
{
internal static string results;
// internal static string results;
[LuisIntent("None")]
[LuisIntent("")]
public async Task None(IDialogContext context, LuisResult result)
{
string message = $"Désolé je n'ai pas compris '{result.Query}'.
Veuillez reformuler votre question";
await context.PostAsync(message);
context.Wait(this.MessageReceived);
context.Done(true);
}
//french luis.ai
[LuisIntent("demarrerintent")]
public async Task demarrerintent(IDialogContext context,
IAwaitable<IMessageActivity> activity, LuisResult result)
{
await context.PostAsync("Bienvenue :) ");
context.Done(true);
}
[LuisIntent("denous")]
public async Task denous(IDialogContext context,
IAwaitable<IMessageActivity> activity, LuisResult result)
{
await context.PostAsync(" Nous sommes .....");
context.Done(true);
}
[LuisIntent("quisommes")]
public async Task quisommes(IDialogContext context, IAwaitable<IMessageActivity> activity, LuisResult result)
{
await context.PostAsync("Je suis un robot");
context.Done(true);
// context.Wait(MessageReceived);
}
}}
AllTheBot.cs
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.Luis;
using Microsoft.Bot.Builder.Luis.Models;
using Microsoft.Bot.Connector;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
namespace FirstBotApplication
{
[LuisModel("bbbbbb", "xxxxxxx")]
[Serializable]
public class AllTheBot : LuisDialog<object>
{
internal static string results;
// internal static string results;
[LuisIntent("None")]
[LuisIntent("")]
public async Task None(IDialogContext context, LuisResult result)
{
string message = $"Sorry, I did not understand '{result.Query}'.
Please reformulate your question";
await context.PostAsync(message);
context.Done(true);
// context.Wait(this.MessageReceived);
}
[LuisIntent("grettings")]
[LuisIntent("intentfr")]
public async Task Greeting(IDialogContext context,
IAwaitable<IMessageActivity> activity, LuisResult result)
{
await context.PostAsync("Welcome ");
context.Done(true);
}
[LuisIntent("test")]
public async Task test(IDialogContext context,
IAwaitable<IMessageActivity> activity, LuisResult result)
{
await context.PostAsync("Do you want to test our bot ? We suggest to
type : hi or who are you, help etc..");
context.Wait(MessageReceived);
}
}}
回答1:
I had a look to your project and got a few problems. You should go step by step to eliminate the problems as you are mixing many things (Dialog management, LUIS calls etc.)
RootDialog.cs
1st point:
message.Text.ToLower().Contains("Démarrer")
and
message.Text.ToLower().Contains("Get Started")
Those two tests can't be valid, as you are comparing something in lowercase and a word with an uppercase.
Moreover, there are better clever ways to get the events of Facebook Messenger 'Get Started' button click, but that's not the point here.
2nd point:
private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> result)
{
await context.PostAsync($"Ooops! Too many attemps :(. But don't worry, I'm handling that exception and you can try again!");
}
Your text here is quite strange for a dialog resume!
AllTheBot.cs and FrenchLuis.cs
When you call your 2 LuisDialog, you are never passing the value of the message to those dialogs, is this normal?
You should use context.Forward
instead of context.Call
: in that way your message will automatically be forwarded to the child dialog.
Global behaviour
I don't think you are going to the right way for managing languages. Why don't you use a valid Language Detection system to check which language is the content you received from the user?
The Text Analytics API from Microsoft Cognitive Services is here for this: https://azure.microsoft.com/en-gb/services/cognitive-services/text-analytics/
Dialog management in your case
I made a sample of the implementation of 2 dialogs management (without LUIS here) to show you what's working:
[Serializable]
public class Dialog44592511 : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
}
public virtual async Task MessageReceivedAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
{
var message = await result;
if (message.Text.ToLower().Contains("Get Started") ||
message.Text.ToLower().Contains("hello") ||
message.Text.ToLower().Contains("hi"))
{
await context.Forward(new Dialog44592511_EN(), this.ResumeAfterOptionDialog, message);
}
else if (message.Text.ToLower().Contains("Démarrer") || message.Text.ToLower().Contains("salut") || message.Text.ToLower().Contains("french"))
{
await context.Forward(new Dialog44592511_FR(), this.ResumeAfterOptionDialog, message);
}
else
{
await context.PostAsync($"Ooops! There are some problems with our system");
}
}
private async Task ResumeAfterOptionDialog(IDialogContext context, IAwaitable<object> result)
{
await context.PostAsync($"Resume!");
}
}
[Serializable]
public class Dialog44592511_FR : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
await context.PostAsync($"Vous êtes dans le dialogue FR");
context.Done<object>(null);
}
}
[Serializable]
public class Dialog44592511_EN : IDialog<object>
{
public async Task StartAsync(IDialogContext context)
{
context.Wait(MessageReceivedAsync);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
var activity = await result as Activity;
await context.PostAsync($"You are in the EN dialog");
context.Done<object>(null);
}
}
Don't hesitate to edit your question for more details
回答2:
Instead of doing context.Call
, you should use context.Forward
, which will forward the message to the dialog.
With the context.Call
you are just calling the dialog and leaving it ready to receive a new message.
You should review the different ways to initiate dialogs, explained here.
来源:https://stackoverflow.com/questions/44592511/how-to-switch-between-two-luis-ai-dialog-with-different-languages