How do you get to the original message text in a Microsoft Bot Framework LuisIntent method
Asked Answered
N

4

10

I'm trying to access the complete original text from within a method marked as a LuisIntent within a LuisDialog.

The documentation shows these methods as taking two arguments:

IDialogContext context, LuisResult result

Neither of which publicly exposes the original text of the message. The context object does contain the message but in a private property (context.data.message.text) which is not accessible.

Is there a way to access this in the context, or can it be passed into the dialog constructor?

Naught answered 7/4, 2016 at 16:51 Comment(0)
H
8

You can override the MessageReceived(...) function of the LuisDialog keep the fields of the message that you need as member variables and access those fields in your intent handlers. Below I modified the SimpleAlarmDialog to show how you can access 'message.Text' in one of the intent handlers:

[LuisModel("c413b2ef-382c-45bd-8ff0-f76d60e2a821", "6d0966209c6e4f6b835ce34492f3e6d9")]
[Serializable]
public class SimpleAlarmDialog : LuisDialog<object>
{
    private readonly Dictionary<string, Alarm> alarmByWhat = new Dictionary<string, Alarm>();

    [Serializable]
    public class PartialMessage
    {
        public string Text { set; get; }
    }

    private PartialMessage message;

    protected override async Task MessageReceived(IDialogContext context, IAwaitable<Message> item)
    {
        var msg =  await item;
        this.message = new PartialMessage { Text = msg.Text };
        await base.MessageReceived(context, item);
    }

    [LuisIntent("builtin.intent.alarm.delete_alarm")]
    public async Task DeleteAlarm(IDialogContext context, LuisResult result)
    {
        await context.PostAsync($"echo: {message.Text}");
        Alarm alarm;
        if (TryFindAlarm(result, out alarm))
        {
            this.alarmByWhat.Remove(alarm.What);
            await context.PostAsync($"alarm {alarm} deleted");
        }
        else
        {
            await context.PostAsync("did not find alarm");
        }

        context.Wait(MessageReceived);
    }
}
Highpitched answered 11/4, 2016 at 21:0 Comment(2)
Even though the 1.0.2 version of the Bot Framework adds the message text, it still doesn't include all the additional information, ConversationId etc., included in the Controller's message object. This allows me to add whatever additional fields I need. Thanks!Naught
Although this worked for V1 of the Bot Framework, it seems to fail for V3. If you attempt to override the async method, it returns a Internal Server error when to call the base.MessageReceived.Krasnoyarsk
C
9

With the new version of Bot Framework (1.0.2) the LuisResult object now has a Query parameter that contains the original query sent to LUIS.

Culpa answered 14/4, 2016 at 10:53 Comment(0)
H
8

You can override the MessageReceived(...) function of the LuisDialog keep the fields of the message that you need as member variables and access those fields in your intent handlers. Below I modified the SimpleAlarmDialog to show how you can access 'message.Text' in one of the intent handlers:

[LuisModel("c413b2ef-382c-45bd-8ff0-f76d60e2a821", "6d0966209c6e4f6b835ce34492f3e6d9")]
[Serializable]
public class SimpleAlarmDialog : LuisDialog<object>
{
    private readonly Dictionary<string, Alarm> alarmByWhat = new Dictionary<string, Alarm>();

    [Serializable]
    public class PartialMessage
    {
        public string Text { set; get; }
    }

    private PartialMessage message;

    protected override async Task MessageReceived(IDialogContext context, IAwaitable<Message> item)
    {
        var msg =  await item;
        this.message = new PartialMessage { Text = msg.Text };
        await base.MessageReceived(context, item);
    }

    [LuisIntent("builtin.intent.alarm.delete_alarm")]
    public async Task DeleteAlarm(IDialogContext context, LuisResult result)
    {
        await context.PostAsync($"echo: {message.Text}");
        Alarm alarm;
        if (TryFindAlarm(result, out alarm))
        {
            this.alarmByWhat.Remove(alarm.What);
            await context.PostAsync($"alarm {alarm} deleted");
        }
        else
        {
            await context.PostAsync("did not find alarm");
        }

        context.Wait(MessageReceived);
    }
}
Highpitched answered 11/4, 2016 at 21:0 Comment(2)
Even though the 1.0.2 version of the Bot Framework adds the message text, it still doesn't include all the additional information, ConversationId etc., included in the Controller's message object. This allows me to add whatever additional fields I need. Thanks!Naught
Although this worked for V1 of the Bot Framework, it seems to fail for V3. If you attempt to override the async method, it returns a Internal Server error when to call the base.MessageReceived.Krasnoyarsk
S
1

If you break into the method, you can see in the quick watch that the context object has a non-public property through to context.data.mesage.Text (note the misspelling of "mesage"). Since the property is non-public, you could cheat by using reflection to get at it (see GetInstanceField in How to get the value of private field in C#?)

        Microsoft.Bot.Builder.Dialogs.Internals.JObjectBotData data = GetInstanceField(typeof (Microsoft.Bot.Builder.Dialogs.Internals.DialogContext), context, "data") as Microsoft.Bot.Builder.Dialogs.Internals.JObjectBotData;            
        Microsoft.Bot.Connector.Message originalMessage = GetInstanceField(typeof(Microsoft.Bot.Builder.Dialogs.Internals.JObjectBotData), data, "mesage") as Microsoft.Bot.Connector.Message;
        string originalMessageText = originalMessage.Text;
Stemma answered 11/4, 2016 at 16:46 Comment(0)
W
0

You could do it like this by using the Query property of the LuisResult,

[LuisIntent(intentName: "someIntentName")]
private async Task Eligibility(IDialogContext context, LuisResult result)
 {
   await context.PostAsync($"The original text is: {result.Query}");
   context.Wait(MessageReceivedAsync);
}
Welldone answered 4/7, 2017 at 6:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.