Skip to Content

Build a Webhook for a Chatbot using Python

test
0 %
Build a Webhook for a Chatbot using Python
Details

Build a Webhook for a Chatbot using Python

July 15, 2020
Created by
June 29, 2020
Create a Python script (with Flask), deploy it to SAP Cloud Platform, and use it as a webhook to be called by an SAP Conversational AI chatbot.

You will learn

  • How to create a Python endpoint in SAP Cloud Platform, using Flask
  • How to read POST data from a chatbot
  • How to send back data to a chatbot
  • How to deploy a Python script to SAP Cloud Platform (using Cloud Foundry CLI)
  • How to connect the webhook to the chatbot

Prerequisites

You will create a very simple chatbot that asks the user to pick an animal, and then have the chatbot call a webhook, which will then call an API to retrieve a “fun fact” about the animal via the cat-facts API. The webhook will also update the memory variable that keeps track of how many times the user requested a fun fact.

The point of the tutorial is to show you how the webhook reads the request data from the chatbot, and to show you the format of the data that must be returned to the chatbot.

As an added bonus, we will show how to deploy a Python script to SAP Cloud Platform. Special thanks to Yohei Fukuhara for his blog Create simple Flask REST API using Cloud Foundry.


Step 1: Create a simple chatbot

Create a bot that asks the user to select an animal to get a fun fact about.

  1. Create a new bot and call it webhookdemo. Use the following values:

    Field Name Value
    1. What do you want your chatbot to do? Perform Actions
    2. Predefined Skills None
    3. Create your bot
    • Name: webhookdemo
    • Description: A bot to test creation of webhooks
    • Language: English
    4. Data Policy Non-personal and Non-vulnerable
    5. Bot Visibility Public

    Click Create Bot.

  2. In the Train tab, create an intent called ask, and add the expression I’m interested in.

    Since you define only one intent, this intent will always be triggered when the user types in a message.

  3. In the Train tab, create a restricted entity called animal and add 4 valid values: cat, horse, snail, dog.

    Restricted entity
  4. In the Build tab, create a skill called answer, and open it.

    Under Triggers, set the condition to: If @ask is-present.

    Under Requirements, specify #animal as animal.

    Expand the requirement and click New Replies – If #animal is missing, add the following text message, and then click Save and Back:

    Type an animal and I will get you a fun fact about it.
    
    But I am only familiar with certain animals.
    
Log on to answer question
Step 2: Test the bot without webhook
  1. First, open the Test tab and test the bot. No matter what you type the intent will be ask.

    Enter dog and it will recognize the animal entity, too.

    Animal
  2. Now open Chat With Your Bot.

    If you enter anything that does not match the animals, a short message is displayed and it asks you to enter an animal.

    Enter one of the animals. Now the requirement is met but you did not define a reply so the default No reply is sent.

    Skill test
Log on to answer question
Step 3: Create Python project
  1. In the file explorer, create a new folder for the project and call it chatbot-webhook.

  2. Open VS Code.

    Make sure you have installed the Microsoft extension for Python, as well as Python and the Flask and requests packages.

  3. Go to File > Add Folder to Workspace, and select the project folder.

    New file
  4. Inside the folder, create the helper files for the project

    manifest.yml

    applications:
    - memory: 128MB
      disk_quota: 256MB
      random-route: true
    

    Procfile

    web: python chatbot-webhook.py
    

    requirements.txt

    This file contains dependencies in our project: Flask to create endpoints and requests to call other APIs from within our app.

    Flask
    requests
    

    runtime.txt

    The first time I tried this I was using version 3.6.6, but that did not work for me, and somehow figured out that this version worked.

    python-3.8.1
    

    You need to verify what Python versions are supported by SAP CLoud Platform. At the time of the writing of this tutorial, 3.8.1 was supported.

    static (folder)

    Create the folder static. Download the SAP Conversational AI icon and place it in the folder.

Your project should look like this:

VS Code setup
Log on to answer question
Step 4: Write Python endpoints

Now we will write the main part of the app, which creates the endpoints.

  1. In your project, create a new file called chatbot-webhook.py.

  2. Add the following code – which adds dependencies and creates a default endpoint, which returns a nice HTML page with a cool image, so you will be able to make sure the deployment was successful.

    from flask import Flask, request, jsonify
    import os
    import json
    import datetime
    import requests
    
    app = Flask(__name__)
    cf_port = os.getenv("PORT")
    
    # Only get method by default
    @app.route('/')
    def hello():
        return '<h1>SAP Conversational AI</h1><body>The animal facts webhook for use in SAP Conversational AI chatbots.<br><img src="static/283370-pictogram-purple.svg" width=260px></body>'
    
    if __name__ == '__main__':
    	if cf_port is None:
    		app.run(host='0.0.0.0', port=5000, debug=True)
    	else:
    		app.run(host='0.0.0.0', port=int(cf_port), debug=True)
    
    

    Save the file.

    If you want, you can test this in VS Code by running the .py file – either by right-clicking the file and choosing Run Python File in Terminal or clicking the green arrow Link text e.g., Destination screen in the upper right. You will get the following:

    VS Code test default endpoint

    You can then open a browser to the default endpoint.

    VS Code test default endpoint
  3. Add the following code for the main endpoint right after the default one – and before the if __name__ == '__main__': line.

    This endpoint takes the data from the chatbot, makes the call to the API to get the fun fact, and then returns the next message to the chatbot.

    @app.route('/bot', methods=['POST'])
    def bot():
      # Get the request body, and determine the dog and memory
      try:
        bot_data = json.loads(request.get_data())
        animal = bot_data['conversation']['memory']['animal']['raw']
        memory = bot_data['conversation']['memory']
      except:
        animal = "dog"
        memory = json.loads("{}")
    
      # Get the fun fact
      url = "https://cat-fact.herokuapp.com/facts/random?animal_type=" + animal + "&amount=1"
      r = requests.get(url)
      fact_data = json.loads(r.content)
    
      # Increment the # of times this has been called
      if 'funfacts' in memory:
         memory['funfacts'] += 1
      else:
         memory['funfacts'] = 1
    
      # Return message to display (replies) and update memory
      return jsonify(
        status=200,
        replies=[
        {
          'type': 'text',
          'content': fact_data['text']
        }
        ],
        conversation={
          'memory': memory
        }
    
      )
    

    Save the file.

    You can test this by opening Postman, and calling the endpoint localhost:5000/bot (with POST method and no body).

    VS Code test bot endpoint

    Test it again but this time sending the following (raw) body, to simulate as if the chatbot were sending the request:

    {
      "conversation": {
        "memory": {
          "animal" : {"raw" : "snail"},
          "funfacts": 1
        }
      }
    }
    

    Now, the API call uses the animal from the body (i.e., snail) and updates the funfacts variable in the memory.

    VS Code test bot endpoint
Log on to answer question
Step 5: Push Python script to SAP Cloud Platform

Use the Cloud Foundry CLI to deploy the script to SAP Cloud Platform.

You will need your SAP Cloud Platform Cloud Foundry endpoint and org name, which you can see when you open your subaccount Overview page.

Account info
  1. Open a command prompt in the folder containing your Python project, and set the Cloud Foundry API URL.

    cf api https://api.cf.eu10.hana.ondemand.com
    
    CLI
  2. Log in by entering the following command and entering your credentials:

    cf login
    
  3. Select your CF org.

    CLI org
  4. Now push the application, and call it catfacts:

    cf push catfacts
    

You should now have the application deployed. Go to your Cloud Foundry space, under Applications.

Link text e.g., Destination screen

If you click the app, you will get the endpoint link.

Link text e.g., Destination screen

And if you click the link (and open it in browser), you will be making a GET call to the default endpoint.

Test endpoint
Log on to answer question
Step 6: Point chatbot to webhook

Now that you deployed your webhook, let’s attach it to the chatbot.

  1. In the Build tab, open the answer skill.

  2. In the Actions tab, click Add New Message Group, and then click Connect External Service > Call Webhook.

    • For the URL, enter the name of your endpoint with /bot at the end. Make sure the method is POST.

      For example, mine is: https://catfacts-quiet-klipspringer-kx.cfapps.eu10.hana.ondemand.com/bot

    • Click Save.

  3. Click Update Conversation > Edit Memory, and then set the Unset memory field to animal.

    Add webhook
  4. Click Add New Message Group.

    This message group is to display a message when the user has requested 3 or more fun facts. Our webhook is keeping track of the number of calls, and then passing the results via the memory.

    • Set the condition to If _memory.funfacts is 3.

    • Add a text message that says: WOW!! You sure like these fun facts!!

Log on to answer question
Step 7: Test chatbot

Open a conversation with the bot, by entering Hi. The message when an animal is missing is displayed.

No animal

Then enter an animal, and the webhook is triggered and a fun fact is displayed.

Animal

Enter an animal 2 more times – must be cat, dog, snail, or horse. The extra message is displayed for when the user repeatedly asks for fun facts.

Lots of animals

Click on the yellow i icon to see the JSON of the conversation. Scroll down and you can see that the webhook added to the memory the value for funfacts.

Memory

You demonstrated the way to return information to the memory from the webhook, so you kept track via a custom memory variable _memory.funfacts of how many times the current user requested a fun fact.

You could have instead used the built-in variable _skill_occurences to keep track of how many times you executed the answer skill.

For information on built-in variables, see Runtime Data Accessible.

Log on to answer question
Step 8: Test yourself
What is the name of the field you created in the chatbot memory to keep track of how many times the user called the webhook?
×

Next Steps

Back to top