Integration with NLP engine (Amazon Lex)

Hi,

I’ve managed to integrate Lookerbot with Amazon Lex, for using free text requests instead of specific commands:

  • Custom command in Lookerbot posts message text to Amazon Lex bot
  • Amazon Lex bot detects intent, and returns that back to Lookerbot
  • Lookerbot uses the intent name to map to the actual Looker dashboard

Here is a code snippet for that custom command in Lookerbot:

 import * as _ from "underscore"
 import config from "../config"
 import { Looker } from "../looker"
 import { DashboardQueryRunner } from "../repliers/dashboard_query_runner"
 import { ReplyContext } from "../reply_context"
 import { Command } from "./command"
 import * as AWS from "aws-sdk"

export class CustomNlpCommand extends Command {

public attempt(context: ReplyContext) {

AWS.config.update({ region: 'eu-west-1' });

var lexruntime = new AWS.LexRuntime();

var params = {
  botAlias: '$LATEST', /* required, has to be '$LATEST' */
  botName: 'lookerbot', /* required, the name of you bot */
  inputText: context.sourceMessage.text.toLowerCase(), /* required, your text */
  userId: 'lookerbot' /* required, arbitrary identifier */
};

lexruntime.postText(params, function (err, data) {
  if (err) {
    console.log(err, err.stack); // an error occurred
    return false
  }
  else {
    console.log(data);           // successful response

    if (!data.intentName) {
      console.log("Cannot find intent");
      context.replyPrivate(":crying_cat_face: " + data.message);
      return false;
    }

    const normalizedText = data.intentName!.toLowerCase()
    const shortCommands = _.sortBy(_.values(Looker.customCommands), (c) => -c.name.length)
    const matchedCommand = shortCommands.filter((c) => normalizedText.indexOf(c.name) === 0)[0]
    if (matchedCommand) {

      if (data.message) context.replyPrivate(":smirk_cat: " + data.message);

      const { dashboard } = matchedCommand
      const query = matchedCommand.name
      normalizedText.indexOf(matchedCommand.name)
      context.looker = matchedCommand.looker

      const runner = new DashboardQueryRunner(context, matchedCommand.dashboard, {})
      runner.start()

      return true
    } else {
      return false
    }
  }
});

return false
}
}
5 Likes

This is awesome, nice work @Olegas_Murasko!

This is so cool! There’s one specific Lookerbot command that I always mess up in some minor way, and this would be really helpful.
I’ve actually never seen a custom Lookerbot command defined before, could you quickly explain how to implement one?

All commands are stored here: https://github.com/looker/lookerbot/tree/master/src/commands

I did the following:

  1. Copied custom_command.ts, renamed that to custom_nlp_command.ts
  2. In custom_nlp_command.ts, changed the class name to CustomNlpCommand
  3. Modified the “attempt” method of CustomNlpCommand to send the message text to Amazon Lex, get back identified intent, and run a Looker query with DashboardQueryRunner with that intent name (assuming there is a dashboard with such name is already created in Looker)
  4. Custom commands return “true”, if the handling attempt is successful (and “false” otherwise) - so, return “true”, if the intent has been detected by Lex, and DashboardQueryRunner gets back the actual dashboard
  5. Modify “commands” list in index.ts (/src/index.ts#L24) to include that new CustomNlpCommand command

In my case, I have removed other non-NLP commands from the command list entirely, as all other commands are handled over NLP with free text.

Thanks.

3 Likes