Gene Reddick
Gene Reddick

Reputation: 4655

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

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?

Upvotes: 10

Views: 2738

Answers (4)

Kunal Mukherjee
Kunal Mukherjee

Reputation: 5853

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);
}

Upvotes: 0

fdezjose
fdezjose

Reputation: 617

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.

Upvotes: 9

Shahin Shayandeh
Shahin Shayandeh

Reputation: 304

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);
    }
}

Upvotes: 8

Andy Thomas
Andy Thomas

Reputation: 1367

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;

Upvotes: 1

Related Questions