WIP on NLPCRAFT-390
7 files changed
tree: 0ea2f306192abc1560983ffa5e15f98b0407b562
  1. .asf.yaml
  2. .github/
  3. .gitignore
  4. DISCLAIMER-WIP
  5. LICENSE
  6. NOTICE
  7. README.md
  8. assembly.xml
  9. bin/
  10. bindist/
  11. docker/
  12. external/
  13. idea/
  14. javadoc/
  15. nlpcraft-examples/
  16. nlpcraft-stanford/
  17. nlpcraft/
  18. openapi/
  19. pom.xml
  20. sql/
README.md

License Build Documentation Status Gitter

What is Apache NLPCraft?

Apache NLPCraft is an open source library for adding a natural language interface for modern applications. It enables people to interact with your products using voice or text:

Why Natural Language?

Natural Language Interface enables users to interact with any type of products using natural language augmenting existing UI/UX with fidelity and simplicity of a familiar spoken language. Natural Language has no learning curve, no special rules or UI to master, no cumbersome syntax or terms to remember - it's just a natural interface that your users already know.

Key Features

Intent Definition Language

Advanced Intent Definition Language (IDL) coupled with deterministic intent matching provide ease of use and unprecedented expressiveness for designing real-life, non-trivial intents.

Composable Named Entities

Easily compose, mix and match new named entities out of built-in or external ones, creating new reusable named entity recognizers on the fly.

Short-Term-Memory

Advanced out-of-the-box support for maintaining and managing conversational context that is fully integrated with intent matching.

Model-As-A-Code

Everything you do with NLPCraft is part of your source code. No more awkward web UIs splitting your logic across different incompatible places. Model-as-a-code is built by engineers, and it reflects how engineers work.

By Devs - For Devs

Built with a singular focus - provide state-of-the-art developers with unprecedented productivity and efficiency when building modern natural language applications.

Java-First

REST API and Java-based implementation natively supports the world's largest ecosystem of development tools, multiple programming languages, frameworks and services.

Out-Of-The-Box Integration

NLPCraft natively integrates with 3rd party libraries for base NLP processing and named entity recognition:

Learn more >

How It Works

When using NLPCraft you will be dealing with three main components:

Data model specifies how to interpret user input, how to query a data source, and how to format the result back. Developers use model-as-a-code approach to build models using any JVM language like Java, Scala, Groovy or Kotlin.

Data probe is a DMZ-deployed application designed to securely deploy and manage data models. Each probe can manage multiple models, and you can have many probes.

REST server provides REST endpoint for user applications to securely query data sources using NLI via data models deployed in data probes.

Learn more >

Example

As a quick example let's consider a very simple implementation for NLI-powered light switch. Our app should understand something like Turn the lights off in the entire house or Switch on the illumination in the master bedroom closet. You can easily modify intent callbacks in the model implementation below to perform the actual light switching using HomeKit or Arduino-based controllers.

Add NLPCraft

Add NLPCraft dependency to your project:

<dependencies>
    <dependency>
        <groupId>org.apache.nlpcraft</groupId>
        <artifactId>nlpcraft</artifactId>
        <version>0.9.0</version>
    </dependency>
</dependencies>

NOTE: 0.9.0 should be the latest NLPCraft version.

Define Data Model

Declare the static part of the data model using YAML which we will later load in our model implementation. You can declare entire model in the code - but doing it with JSON or YAML is usually more productive:

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|let|set|get|put}"
 - name: "<KILL>"
   macro: "{shut|kill|stop|eliminate}"
 - name: "<ENTIRE_OPT>"
   macro: "{entire|full|whole|total|_}"
 - name: "<FLOOR_OPT>"
   macro: "{upstairs|downstairs|{1st|2nd|3rd|4th|5th|top|ground} floor|_}"
 - name: "<TYPE>"
   macro: "{room|closet|attic|loft|{store|storage} {room|_}}"
 - name: "<LIGHT>"
   macro: "{all|_} {it|them|light|illumination|lamp|lamplight}"
enabledBuiltInTokens: [] # This example doesn't use any built-in tokens.

#
# Allows for multi-word synonyms in this entire model
# to be sparse and permutate them for better detection.
# These two properties generally enable a free-form
# natural language comprehension.
#
permutateSynonyms: true
sparse: true

elements:
 - id: "ls:loc"
   description: "Location of lights."
   synonyms:
    - "<ENTIRE_OPT> <FLOOR_OPT> {kitchen|library|closet|garage|office|playroom|{dinning|laundry|play} <TYPE>}"
    - "<ENTIRE_OPT> <FLOOR_OPT> {master|kid|children|child|guest|_} {bedroom|bathroom|washroom|storage} {<TYPE>|_}"
    - "<ENTIRE_OPT> {house|home|building|{1st|first} floor|{2nd|second} floor}"

 - id: "ls:on"
   groups:
    - "act"
   description: "Light switch ON action."
   synonyms:
    - "<ACTION> {on|up|_} <LIGHT> {on|up|_}"
    - "<LIGHT> {on|up}"

 - id: "ls:off"
   groups:
    - "act"
   description: "Light switch OFF action."
   synonyms:
    - "<ACTION> <LIGHT> {off|out}"
    - "{<ACTION>|<KILL>} {off|out} <LIGHT>"
    - "<KILL> <LIGHT>"
    - "<LIGHT> <KILL>"
    - "no <LIGHT>"

intents:
 - "intent=ls term(act)={has(tok_groups(), 'act')} term(loc)={tok_id() == 'ls:loc'}*"

Model Implementation

Once we have model declaration we can provide implementation for intent callbacks. We'll use Scala to implement the data model, but you can use any JVM-based language like Java, Groovy, or Kotlin:

package org.apache.nlpcraft.examples.lightswitch

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

class LightSwitchScalaModel extends NCModelFileAdapter("lightswitch_model.yaml") {  
    @NCIntentRef("ls")
    @NCIntentSample(Array(
        "Turn the lights off in the entire house.",
        "Turn off all lights now",
        "Switch on the illumination in the master bedroom closet.",
        "Get the lights on.",
        "Lights up in the kitchen.",
        "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.",
        "Light up the garage, please!",
        "Kill the illumination now!"
    ))
    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(_.getOriginalText).mkString(", ")

        // Add HomeKit, Arduino or other integration here.

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

NOTES:

  • We are loading our static model declaration that we've defined above using NCModelFileAdapter base class.
  • Annotation @NCIntentRef references the intent defined in our YAML model definition.
  • We use @NCIntentSample to provide sample sentences that should satisfy this intent. These samples are used for model auto-testing and synonyms analysis.

Done! 👌

Learn more about this example >

Copyright

Copyright (C) 2021 Apache Software Foundation