• Features
  • Docs & Tutorials
  • Downloads
  • Blog
  • Community
  • Use Cases
  • v.0.7.4
  • GitHub
  1. Home
  2. Light Switch ex

Light Switch ex

  • Introduction
  • Overview
  • Installation
  • Getting Started
  • Developer Guide
  • Basic Concepts
  • First Example
  • Data Model
  • Intent Matching
  • REST API
  • Server & Probe
  • Metrics & Tracing
  • Integrations
  • Tools
  • nlpcraft.{sh|cmd}
  • Test Framework
  • Embedded Probe
  • SQL Model Generator
  • Synonyms Tool
  • Examples
  • Alarm Clock
  • Light Switch
  • Weather Bot
  • SQL Model

Overview

This example provides very simple implementation for NLI-powered light switch. You can say something like "Turn the lights off in the entire house" or "Switch on the illumination in the master bedroom closet". You can modify intent callbacks to perform the actual light switching using HomeKit or Arduino-based controllers.

Complexity:
Source code: GitHub

Create New Project

You can create new Scala project in many different ways - we'll use NLPCraft CLI to accomplish this task:

Command Output
                    $ bin/nlpcraft.sh gen-project --baseName=LightSwitch --outputDir=~ --pkgName=demo --lang=scala
                

NOTES:

  • New project created in /home/LightSwitch directory.
  • gen-project command defaults to Java and Maven as its built tool.
  • Run bin/nlpcraft.sh help --cmd=gen-project to get a full help on gen-project command.
  • NLPCraft CLI is available as nlpcraft.sh for and nlpcraft.cmd for .

Data Model

We are going to start with declaring the static part of our model using YAML which we will later load using NCModelFileAdapter in our Scala-based model implementation. Open src/main/resources/light_switch.yaml file and replace its content with the following YAML:

id: "nlpcraft.lightswitch.ex"
name: "Light Switch Example Model"
version: "1.0"
description: "NLI-powered light switch example model."
macros:
  - name: "<ACTION>"
    macro: "{turn|switch|dial|control|let|set|get|put}"
  - name: "<ENTIRE_OPT>"
    macro: "{entire|full|whole|total|*}"
  - name: "<LIGHT>"
    macro: "{all|*} {it|them|light|illumination|lamp|lamplight}"
enabledBuiltInTokens: [] # This example doesn't use any built-in tokens.
elements:
  - id: "ls:loc"
    description: "Location of lights."
    synonyms:
      - "<ENTIRE_OPT> {upstairs|downstairs|*} {kitchen|library|closet|garage|office|playroom|{dinning|laundry|play} room}"
      - "<ENTIRE_OPT> {upstairs|downstairs|*} {master|kid|children|child|guest|*} {bedroom|bathroom|washroom|storage} {closet|*}"
      - "<ENTIRE_OPT> {house|home|building|{1st|first} floor|{2nd|second} floor}"

  - id: "ls:on"
    groups:
      - "act"
    description: "Light switch ON action."
    synonyms:
      - "<ACTION> <LIGHT>"
      - "<ACTION> on <LIGHT>"

  - id: "ls:off"
    groups:
      - "act"
    description: "Light switch OFF action."
    synonyms:
      - "<ACTION> <LIGHT> {off|out}"
      - "{<ACTION>|shut|kill|stop|eliminate} {off|out} <LIGHT>"
      - "no <LIGHT>"
intents:
  - "intent=ls term(act)={groups @@ 'act'} term(loc)={id == 'ls:loc'}*"
        

There are number of important points here:

  • Line 10 defines several macros that are used later on throughout the model's elements to shorten the synonym declarations. Note how macros coupled with option groups shorten overall synonym declarations 1000:1 vs. manually listing all possible word permutations.
  • Lines 19, 26, 34 define three model elements: the location of the light, and actions to turn the light on and off. Note that action elements belong to the same group act which will be used in our intent (line 42).
  • On line 42 we define a non-conversational intent ls that requires one action (a token belonging to the group act) and optional light location - we assume all lights by default.

Now that our model is ready let's create a Java class that would load this model and provide the actual callback for when the intent ls is detected in the user input.

Model Class

Open src/main/scala/demo/LightSwitch.scala with the following code:

package demo

import org.apache.nlpcraft.model.{NCIntentTerm, _}

