Overview

Skill Level: Intermediate

Node.js, Watson, botframework, microsoft

This recipe will allow you to deploy a bot powered by advanced cognitive capabilities powered by Watson on your IBM Bluemix environment and make it accessible from Skype, Cortana or even Microsoft Office 365 email in less than 10 minutes.

Ingredients

  • Bluemix Account - Sign up for a trial account if you don't already have one.
  • Bluemix Command Line
  • Microsoft Bot Framework Account. Go here to sign up
  • Watson Conversation Instance.
  • Latest Node.js with NPM. Download it from here.
  • [Optional except for Step 3] The Bot Framework Emulator. To install the Bot Framework Emulator, download it from here.


You can also check my Github repository for more info.

Step-by-step

  1. Download BotBuilder SDK For Node.js

    • First thing to do is to create a folder for your app in your folder directory. 
    • Create a file named app.js
    • Copy that content in this file

    /*—————————————————————————–
    A simple echo bot for the Microsoft Bot Framework.
    —————————————————————————–*/

    var restify = require(‘restify’);
    var builder = require(‘botbuilder’);

    require(‘dotenv’).config({silent: true});

    // Setup Restify Server
    var server = restify.createServer();
    server.listen(process.env.port || process.env.PORT || 3978, function () {
    console.log(‘%s listening to %s’, server.name, server.url);
    });

    // Create chat connector for communicating with the Bot Framework Service
    var connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD
    });

    // Listen for messages from users
    server.post(‘/api/messages’, connector.listen());

    // Create your bot with a function to receive messages from the user
    var bot = new builder.UniversalBot(connector, function (session) {
    session.send(“You said: %s”, session.message.text);
    });

    • Create a file named package.json
    • Copy that content in this file

    {
    “name”: “mybot”,
    “version”: “1.0.0”,
    “main”: “app.js”,
    “scripts”: {
    “start”: “node app.js”
    },
    “author”: “Vincent Perrin”,
    “license”: “ISC”,
    “description”: “”,
    “dependencies”: {
    “botbuilder”: “^3.8.4”,
    “dotenv”: “^2.0.0”,
    “restify”: “^5.0.1”,
    “watson-developer-cloud”: “^2.31.1”
    }
    }

    • Create a .env file (nothing before .)
    • Copy that content in this file

    # Environment variables
    WORKSPACE_ID=
    CONVERSATION_USERNAME=
    CONVERSATION_PASSWORD=

    #Microsoft Bot Info
    MICROSOFT_APP_ID=”
    MICROSOFT_APP_PASSWORD=”

     

    You have now the skeleton of your app.

  2. Start your Bot

    First of all, you have to install all dependencies. type npm install in the folder of your bot.

    Then, you can start with npm start

  3. Install BotFramework emulator for local testing

    Please refer to this documentation article to know more about the Bot Framework Emulator.

    framework

    At this stage, you don’t need to provide Microsoft App Id and App Password.

  4. Add Watson Conversation SDK in your bot

    • Open app.js file
    • Update your file with this content. Content in Bold

    var restify = require(‘restify’);
    var builder = require(‘botbuilder’);
    var Conversation = require(‘watson-developer-cloud/conversation/v1’); // watson sdk

    require(‘dotenv’).config({silent: true});

    var contexts;
    var workspace=process.env.WORKSPACE_ID || ”;

    // Setup Restify Server
    var server = restify.createServer();
    server.listen(process.env.port || process.env.PORT || 3978, function () {
    console.log(‘%s listening to %s’, server.name, server.url);
    });

    // Create the service wrapper
    var conversation = new Conversation({
    // If unspecified here, the CONVERSATION_USERNAME and CONVERSATION_PASSWORD env properties will be checked
    // After that, the SDK will fall back to the bluemix-provided VCAP_SERVICES environment property
    // username: ‘<username>’,
    // password: ‘<password>’,
    url: ‘https://gateway.watsonplatform.net/conversation/api’,
    version_date: Conversation.VERSION_DATE_2017_04_21
    });

    // Create chat connector for communicating with the Bot Framework Service
    var connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD
    });

    // Listen for messages from users
    server.post(‘/api/messages’, connector.listen());

    // Receive messages from the user and respond by echoing each message back (prefixed with ‘You said:’)
    var bot = new builder.UniversalBot(connector, function (session) {

    var payload = {
    workspace_id: workspace,
    context:”,
    input: { text: session.message.text}
    };

    var conversationContext = findOrCreateContext(session.message.address.conversation.id);
    if (!conversationContext) conversationContext = {};
    payload.context = conversationContext.watsonContext;

    conversation.message(payload, function(err, response) {
    if (err) {
    session.send(err);
    } else {
    console.log(JSON.stringify(response, null, 2));
    session.send(response.output.text);
    conversationContext.watsonContext = response.context;
    }
    });

    });

    function findOrCreateContext (convId){
    // Let’s see if we already have a session for the user convId
    if (!contexts)
    contexts = [];

    if (!contexts[convId]) {
    // No session found for user convId, let’s create a new one
    //with Michelin concervsation workspace by default
    contexts[convId] = {workspaceId: workspace, watsonContext: {}};
    //console.log (“new session : ” + convId);
    }
    return contexts[convId];
    }

    • Update your .env file with your Watson Conversation infos
    • Redo Step 3 to test your conversation.
  5. Deployment on IBM Bluemix

    • Create a manifest.yml file with that content

    applications:
    – path: .
    memory: 256M
    instances: 1
    domain: mybluemix.net
    name: [name of your app]
    host: [hostname]
    disk_quota: 1024M

    • Use Bluemix command line as described here in chapter 4
  6. Register your bot on BotFramework

    Register your bot with the Microsoft Bot Framework. Please refer to this for the instructions. 

    Screen-Shot-2017-07-26-at-17.34.41

    • Create your keys

     

    Screen-Shot-2017-07-26-at-17.39.34

    • Fill in Messaging Endpoint with an url (according your Bluemix app parameter) like https://[hostname].mybluemix.net/api/messages
    • Update your bot configuration with the registered configuration values in .env file
    • Use the test service in the Bot Framework web page

     

    test

  7. Test Skype and enable additional channels

    If you have Skype on your laptop, click on Skype, it will invite the bot in your Skype client.

    channels

     A conversation powered by Watson via Skype

    skype

    Skype can be very useful for a B2C chatbot using advanced Watson capabilities like Tone Analyzer to add emotion detection so your chatbot can mimic and appropriately respond to the end user’s sentiment and Discovery to query unstructured data.

    Watson Discovery is very useful to handle “long-tail” questions. 

