/recastbot

Semantic Interface for natural language processing via Recast.AI

Primary LanguageJavaScriptMIT LicenseMIT

recastbot

Recast.AI API:v1 Code-Style:Standard License:MIT

recastbot helps you build applications that understand natural language using Recast.AI's Natural Language Processing & Understanding API.

Features

Semantic Interface

Handle intents using expressive words such as hears, fails, any, and otherwise to make your code meaningful and readable.

Platform-agnostic

You can integrate recastbot anywhere. It does not make any assumptions about frameworks or platforms.

Use cases

recastbot is useful for building conversational interfaces. Some examples include chatbots (e.g. Slack, Twitter bots, HipChat bots), virtual assistants, cross-platform conversational interfaces, and many more.

Quick Example: a WeatherBot

import RecastBot from 'recastbot'
const ai = new RecastBot(API_TOKEN)

ai.process(textToProcess, userData, respondFn)
  .hears('weather', (res, userData, respondFn) => {
    if (res.sentences[0] && res.sentences[0].entities) {
      let entities = res.sentences[0].entities

      // defaults...
      let location = userData.location
      let datetime = userData.localDatetime

      // get entity objects from Recast.AI
      if (entities.location) location = entities.location[0]
      if (entities.datetime) datetime = entities.datetime[0]

      // get weather status as {string}
      let weather = getWeather([location.lat, location.lng], datetime.value)

      // send response to user
      respondFn('The weather in ' + location.raw + ' ' +
        datetime.raw + ' is ' + weather)
    } else {
      // ask user for time and place
      respondFn('Hi, ' + userData.firstName + '! Weather? where?')
    }
  })
  .hears('greetings', (res, userData, respondFn) => {
    respondFn('Hello, ' + userData.firstName + '!')
  })
  .otherwise((res, userData, respondFn) => {
    respondFn('Sorry, I didn\'t get that... ')
  })
  .fails((err) => {
    respondFn('Sorry, there was an error. Try again later.')
    console.error(err.message)
  })

Input: "How is the weather in San Juan today?"

Output: "The weather in San Juan is cloudy, 77ºC, 79% humidity"

Requirements

To use recastbot you need to sign up to Recast.AI and create a Recast.AI app. This allows you to make API requests from your application/bot.

This documentation assumes that you know how Recast.AI works. See the Recast.AI docs for more information.

Installation

Installing recastbot is as simple as installing any other npm module:

$ npm install recastbot --save

Usage

Initialization

First, you need to initialize a new RecastBot instance with your API_TOKEN and store it somewhere (ai is a good name for it, but you can call it whatever you want):

// ES6+
import RecastBot from 'recastbot'
const ai = new RecastBot(API_TOKEN)
// or, in ES5
var RecastBot = require('recastbot')
var ai = new RecastBot(APITOKEN)

Process a string

When you have your RecastBot instance ready, you can process a string using the .process() method. This method should be called for each string you process.

.process() returns an object with several methods that allow you to register handlers for each intent, catch API errors, handle any event at once, and catch unhandled intents.

The first parameter is the string to be processed and the remaining arguments will be passed to the handlers you register for each intent.

import RecastBot from 'recastbot'
const ai = new RecastBot(API_TOKEN)
// ...
let bot = ai.process(text, optArgument1, ...optArgumentN)

Register intent handlers

bot.hears(intentName, handlerFn)

Use the .hears() method to register an intent handler. The first argument is the name of the intent and the second argument is the handler (a callback function). The handler function is called when the specified intent is matched.

One or more arguments are passed to the callback function: the first one is always the results from Recast.AI and the rest (if any) are the ones passed through .process()

Real-world Example:

// ...
let bot = ai.process('Hi, RecastBot!', userData, respondFn)

bot.hears('greetings', (results, userData, respondFn) => {
  // handler function for 'greetings' intent
  respondFn('Hello, ' + userData.firstName + '!')
})

In the example above, we passed three arguments to .process(), the first one is used by the Recast.AI API and the last two are used in the handler function passed to .hears():

  1. 'Hi, RecastBot!' {string} [required]: The text to be processed
  2. userData {object} [arbitrary; optional]: The user's data (used in the handler function)
  3. respondFn {function} [arbitrary; optional]: The function that will be used to respond back to the user (also used in the handler function)

Catch unhandled intents

bot.otherwise(handlerFn)

When the intent does not match any handlers, the .otherwise() method is called. The .otherwise() method works the same way as .hears() but with a small difference: it takes only a handler (callback function). The handler function is called when no handler function was provided for that intent or when no intents were registered.

Real-world Example:

// ...
let bot = ai.process('Open the pod bay doors.', userData, respondFn)

bot.hears('greetings', (response, userData, respondFn) => {
  respondFn('Hello, ' + userData.firstName + '!')
})

bot.otherwise((response, userData, respondFn) => {
  respondFn('I\'m sorry, ' + userData.firstname + ' I don\'t understand.')
})

Catching errors

bot.fails(errorHandlerFn)

When an error with the Recast.AI API occurs, the method .fails() is called. The .fails() method takes a callback function as an argument. When an error occurs, it calls your defined callback function. It passes a new Error() object along with the additional methods passed through .process().

Example:

ai.process('Hi', userData, respondFn)
  .hears('greeting', greetingFn)
  .otherwise(otherwiseFn)
  .fails((err, userData, respondFn) => {
    console.error(err.message)
    respondFn('There is a problem with my brain. Please try again later.')
  })

Chaining

You can chain multiple methods to make your code look simpler and meaningful. This is useful because it allows you visualize how data flows through different handler functions.

ai.process('Hi, RecastBot!', userData, respondFn)
  .hears('greetings', (response, userData, respondFn) => {
    respondFn('Hello, ' + userData.firstName + '!')
  })
  .otherwise((response, userData, respondFn) => {
    respondFn('Sorry,' + userData.firstname + ' I do not understand')
  })
  .fails((err, userData, respondFn) => {
    console.error(err.message)
    respondFn('There is a problem with my brain. Please try again later.')
  })

For the lazy

Register handlers in bulk

If you prefer an alternate way for registering handler functions for your intents in bulk, you can use the .setHandlers() method. This method takes an object containing the handler functions and registers each of them for you. Make sure your object's properties match your app's intent names.

const myHandlers = {
  'greetings': (response, userData, respondFn) => {
    respondFn('Hello, ' + userData.firstName + '!')
  },
  'get status': (response, userData, respondFn) => {
    respondFn('I\'m feeling great :)')
  }
}

ai.process('How are you?', userData, respondFn)
  .setHandlers(myHandlers)
  .fails((err, userData, respondFn) => {
    respondFn('There is a problem with my brain. Please try again later.')
    console.error(err.message)
  })

Contributing

Bug Reports & Feature Requests

Something does not work as expected or perhaps you think this module needs a feature? Please open an issue using GitHub's issue tracker.

Developing

Pull Requests (PRs) are welcome. Make sure you follow the same basic stylistic conventions as the original code (i.e. "JavaScript standard code style")

License

The MIT License (MIT)

Copyright (c) 2016 Kristian Muñiz

Acknowledgements

Inspired by Mike Brevoort's witbot: an adaptation of Wit – a NLP service similar to Recast.AI

I am not affiliated in any way to Recast.AI and this is not an official library.