class LightSwitch extends NCModelFileAdapter("light_switch.yaml") {
    @NCIntentRef("ls")
    @NCIntentSample(Array(
        "Turn the lights off in the entire house.",
        "Switch on the illumination in the master bedroom closet.",
        "Get the lights on.",
        "Please, put the light out in the upstairs bedroom.",
        "Set the lights on in the entire house.",
        "Turn the lights off in the guest bedroom.",
        "Could you please switch off all the lights?",
        "Dial off illumination on the 2nd floor.",
        "Please, no lights!",
        "Kill off all the lights now!",
        "No lights in the bedroom, please."
    ))
    def onMatch(
        @NCIntentTerm("act") actTok: NCToken,
        @NCIntentTerm("loc") locToks: List[NCToken]
    ): NCResult = {
        val status = if (actTok.getId == "ls:on") "on" else "off"
        val locations =
            if (locToks.isEmpty)
                "entire house"
            else
                locToks.map(_.meta[String]("nlpcraft:nlp:origtext")).mkString(", ")

        // Add HomeKit, Arduino or other integration here.

        // By default - return a descriptive action string.
        NCResult.text(s"Lights '$status' in '${locations.toLowerCase}'.")
    }
}
        

The intent callback logic is very simple - we simply return a descriptive confirmation message back (explaining what lights were changed). With action and location detected - you can add the actual light switching using HomeKit or Arduino devices. Let's review this implementation step by step:

  • On line 5 our class extends NCModelFileAdapter that allows us to load most of the model declaration from the external YAML file and only provide functionality that we couldn't express in declarative portion in JSON.
  • Line 6 annotates method onMatch as a callback for the intent ls when it is detected in the user input.
  • Note the line 7 where we use @NCIntentSample annotation to provide samples of the user input that this intent should match. Apart from documentation purpose these samples will be used when we will be testing out model below.
  • Lines 21 and 22 map terms from detected intent to the formal method parameters of the onMatch method.
  • On the line 34 the intent callback simply returns a confirmation message.

Build Project

Once we have our model ready let's go to ~/LightSwitch directory and run the Maven build:

            $ cd ~/LightSwitch
            $ mvn clean package
        

At this stage we have our project built and we are ready to start testing.

Start Server

Run the following command to start local REST server, if it hasn't been started already, from the NLPCraft installation directory:

Command Output
                    $ bin/nlpcraft.sh start-server
                

NOTES:

  • REST server is a "fore-and-forget" component that you generally need to start only once.
  • Run bin/nlpcraft.sh help --cmd=start-server to get a full help on this command.
  • NLPCraft CLI is available as nlpcraft.sh for and nlpcraft.cmd for .

Testing

Remember the @NCIntentSample annotation we have used in our model code next to intent definition?

Part of the test framework, the auto-validator class NCTestAutoModelValidator takes one or more model IDs (or class names) and performs validation. Validation consists of starting an embedded probe with a given model, scanning for @NCIntentSample annotations and their corresponding callback methods, submitting each sample input sentences from @NCIntentSample annotation and checking that resulting intent matches the intent the sample was attached to. Note that auto-testing does not require any additional code to be written - the class gathers all required information from the model itself.

As always, you can launch model auto-validator as any other Java class but we'll use NLPCraft CLI to do it more conveniently:

            $ bin/nlpcraft.sh test-model --cp=~/LightSwitch/target/classes --mdls=demo.LightSwitch
        

NOTES:

  • Run bin/nlpcraft.sh help --cmd=test-model to get a full help on this command.
  • NLPCraft CLI is available as nlpcraft.sh for and nlpcraft.cmd for .

Look at the output of this command and you will see the test results for all our sample utterances:

Rinse & Repeat

Typical development cycle consists of:

  • Modifying the model
  • Re-building the project
  • Re-running the test

All of these operations can be performed from NLPCraft CLI in REPL mode or from any IDE.

NOTE: you don't need to restart REST server every time - it only needs to be started once.

Done! 👌

You've created light switch data model, started the REST server and tested this model using the built-in test framework.

  • On This Page
  • Overview
  • New Project
  • Data Model
  • Model Class
  • Build Project
  • Start Server
  • Testing
  • Rinse & Repeat
  • Quick Links
  • Examples
  • Javadoc
  • REST API
  • Download
  • Cheat Sheet
  • Support
  • JIRA
  • Dev List
  • Stack Overflow
  • GitHub
  • Gitter
Copyright © 2021 Apache Software Foundation asf Events • Privacy • News • Docs release: 0.7.4 Gitter Built in: