【问题标题】:How to make a custom attribute in C# for mapping intents in Microsoft Bot Framework?如何在 C# 中为 Microsoft Bot Framework 中的映射意图创建自定义属性?
【发布时间】:2018-04-22 22:56:04
【问题描述】:

[LuisIntent("")]属性使用ILuisService查询 LUIS 基于 LUISModel 属性的值,然后找出 得分最高的意图并匹配 IntentHandler 代表 重写 MessageRecievedAsync 方法并加载 LUISResult 在调试继承自 LuisDialog 的类时动态地在以下方法中。

public async Task None(IDialogContext context, LuisResult result)
{
  //some stuff
}

我的问题是如何制作一个自定义属性,将其映射到正确的意图处理程序。

我正在尝试使用 RASA NLU 服务作为我的 NLP 引擎以及 C# 中的 Microsoft Bot Framework。

我正在尝试将我从查询 RASA NLU 以获取 LUISResult 类型 JSON 的 HttpClient.GetAsync() 方法获得的 LUISEmulatedResult 映射到遵循此委托的方法。

我的进展:

[RASAIntentAttribute("IntentName")]

using Microsoft.Bot.Builder.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

namespace DemoFlightRASA.Models
{
    public class RASAIntentAttribute : Attribute
    {
        private readonly string _intentName;

        public RASAIntentAttribute(string IntentName)
        {
            this._intentName = IntentName;
        }

        //The intent handler delegate
        //Now I want to map LUISEmulatedResult which I get from HttpClient.GetAsync() method to a method which follows this delegate
        public delegate Task RASAIntentHandler(IDialogContext context, LUISEmulatedResult result);


    }
}

LUISEmulatedResult 模型类:

namespace DemoFlightRASA.Models
{
    public class LUISEmulatedResult
    {
        public string query { get; set; }
        public Topscoringintent topScoringIntent { get; set; }
        public Intent[] intents { get; set; }
        public Entity[] entities { get; set; }
    }

    public class Topscoringintent
    {
        public string intent { get; set; }
        public float score { get; set; }
    }

    public class Intent
    {
        public string intent { get; set; }
        public float score { get; set; }
    }

    public class Entity
    {
        public string entity { get; set; }
        public string type { get; set; }
        public int startIndex { get; set; }
        public int endIndex { get; set; }
        public Resolution resolution { get; set; }
        public float score { get; set; }
    }

    public class Resolution
    {
        public string[] values { get; set; }
    }

}

Also I tried this one, but this doesn't seem to work

我想在机器人框架中创建一个使用 RASA NLU 与 LUIS 相对的端到端流程。我已经准备好 RASA NLU 端点,只是无法创建 RASAIntentAttribute。

任何关于如何将委托映射到方法的指针、提示、教程、代码 sn-ps 将不胜感激。谢谢。

【问题讨论】:

  • 你检查过 LuisIntent 的代码以及它是如何工作的吗?
  • LuisDialog 的代码可以在这里找到:github.com/Microsoft/BotBuilder/blob/…
  • 是的,我看到了它是如何工作的,但我在某些时候卡住了。就像如何将委托 RASAIntentHandler 映射到 LUISResult。我对它是如何映射的感到困惑。任何指针都会有所帮助

标签: c# delegates attributes botframework rasa-nlu


【解决方案1】:

注意:我认为您不能将委托作为属性参数:Is it possible to have a delegate as attribute parameter?您打算如何使用 RASAIntentHandler 委托?

.net Bot Framework sdk 使用反射来确定 LuisDialog 中的哪些方法是意图处理程序:https://github.com/Microsoft/BotBuilder/blob/b6cd3ff85e8dc57ac586a11db489a0c75c635ae2/CSharp/Library/Microsoft.Bot.Builder/Dialogs/LuisDialog.cs#L362

public static IEnumerable<KeyValuePair<string, IntentActivityHandler>> EnumerateHandlers(object dialog)
        {
            var type = dialog.GetType();
            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            foreach (var method in methods)
            {
                var intents = method.GetCustomAttributes<LuisIntentAttribute>(inherit: true).ToArray();
                IntentActivityHandler intentHandler = null;

                try
                {
                    intentHandler = (IntentActivityHandler)Delegate.CreateDelegate(typeof(IntentActivityHandler), dialog, method, throwOnBindFailure: false);
                }
                catch (ArgumentException)
                {
                    // "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type."
                    // https://github.com/Microsoft/BotBuilder/issues/634
                    // https://github.com/Microsoft/BotBuilder/issues/435
                }

                // fall back for compatibility
                if (intentHandler == null)
                {
                    try
                    {
                        var handler = (IntentHandler)Delegate.CreateDelegate(typeof(IntentHandler), dialog, method, throwOnBindFailure: false);

                        if (handler != null)
                        {
                            // thunk from new to old delegate type
                            intentHandler = (context, message, result) => handler(context, result);
                        }
                    }
                    catch (ArgumentException)
                    {
                        // "Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type."
                        // https://github.com/Microsoft/BotBuilder/issues/634
                        // https://github.com/Microsoft/BotBuilder/issues/435
                    }
                }

                if (intentHandler != null)
                {
                    var intentNames = intents.Select(i => i.IntentName).DefaultIfEmpty(method.Name);

                    foreach (var intentName in intentNames)
                    {
                        var key = string.IsNullOrWhiteSpace(intentName) ? string.Empty : intentName;
                        yield return new KeyValuePair<string, IntentActivityHandler>(intentName, intentHandler);
                    }
                }
                else
                {
                    if (intents.Length > 0)
                    {
                        throw new InvalidIntentHandlerException(string.Join(";", intents.Select(i => i.IntentName)), method);
                    }
                }
            }
        }

这是 LuisDialog 中的代码,它调用与从 LUIS 返回的 IntentRecommendation 中的最佳意图相对应的处理程序:https://github.com/Microsoft/BotBuilder/blob/b6cd3ff85e8dc57ac586a11db489a0c75c635ae2/CSharp/Library/Microsoft.Bot.Builder/Dialogs/LuisDialog.cs#L252

protected virtual async Task DispatchToIntentHandler(IDialogContext context,
                                                            IAwaitable<IMessageActivity> item,
                                                            IntentRecommendation bestIntent,
                                                            LuisResult result)
        {
            if (this.handlerByIntent == null)
            {
                this.handlerByIntent = new Dictionary<string, IntentActivityHandler>(GetHandlersByIntent());
            }

            IntentActivityHandler handler = null;
            if (result == null || !this.handlerByIntent.TryGetValue(bestIntent.Intent, out handler))
            {
                handler = this.handlerByIntent[string.Empty];
            }

            if (handler != null)
            {
                await handler(context, item, result);
            }
            else
            {
                var text = $"No default intent handler found.";
                throw new Exception(text);
            }
        }

这是 LUIS 结果映射到 LUISDialogs 上标有 LUISIntentAttribute 的方法的方式。此功能或类似功能需要在 RASA 实现中。

【讨论】:

    猜你喜欢
    • 2022-08-19
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多