A web script for end2end NLP Text to template

The NLP Text-to-template feature in the console and REST api allows you to convert natural language input to a waylay rule template. In console this template can be saved and tested.

But what if you want to generate and execute that template immediately?

Thats where this utility comes in: a waylay web script that invokes NLP text to template AND executes it.

Set up

  • Login into console and create a webscript at Console
  • Give it a name (e.g. executNlp)
  • paste the following code
//   
//  NLP Text to template, see https://forum.waylay.io/t/a-web-script-for-end2end-nlp-text-to-template/84
//
const NLP_ENDPOINT = 'https://nlp-io.waylay.io/nlp/v0'
const RULES_ENDPOINT = 'https://api-io.waylay.io/rules/v1'
const DEFAULT_RULEBASE = 'weather_only'
const TRIGGER_RESOURCE = 'nlpWebscriptActuation'

// as `waylay.nlp` is currently not general available, we use this `waylay._request` workaround
// for authenticated api calls to the waylay API
async function invokeNlpTextToTemplate (rulebase, utterance) {
  return waylay._request({
    url: `${NLP_ENDPOINT}/rulebase/${rulebase}`,
    headers: { 'content-type': 'application/json' },
    method: 'POST',
    data : { utterance }
  })
}

async function invokeTemplateRun( templateNetwork ) {
  // a small hack until trigger input binding is correctly implemented
  // or we have a way to run a template with a single tick
  templateNetwork.sensors[0].dataTrigger=true
  templateNetwork.sensors[0].resource='$'
  return waylay._request({
    url: `${RULES_ENDPOINT}/templates/run`,
    headers: { 'content-type': 'application/json' },
    method: 'POST',
    data : { 
      graph: templateNetwork,
      data: [ [ { resource: TRIGGER_RESOURCE } ] ],
      conf: {
        resource: TRIGGER_RESOURCE,
        resetObservations: true,
        executeActuators: false
      }
    }
  })
}

async function handleRequest (req, res) {
  if (req.method !== 'POST') {
    res.sendStatus(405)
    return
  }
  try {
    const { rulebase=DEFAULT_RULEBASE, utterance } = req.body
    const { canonical, rule_template } = await invokeNlpTextToTemplate(rulebase, utterance);
    const { sensors } = await invokeTemplateRun(rule_template)
    res.send({ utterance, canonical, sensors });
  } catch (err) {
    const error = err.response ? err.response.data : err.message;
    console.error(error);
    res.status(500).send(error);
  }
}
  • save the webscript, and wait until it is completed

Testing the web script

  • copy the URL of the webscript and test it. e,g, using curl:
curl "https://webscripts-io.waylay.io/api/v1/${webscript_path}?secret=${webscript_secret}" \
-H 'content-type: application/json' \
-X POST -d '{"utterance":"Is it snowing in Melle?", "rulebase":"weather_only"}' \

The result will show you the initial input utterance, the canonical expression, and the output state of one execution of the task network (sensors only, but you can adapt the script)

{
  "utterance": "Is it snowing in Melle?",
  "canonical": "(weather condition in Melle) equals \"Snow\"",
  "sensors": {
    "weatherConditionInMelle": {
      "executed": true,
      "result": true,
      "state": "Collected",
      "rawData": {
        "temperature": -0.74,
        "temp_feel": -7.14,
        "pressure": 1008,
        "humidity": 92,
        "temp_min": -1.33,
        "temp_max": 0.77,
        "wind_speed": 7.64,
        "wind_direction": 46,
        "clouds_coverage": 100,
        "sunrise": 1648789292,
        "sunset": 1648835951,
        "longitude": 8.35,
        "latitude": 52.2,
        "name": "Melle",
        "condition": "Snow",
        "icon": "http://openweathermap.org/img/w/13d.png"
      },
      "log": []
    },
    "isSnow": {
      "executed": true,
      "result": true,
      "state": "True",
      "rawData": {},
      "log": []
    }
  }
}