我使用Microsoft机器人框架制作了Bot,并使用Luis进行了匹配。一些意图将其定向到QNA,另一些意图将其定向到图形api。
我的问题是识别它应该转到qna以便在qna中搜索相关意图的最佳方法,还是应该转到图形api来获取结果的最佳方法是什么。
到目前为止,我使用多个Luis Intents进行了匹配,以匹配正确的Intent,然后根据所需的Intent功能将其重定向(无论是将其定向到QNA对话框还是图形API对话框)。
`[LuisModel(“ model id”,“ key”)]
[Serializable]
public class RootDialog : DispatchDialog
{
//this intent directs to graph api dialog
[LuisIntent(DialogMatches.GraphApiIntent)]
public async Task RunGraphapiIntent(IDialogContext context, IActivity activity)
{
UserMessage = (activity as IMessageActivity).Text;
await context.Forward(new GraphApiDailog(), EndDialog, context.Activity, CancellationToken.None);
}
//This intent directs to qna dialog
[LuisIntent(DialogMatches.BlogMatch)]
public async Task RunBlogDialogQna(IDialogContext context, LuisResult result)
{
var userQuestion = (context.Activity as Activity).Text;
(context.Activity as Activity).Text = DialogMatches.BlogMatch;
await context.Forward(new BasicQnAMakerDialog(), this.EndDialog, context.Activity, CancellationToken.None);
}
`
但是这种方法要求我使用[LuisIntent("intentstring")]
..来匹配每个意图。由于我可以拥有50或100个意图,因此为50个意图编写50个函数并不现实。
我在快速入门中找到了一种方法来调用api从话语中获取意图:使用C#分析文本
它利用了“ https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/df67dcdb-c37d-46af-88e1-8b97951ca1c2?subscription-key=&q =打开卧室灯” api用于获取意图。
同样,我的问题是我如何知道应该使用我得到的意图结果将其重定向到QnaDialog还是Graph Api Dialog来获取数据?
提前致谢
如果您希望扩展规模,则可以编写自己的调用Luis API的Nlp服务来检测意图,从而获得更好的收益。我认为按意图处理对话框重定向的最佳方法是制作类似IntentDetectorDialog的东西,其唯一的工作就是分析用户的话语并转发到与检测到的意图对应的对话框。
这是我一段时间以来一直使用的一种整洁的方法:
public abstract class BaseDialog : IDialog<BaseResult>
{
public bool DialogForwarded { get; protected set; }
public async Task StartAsync(IDialogContext context)
{
context.Wait(OnMessageReceivedAsync);
}
public async Task OnMessageReceivedAsync(
IDialogContext context,
IAwaitable<IMessageActivity> result)
{
var message = await result;
var dialogFinished = await HandleMessageAsync(context, message);
if (DialogForwarded) return;
if (!dialogFinished)
{
context.Wait(OnMessageReceivedAsync);
}
else
{
context.Done(new DefaultDialogResult());
}
}
protected abstract Task<bool> HandleMessageAsync(IDialogContext context, IMessageActivity message);
protected async Task ForwardToDialog(IDialogContext context,
IMessageActivity message, BaseDialog dialog)
{
DialogForwarded = true;
await context.Forward(dialog, (dialogContext, result) =>
{
// Dialog resume callback
// this method gets called when the child dialog calls context.Done()
DialogForwarded = false;
return Task.CompletedTask;
}, message);
}
}
基本对话框是所有其他对话框的父级,将处理该对话框的一般流程。如果对话框尚未结束,它将通过调用通知bot框架,context.Wait
否则将以结束对话框context.Done
。它还将强制所有子对话框执行该方法HandleMessageAsync
,该方法返回一个bool
指示该对话框是否已完成的指示。并且还公开了可重用的方法ForwardToDialog
,我们IntentDetectorDialog
将使用该方法来处理意图重定向。
public class IntentDetectorDialog : BaseDialog
{
private readonly INlpService _nlpService;
public IntentDetectorDialog(INlpService nlpService)
{
_nlpService = nlpService;
}
protected override async Task<bool> HandleMessageAsync(IDialogContext context, IMessageActivity message)
{
var intentName = await _nlpService.AnalyzeAsync(message.Text);
switch (intentName)
{
case "GoToQnaDialog":
await ForwardToDialog(context, message, new QnaDialog());
break;
case "GoToGraphDialog":
await ForwardToDialog(context, message, new GraphDialog());
break;
}
return false;
}
}
那是IntentRedetectorDialog
:儿子,BaseDialog
其唯一的工作就是检测意图并转发到相应的对话框。为了使事情更具可伸缩性,您可以实现一个IntentDialogFactory,它可以根据检测到的意图来构建对话框。
public class QnaDialog : BaseDialog
{
protected override async Task<bool> HandleMessageAsync(IDialogContext context, IMessageActivity message)
{
if (message.Text == "My name is Javier")
{
await context.PostAsync("What a cool name!");
// question was answered -> end the dialog
return true;
}
else
{
await context.PostAsync("What is your name?");
// wait for the user response
return false;
}
}
}
最后,我们有了QnaDialog
:还有一个儿子,BaseDialog
他的唯一工作就是询问用户名并等待响应。
编辑
根据您的评论,您可以在NlpService中拥有:
public class NlpServiceDispatcher : INlpService
{
public async Task<NlpResult> AnalyzeAsync(string utterance)
{
var qnaResult = await _qnaMakerService.AnalyzeAsync(utterance);
var luisResult = await _luisService.AnalyzeAsync(utterance);
if (qnaResult.ConfidenceThreshold > luisResult.ConfidenceThreshold)
{
return qnaResult;
}
else
{
return luisResult;
}
}
}
然后将更IntentDetectorDialog
改为:
public class UtteranceAnalyzerDialog : BaseDialog
{
private readonly INlpService _nlpService;
public UtteranceAnalyzerDialog(INlpService nlpService)
{
_nlpService = nlpService;
}
protected override async Task<bool> HandleMessageAsync(IDialogContext context, IMessageActivity message)
{
var nlpResult = await _nlpService.AnalyzeAsync(message.Text);
switch (nlpResult)
{
case QnaMakerResult qnaResult:
await context.PostAsync(qnaResult.Answer);
return true;
case LuisResult luisResult:
var dialog = _dialogFactory.BuildDialogByIntentName(luisResult.IntentName);
await ForwardToDialog(context, message, dialog);
break;
}
return false;
}
}
那里有!您无需在Luis和QnaMaker中重复说话,您可以同时使用这两者并根据更自信的结果设置策略!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句