New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LUIS] How could call Luis inside a new dialog? #2741

Closed
wolf0x opened this Issue May 11, 2017 · 14 comments

Comments

Projects
7 participants
@wolf0x
Copy link

wolf0x commented May 11, 2017

System Information (Required)

  • SDK language (Node)
  • **Development environment - localhost **
  • Node.js + npm version
    6.9.5 + 4.5.0

Issue Description

How could call Luis inside a sub dialog?
I have a app.js which will match the intents of the user's request, then it will begin a new dialog while matched. however in the new dialog, it will ask user more questions, and I need LUIS to match and recognize the user's inputting on the new dialog, how could i do that?

Example Code

// this code inside app.js, it will match the intent of the keyword when user want to search something.

intents.matches('search', [
    function(session,result){
        session.beginDialog('procgosh:GoShDialog', session.message.text);
        },
    function(session,result){
        session.send('Thanks for your information and do you have any other request?');
    }    
]);

// when it match the search, it will redirect to GoShDialog (procgosh.js), and its a new waterfall question dialog, and I need same Luis to match and recognize more user's inputting on that dialog, how could i do?

@wolf0x wolf0x changed the title How could call Luis inside a sub dialog? How could call Luis inside a new dialog? May 11, 2017

@stevengum

This comment has been minimized.

Copy link
Member

stevengum commented May 11, 2017

If you're redirecting from the first waterfall step, I would say to just send the args object from your 'search' intent. This object will have been ran through LUIS and have what you're looking for. I've rewritten parts of your code below.

intents.matches('search', [
    function(session, args) {                               // Convention has the second parameter in the initial waterfall step named 'args'
        session.beginDialog('procgosh:GoShDialog', args);   // If you send session.message.text, it'll just send the string, which isn't everything you're asking for
     },
    function(session, results){                             // Likewise, convention is to call it results, not result here.
        session.send('Thanks for your information and do you have any other request?');
        session.endDialog();                                // Even when testing, it is important to end your dialogs, otherwise you will be stuck here.
    }    
]);

@stevengum stevengum changed the title How could call Luis inside a new dialog? [LUIS] How could call Luis inside a new dialog? May 11, 2017

@stevengum stevengum self-assigned this May 11, 2017

@Stevenic

This comment has been minimized.

Copy link
Contributor

Stevenic commented May 11, 2017

So I've been asked before how to build a prompt based on a LUIS model and with v3.8 that we released this week it's now easier then ever. Here's how to use the new prompt customization system to build a custom LUIS prompt:


// Create a recognizer for your LUIS model
var recognizer = new builder.LuisRecognizer('<model>');

// Create a custom prompt
var prompt = new builder.Prompt({ defaultRetryPrompt: "I'm sorry. I didn't recognize your search." })
    .onRecognize(function (context, callback) {
        // Call prompts recognizer
        recognizer.recognize(context, function (err, result) {
            // If the intent returned isn't the 'None' intent return it
            // as the prompts response.
            if (result && result.intent !== 'None') {
                callback(null, result.score, result);
            } else {
                callback(null, 0.0);
            }
        });
    });

// Add your prompt as a dialog to your bot
bot.dialog('myLuisPrompt', prompt);

// Add function for calling your prompt from anywhere
builder.Prompts.myLuisPrompt = function (session, prompt, options) {
    var args = options || {};
    args.prompt = prompt || options.prompt;
    session.beginDialog('myLuisPrompt', args);
}

Now to use your custom prompt you can call it like any other prompt:

bot.dialog('foo', [
     function (session) {
          builder.Prompts.myLuisPrompt(session, "Please say something I recognize");
     },
     function (session, results) {
          switch (results.response.intent) {
               case 'Bar':
                    break;
          }
     }
]);

Anytime the prompt recognizes an intent from your model (other than None) it will return the matched intent.

Is that what you're wanting?

@wolf0x

This comment has been minimized.

Copy link
Author

wolf0x commented May 12, 2017

emm... actually, its not what I want...let me clarify again.

on App.js file, I used Luis to match the utterance and if it find the the entity belongs to Type, then begin a new dialog, like what I did in below,
`

intents.matches('search', [
    function(session, args, next) { 
        var request = builder.EntityRecognizer.findEntity(args.entities, 'TYPE'); 
        if (!request) {                    
            session.beginDialog('procgosh:GoShDialog', args);  
        }
        else{
            next({response:request.entity});
       }
     },
    function(session, results){                            
        session.send('Thanks for your information and do you have any other request?');
        session.endDialog();                               
    }    
]);

however, when I in procgosh.js file, I have a waterfall to ask user input more requirement fields, such as color, size, price etc..and there's one more filed is called "special", it allows user to input something, I want the procgosh.js is able to recognize the user's inputting to another intent of LUIS, right now, I have to use HTTP Request to query the Json file back and parse it, such as below, so I want to know if there's any way to reuse builder.EntityRecognizer.findEntity instead of below callback function. tkx.

// this code is on procgosh.js
                    var LUISURL = process.env.LUIS_MODEL_URL;
                    var query = results.response;
                    request(LUISURL + query, function(error, response, body) {
                        let jbody = JSON.parse(body);
                        console.log('---------request body-------------');
                        console.log(jbody.entities[0].type);
                    });  

`