3 comments on"How to build a chatbot with Watson Conversation using Microsoft BotFramework"

  1. Harshal Wank July 14, 2018

    Hi Vincent,
    I am trying to run my WATSON chatbot using skype.
    I have followed all the above instructions as mentioned by you, but still I am stuck,
    when I am testing the bot from bot framework emulator locally :
    I get response as
    “you said HI”,
    so the connections are established but my watson bot is not connected, else in response of HI would have got “regards”
    in reply,
    end point url for framework emulator is :

    here is the content of files:
    app.js
    /*—————————————————————————–
    A simple echo bot for the Microsoft Bot Framework.
    —————————————————————————–*/

    var restify = require(‘restify’);
    var builder = require(‘botbuilder’);
    var Conversation = require(‘watson-developer-cloud/conversation/v1’); // watson sdk
    require(‘dotenv’).config({silent: true});
    var contexts;
    var workspace=process.env.WORKSPACE_ID || ‘https://gateway.watsonplatform.net/assistant/api/v1/workspaces/91ccb060-0a21-411b-9ce6-c632d7fc9eb0/message/’;

    // Setup Restify Server
    var server = restify.createServer();
    server.listen(process.env.port || process.env.PORT || 3978, function () {
    console.log(‘%s listening to %s’, server.name, server.url);
    });

    // Create the service wrapper
    var conversation = new Conversation({
    // If unspecified here, the CONVERSATION_USERNAME and CONVERSATION_PASSWORD env properties will be checked
    // After that, the SDK will fall back to the bluemix-provided VCAP_SERVICES environment property
    // username: ‘fca4123f-0a48-49ff-afdd-708ce3e4a078’,
    //password: ”,
    url: ‘https://gateway.watsonplatform.net/conversation/api’,
    version_date: Conversation.VERSION_DATE_2017_04_21
    });

    // Create chat connector for communicating with the Bot Framework Service
    var connector = new builder.ChatConnector({
    appId: process.env.MICROSOFT_APP_ID,
    appPassword: process.env.MICROSOFT_APP_PASSWORD
    });

    // Receive messages from the user and respond by echoing each message back (prefixed with ‘You said:’)
    var bot = new builder.UniversalBot(connector, function (session) {

    var payload = {
    workspace_id: workspace,
    context:”,
    input: { text: session.message.text}
    };

    var conversationContext = findOrCreateContext(session.message.address.conversation.id);
    if (!conversationContext) conversationContext = {};
    payload.context = conversationContext.watsonContext;

    conversation.message(payload, function(err, response) {
    if (err) {
    session.send(err);
    } else {
    console.log(JSON.stringify(response, null, 2));
    session.send(response.output.text);
    conversationContext.watsonContext = response.context;
    }
    });

    });

    function findOrCreateContext (convId){
    // Let’s see if we already have a session for the user convId
    if (!contexts)
    contexts = [];

    if (!contexts[convId]) {
    // No session found for user convId, let’s create a new one
    //with Michelin concervsation workspace by default
    contexts[convId] = {workspaceId: workspace, watsonContext: {}};
    //console.log (“new session : ” + convId);
    }
    return contexts[convId];
    }

    // Listen for messages from users
    server.post(‘/api/messages’, connector.listen());

    // Create your bot with a function to receive messages from the user
    var bot = new builder.UniversalBot(connector, function (session) {
    session.send(“You said: %s”, session.message.text);
    });
    ——————————–
    mainfest.yml:
    applications:
    – path: .
    memory: 256M
    instances: 1
    domain: mybluemix.net
    name: watdox
    host: watdox
    disk_quota: 1024M
    ——————————————–
    .env file:

    # Environment variables
    WORKSPACE_ID=91ccb060-0a21-411b-9ce6-c632d7fc9eb0
    CONVERSATION_USERNAME=fca4123f-0a48-49ff-afdd-708ce3e4a078
    CONVERSATION_PASSWORD=v4rKRhHoFSOe

    #Microsoft Bot Info
    MICROSOFT_APP_ID=643b5fd0-efc6-4c62-b8df-f87f40de5edd
    MICROSOFT_APP_PASSWORD=kdOCQWM6444-+mzxtnLI7*:
    ———————————————————–

  2. Hi Vincent

    I have followed the step and was successful till step 6.
    After the end of the step 6 I tested the bot from the test service provide in the Bot Framework and it didn’t work.

    Interestingly it works when I try it from the Botframework emulator connecting to the Chatbot hosted remotely using “ngrok”

    Please can you guide me in debugging the issue.

Join The Discussion