@kognitalabs/shallot-framework
TypeScript icon, indicating that this package has built-in type declarations

1.0.1 • Public • Published

🧅 Shallot Framework (Kognita Lab)

Small mild-flavored onion - or code - clustered bulbs used for seasoning your chatbot.

Requirements

The Shallot Framework was made to have a perfect integration with a few services, making them required, are them:

  • Microsoft Language Understanding (LUIS) - A machine learning-based service to build natural language into apps, bots, and IoT devices. Quickly create enterprise-ready, custom models that continuously improve. - Paid Account Required

  • Sunshine: Omnichannel messaging platform - Sunshine Conversations connects your business software to all the world’s messaging channels for a more human customer experience. - Paid Account Required

  • MySQL Database - MySQL is a relational database management system based on SQL – Structured Query Language.

  • RabbitMQ Message Broker - With tens of thousands of users, RabbitMQ is one of the most popular open source message brokers. From T-Mobile to Runtastic, RabbitMQ is used worldwide at small startups and large enterprises.

If your stack already meet the requirements. You can skip to the next step of the README.

What is Shallot? / Why use Shallot?

The Shallot Framework is a framework that facilitates the development of chatbots.

With a simple language, it allows chatbot actions to be as action-oriented writing. You basically describe what the dialog will do.

Let's assume we have the welcome dialog. Just use set dialog.name and at the first parameter we use 'welcome', after that in the second parameter we use a callback which will receive the actions to take for the dialog specified.

  event.dialog.name('welcome', async (dialog) => {

Inside the callback just specify as example: For the HumanHelp intent forIntent change the dialog to human_help changeDialogTo and send the predicted intent response sendPredictedIntentAnswer.

  await dialog.forIntent('HumanHelp')
    .changeDialogTo('human_help')
    .sendPredictedIntentAnswer();

When putting it all together the result would be the following:

event.dialog.name('welcome', async (dialog) => {
  await dialog.forIntent('HumanHelp')
    .changeDialogTo('human_help')
    .sendPredictedIntentAnswer();
})

Installation

Install Shallot Framework with yarn:

  yarn add @kognitalabs/shallot-framework

Usage/Examples

Do you know how to create a chatbot? It's very easy, follow the steps below:

import { ShallotFramework as framework } from '@kognitalabs/shallot-framework';

framework.instance(async (shallot) => {
  /**
   * CONNECT REQUIRED SERVICES
   */
  await shallot.connectDatabase({
    host: process.env.MYSQL_HOST,
    port: process.env.MYSQL_PORT,
    username: process.env.MYSQL_USERNAME,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE,
    synchronize: true // When executing for the first time, set as true for database tables sync.
  });

  await shallot.connectLUIS({
    applicationId: process.env.LUIS_BOT_ID,
    endpoint: process.env.LUIS_ENDPOINT,
    endpointKey: process.env.LUIS_PREDICTION_KEY,
    name: process.env.LUIS_BOT_NAME
  });

  await shallot.connectSunshine({
    appId: process.env.SMOOCH_APP_ID,
    keyId: process.env.SMOOCH_API_KEY_ID,
    keySecret: process.env.SMOOCH_API_KEY_SECRET
  });

  await shallot.connectAMQP(process.env.AMQP_URL);

  /**
   * CONTROL YOUR BOT ACTIONS
   */

  /**
   * When the Sunshine event was conversation:message on RabbitMQ queue named conversation execute this callback(err, event) => Promise<AMQP.EventManager>
   */
  void shallot.when(
    'conversation:message', 'conversation', async (err, event) => {
      if (err !== undefined) {
        return event;
      }

      /**
       * If the conversation dialog in the received event is named 'welcome' returns a callback(dialog).
       */
      void event.dialog.name('welcome', async (dialog) => {
        await dialog.forNotListedOnes()
          .changeDialogTo('default')
          .sendIntentReplaceableAnswer('Greeting', {
            displayName: () => {
              const nameCompose = [];
              nameCompose.push(dialog.props.customer.props.givenName);
              nameCompose.push(dialog.props.customer.props.surname);

              return nameCompose.join(' ');
            }
          });
      });

      /**
       * If the conversation dialog in the received event is named 'default' returns a callback(dialog).
       */
      void event.dialog.name('default', async (dialog) => {
        await dialog.forIntent('HumanHelp')
          .changeDialogTo('human_help')
          .sendPredictedIntentAnswer();

        await dialog.forIntent('HowTo')
          .sendIntentAnswer('PostGreeting');

        await dialog.forIntent('Greeting')
          .sendHandWritedAnswer('Como posso ajudar?');

        await dialog.forIntent('None')
          .changeDialogTo('confusing')
          .sendPredictedIntentAnswer();

        await dialog.forNotListedOnes()
          .sendPredictedIntentAnswer();
      });

      /**
       * If the conversation dialog in the received event is named 'chating_with_human' returns a callback(dialog).
       */
      void event.dialog.name('chating_with_human', async (dialog) => {
        // Since this is an human help case, skip bot interference.
        dialog.skip();
      });

      void event.dialog.noneOf(['chating_with_human', 'default', 'welcome'], async (dialog) => {
        await dialog.forIntent('HowTo')
          .sendIntentAnswer('PostGreeting');

        await dialog.forNotListedOnes()
          .changeDialogTo('default')
          .sendPredictedIntentAnswer();
      });

      /**
       * Required function at the end, always run execute()
       */
      event.dialog.execute();
      return event;
    }
  );
});

Classes & Functions

(class): ShallotFramework

This class is a singleton and an instance can be received when you call for the method instance(callback) as you can see here:

ShallotFramework.instance(async (shallot) => {
  ...
  // The shallot receveid value is the singleton instance itself.
});

(method): ShallotFramework.when(event: EventType, queue: string, callback: CallbackFunction<AMQP.EventManager>): Promise< void >

This is one of the main methods of Shallot. It is the first line of the three-level callback structure. It is responsible to filter the event type, set a queue to list to and return the all formated Smooch Event into a Callback. So to make it work, use it!

You can define multiple events to the same queue.

@param event — The Event type as 'conversation:message'.

@param queue — The RabbitMQ queue to attach to.

@param callback — The magic portal to process the action! The callback return two values, are them Error and EventManager.

e.g: usage and return:

...
void shallot.when(
    'conversation:message', 'conversation', async (err, event) => {
      if (err !== undefined) {
        return event;
      }

      void event.dialog.name('welcome', async (dialog) => {
        ...

(class): EventManager

This class is the non-error return value of the ShallotFramework.when method.

Test Coverage

Currently our tests cover 51.06% percent of the lines in all files:

File % Stmts % Branch % Funcs % Lines Uncovered Line #s
All files 42.42 33.9 39.82 51.06
src 80 73.91 60 86.66
envvars.ts 100 85.71 100 100 3
index.ts 73.33 68.75 50 80 6-7
src/core 31.42 17.84 28.12 37.18
framework.module.ts 21.96 16.74 14.81 26.19 ...162,167-175,181-210,216-237,252-286
injection.module.ts 96.77 75 100 96.77 41
src/core/domain 71.26 43.85 64.28 74.69
aggregate-root.abstract.ts 75 55.55 66.66 81.81 5-6,11,33
entity.abstract.ts 55.55 25 50 55.55 7,15-24
identifier.class.ts 64.7 0 60 64.7 11-17,27
mapper.abstract.ts 100 100 50 100
unique-id.abstract.ts 78.26 57.14 75 85.71 5-6,11
src/core/logic 50.25 36.48 51.28 55.97
generic-app.error.ts 70.73 52.08 72.72 78.78 5-6,11,20,39-44
guard.class.ts 39.74 31.66 44.44 42.62 10-16,46,59-81,88-96,104-128
result.class.ts 50 25 42.1 56.92 ...4-35,50-64,71,74,77,84,87,90,96,100
src/infrastructure/amqplib 15.98 16.26 15 18.77
amqp.module.ts 15.98 16.26 15 18.77 ...,94-123,129-133,139-211,223-319,323
src/infrastructure/smooch 29.54 23.23 21.95 40.67
smooch.module.ts 29.54 23.23 21.95 40.67 ...114-126,132-151,182-189,193-195,200
src/infrastructure/typeorm/entities 75.45 55.4 59.61 85.62
answer-action.entity.ts 76.47 53.06 61.53 85.71 5-6,11,20,44,70
answer.entity.ts 77.19 59.18 60 87.23 5-6,11,20,67,77
bot-message.entity.ts 73.58 53.06 53.33 83.72 5-6,11,20,42,83,94
conversation.entity.ts 73.58 53.06 53.33 83.72 5-6,11,20,44,74,85
customer.entity.ts 75.55 57.44 66.66 86.11 5-6,11,20,73
intent.entity.ts 73.8 57.44 66.66 84.84 5-6,11,20,47
standard-column-group.abstract.ts 86.2 58.06 100 95.65 5
user-message.entity.ts 71.92 53.06 47.05 82.6 5-6,11,20,43,86,93,104
src/modules/dialogs 78.57 68.75 75 77.77
index.ts 78.57 68.75 75 77.77 6-7
src/modules/dialogs/cases 50 49.13 55.67 62
create-bot-answer.case.ts 72.02 65.11 91.3 88 5,15,32-33,120,142-144,148,153-155
create-conversation.case.ts 70.18 65.71 87.09 82.09 ...123,161,182-184,197-198,232,240-241
predict-user-message-utterance.case.ts 22.31 19.81 13.04 30.76 5,12-17,21-44,69,77-85,97-121
send-customer-answer.case.ts 18.18 19.13 15 23.59 5,12-17,21-44,67,75-135
src/modules/dialogs/domain 57.14 44.84 52.5 67.76
bot-answer.entity.ts 79.41 56.52 70 84.37 5-6,11,43,73
conversation.aggregate.ts 44.86 40.45 40.81 56.84 ...192,195-197,200-204,209-210,213-214
customer.entity.ts 78.12 52.63 70 83.33 5-6,11,31,39
message.entity.ts 80.55 52.38 72.72 85.29 5-6,11,36,53
src/modules/dialogs/errors 82.53 42.85 68 85.24
dialog.errors.ts 82.53 42.85 68 85.24 5-6,11,38,48,58,78,88,98
src/modules/dialogs/infrastructure 20.17 15.83 16.43 22.89
composite-query.ts 20.17 15.83 16.43 22.89 ...393,396-433,444,447-471,482,485-487
src/modules/dialogs/infrastructure/mappers 57.26 39.65 56 60.69
bot-answer.mapper.ts 55.93 41.81 58.33 58.82 5-6,11,20,40,43-57,62-75
conversation.mapper.ts 57.37 41.81 50 61.53 5-6,11,20,41,44-58,63-70
customer.mapper.ts 58.92 45.09 58.33 62.5 5-6,11,20,38,41-52,56-62
message.mapper.ts 56.89 32.39 58.33 60 5-6,11,20,38,42-59,64-75
src/modules/dialogs/repositories 23.19 17.67 20.54 33.25
answer.repository.ts 19.49 17.51 19.35 28.71 ...29,33-56,60-68,80-82,85-101,107-144
bot-answer.repository.ts 25.89 18.75 24 39.7 5-6,11,20,24-29,33-56,69,72-90
conversation.repository.ts 22.02 15.67 17.64 28.45 ...,75-79,82-91,98-121,127-144,150-176
customer.repository.ts 25.42 18.42 21.42 37.83 5-6,11,20,24-29,33-56,70,73-83,89-103
message.repository.ts 25 18.42 21.42 36.84 5-6,11,20,24-29,33-56,69,72-86,92-101

Authored/Licensed

All rights reserved to:

Contributors

Package Sidebar

Install

npm i @kognitalabs/shallot-framework

Weekly Downloads

0

Version

1.0.1

License

AGPL-3.0-or-later

Unpacked Size

341 kB

Total Files

99

Last publish

Collaborators

  • iagocalazans
  • cyborgbit