@wolf0x

This comment has been minimized.

Copy link
Author

wolf0x commented May 13, 2017

@stevengum97 I tried to renew a new LUIS instance on the procgosh.js file, in one of waterfall steps, however this doesnt work as return Null, or will error to me with "module has been used" so, how can i use LUIS to recognize the result.response?

                    var request = builder.EntityRecognizer.findEntity(result.response, 'TYPE');
                    console.log('---------request body-------------');
                    console.log(request);
@Stevenic

This comment has been minimized.

Copy link
Contributor

Stevenic commented May 16, 2017

@wolf0x you can call LUIS manually using builder.LuisRecognizer.recognize() so something like:

builder.LuisRecognizer.recognize(session.message.text, '<model url>', function (err, intents, entities) {
     if (entities) {
            var entity = builder.EntityRecognizer.findEntity(entities, 'TYPE');
            // do something with entity...
     }
});
@wolf0x

This comment has been minimized.

Copy link
Author

wolf0x commented May 17, 2017

@Stevenic great and thanks, thats what I want.. tkx again.

@stevengum

This comment has been minimized.

Copy link
Member

stevengum commented May 17, 2017

Closing issue

@SamuelTassell

This comment has been minimized.

Copy link

SamuelTassell commented Jun 9, 2017

So I'd thought I'd leave a comment here as I was in need of calling multiple LUIS models in dialog's. I just used a part of your custom prompt @Stevenic to use the session at the start of a dialog instead:

bot.dialog('foo', [
    function (session) {
        // As long as the message is being passed here with the session we can:
        recognizer.recognize(session, function (err, result) {
            console.log(result);
            if (result && result.intent !== 'None') {
                // Match
            } else {
                // No match
            }
        });
    }
]);

This way I get the matched intent too, as opposed to just getting and array of intents and entities by manually using builder.LuisRecognizer.recognize() as you mentioned above. 👍

ADDED:
Also, in my instance I wanted to store the original utterance so I can check it in a later dialog using the code from above.

I'm not sure if this is the best way but I stored the original message like so:

function (session, results) {
	// Store the utterance message object
	session.userData.utterance = {};
	session.userData.utterance.message = session.message;
}

Then used it in a later dialog:

function (session) {
	// On passing the 'session.userData.utterance'
	// the recognizer uses the stored message object
	recognizer.recognize(session.userData.utterance, function (err, result) {
		if (result && result.intent !== 'None') {
			// Match
		} else {
			// No match
		}
	});

},
@aakashkag

This comment has been minimized.

Copy link

aakashkag commented Jun 9, 2017

I am facing similar problem
how to call luis dialog from general dialog

dialog.matches('morningUpdate',[    
    function (session, args, next) {
  }
]);

bot.dialog('/work', [
  function (session, args) {
    //how to call here "morningUpdate" dialog
  }
]);


@SamuelTassell

This comment has been minimized.

Copy link

SamuelTassell commented Jun 9, 2017

I'm not sure your issue relates to this, would this not work in your case:

bot.dialog('/morningUpdate', [
    function (session, args, next) {
        // DO SOMETHING
    }
]).triggerAction({
    matches: 'morningUpdate'
});

bot.dialog('/work', [
    function (session, args) {
        // DO SOMETHING
	session.replaceDialog('/morningUpdate');
	// OR IF YOU WANT TO RETURN TO THIS DIALOG AFTERWARDS
	session.beginDialog('/morningUpdate');
    },
    ...
]);
@stevengum

This comment has been minimized.

Copy link
Member

stevengum commented Jun 9, 2017

#2741 (comment)

dialog.matches('morningUpdate', 'morningUpdate');

bot.dialog('morningUpdate', [    
    function (session, args, next) {
   
    }
]);

bot.dialog('/work', [
  function (session, args) {
    builder.LuisRecognizer.recognize(session.message.text, '<model url>', function (err, intents, entities) {
      var result = {};
      result.intents = intents;
      result.entities = entities;
      intents.forEach(function (intent) {
        if (intent.intent == 'morningUpdate') {
          session.beginDialog('morningUpdate', result);
        } else {
          // Do other stuff
        } 
      }
    });
  }
]);

@aakashkag Is this what you're asking for?

@aakashkag

This comment has been minimized.

Copy link

aakashkag commented Jun 16, 2017

yes exactly . btw thanks so much

@akontsevich

This comment has been minimized.

Copy link

akontsevich commented Aug 23, 2017

@wolf0x you can call LUIS manually using builder.LuisRecognizer.recognize() so something like:

Add this to the documentation please! Spent too many time to find this.

@EricDahlvang

This comment has been minimized.

Copy link
Collaborator

EricDahlvang commented Aug 23, 2017

@akontsevich This is a closed issue. Please open a new issue for your request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment