Dialogflow Tutorial: Back Functionality in Chatbot using Python + Django

Chatbots, Python Development, Machine Learning, Natural Language Processing (NLP)

Dialogflow is a very powerful tool when it comes to chatbots development. We can create complex conversation flow using Dialogflow. Not only logical-tree-based step-by-step conversation flow but we can also create free flow where user can jump from one point of conversation to another.

However, Dialogflow has its own limitations. It doesn’t provide all the functionalities we require. One such functionality is taking user back to the previous intents.

For example, when we are browing a website, we can easily go back to previous page by clicking on Back button on top of the browser. But in chatbot, user doesn’t have any such option. So, we have to create it on our own. If a user says “Back” then we should take him to one step back and continue the conversation flow from there.

Sounds interesting, right?

We can create such back functionality in Dialogflow based chatbot by managing the contexts and response properly. And to manage contexts and response, we have to use Fulfillment. In this tutorial, we’ll setup fulfillment URL, also known as webhook, using Python + Django. If you are new to creating Dialogflow fulfillment using Python + Django, then refer our previous tutorial.

Solution

To move one step in the backward direction from the current stage we have to store the output of the previous stages while moving forward. And for that we are using output context to preserve conversation flow. We have to save the responses as well as the output contexts of every stage.

[
   [
       [
           "Response Message of stage 1"
       ],
       [
           "Output Context of stage 1"
       ]
   ],
   [
       [
           "Response Message of stage 2"
       ],
       [
           "Output Context of stage 2"
       ]
   ],
   .
   .
   .
   [
       [
           "Response Message of stage N"
       ],
       [
           "Output Context of stage N"
       ]
   ]
]

Once we have the conversation flow saved in output context, when user will input “Back” our Back intent will be invoked. Back intent will do the following:

  • We have to enable webhook call for Back intent so that we can check what is the last response+context and respond to user with that response+context. So user will get the previous response and we set the output context of that response so that conversation flow will continue from there.
  • Also, we have to remove response+context we send to user so that if user says “Back” again then he will be taken further back in the conversation.

We’ll integrate the above solution using Python+Django.

Let’s begin!

Install Python:

We are using python language for the webhook, so install it first. You can find information about how to install python here.

Install and setup Django:

Open the terminal and run below command to install django.

 pip install Django

Follow the following steps to setup django project in your system.

 django-admin startproject Back_Function

This will create create Back_Function Project in the following structure

 Back_Function/
     Manage.py
     Back_Function/
         __init__.py
         Settings.py
         Urls.py
         Wsgi.py

Now run the following commands:

 cd Back_Function
 python manage.py migrate
 python manage.py startapp myapp
 
 myapp/
     __init__.py
     Admin.py
     Apps.py
     Models.py
     Tests.py
     Views.py

Now add newly created app “myapp” in /Back_Function/settings.py file.

 INSTALLED_APPS = [
         'Django.contrib.admin',
         'Django.contrib.auth',
         'Django.contrib.contenttypes',
         'Django.contrib.sessions',
         'Django.contrib.messages',
         'Django.contrib.staticfiles',
         'myapp',
  ]

DialogFlow setup:

Now, open Dialogflow and Sign up using your google ID.

Now create a new Agent using CREATE AGENT Button and call it “Back_functionality” and hit CREATE to save the agent.

Your DialogFlow agent is ready. Now it’s time to make intents.

Create Intents using CREATE INTENT button and give the name “Stage_1” to the intent.

Now set Training phrases to help intent to identify this particular intent and action to provide the value to your fulfillment webhook request.

Enable Webhook call for this intent in the Fulfillment section to communicate with your server.

Now save the intent using SAVE button.

Let’s create another follow-up intent of “Stage_1”  intent.

Rename the newly created follow_up intent by “Stage_2”, add training phrases, change action and enable fulfillment call similar to we done in Stage_1 intent.

Now create another two intent Stage_3 and Stage_4 where Stage_3 is follow-up of Stage_2 and Stage_4 is follow-up of Stage_3.

The flow will be like:

Stage_1 -> stage_2 -> Stage_3 -> Stage_4

Now make separate “Back” intent in the same agent. This intent is not follow-up intent of any intent.

Set the training phrases and action and also enable webhook call in the fulfillment section of the intent.

Create Fulfillment Webhook

Now it’s time to create webhook URL for webhook.

To do that, copy the following code in your /Back_Function/Back_Function/urls.py file.

from django.urls import path
from myapp import views
urlpatterns = [
    # define a route for home
    path('home/', views.home, name='home'),
    path('webhook/', views.webhook, name='webhook')
]

Building fulfillment responses from webhook

Copy below code in the Back_Function/myapp/views.py file.

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json
from df_response_lib import *

# define home function
def home(request):
    return HttpResponse('Hello World!')
                                                        
@csrf_exempt
def webhook(request):

    ff_response = fulfillment_response()

    # build a request object of the qebhook request
    req = json.loads(request.body)

    # get action from json
    action = req.get('queryResult').get('action')

    # Django responses from webhook

    # response for the Stage_1 intent
    if action == "S_1":
        Text_response = "You are in Stage 1."

    # response for the Stage_2 intent
    elif action == "S_2":
        Text_response = "You are in Stage 2."
    
    # response for the Stage_3 intent
    elif action == "S_3":
        Text_response = "You are in Stage 3."
    
    # response for the Stage_4 intent
    elif action == "S_4":
        Text_response = "You are in Stage 4."

    storage = []
    context = []

    # loop over the all the context 
    mess = req.get('queryResult').get("outputContexts")
    for m in mess:
        name = m.get('name')
        # save the parameter value of 'back' context which is our saved last responses
        if name[-len("back"):] == "back":
            stored = m.get("parameters").get("parameter")
            for k in stored:
                storage.append(k)
        else:
            # contexts of the current stage
            context.append(m)
    
    # when request for back is arise, get the last response from the storage which was saved in the parameter of the back context and remove the currernt response from the data.
    if action == "back":
        temp = storage[-2]
        ff_context = temp[1]
        ff_text = temp[0]
        storage.pop(len(storage)-1)
    else:
        ff_text = ff_response.fulfillment_text(Text_response)
        new_data = [ff_text, context]
        storage.append(new_data)

    # output context from the webhook for back functionality    
    contexts = [['back', 100, {'parameter': storage}]]
    # get session name from fulfilment reqest
    session = req.get("session")

    # set the output context in the webhook response
    ff_out_context  = ff_response.output_contexts(session, contexts)

    # Also activate the contexts of the last response
    if action == "back":
        for i in range(len(ff_context)):
            ff_out_context.get('output_contexts').append(ff_context[i])

    # set webhook response for the requested action        
    reply = ff_response.main_response(fulfillment_text = ff_text, output_contexts = ff_out_context)

    # webhook response
    return JsonResponse(reply, safe = False)

In this, we are using our Dialogflow Response Library which you can clone from our github repo.

Now our django project is ready. Let’s execute below command to run server.

python manage.py runserver

Create a public URL for your webhook

In our previous step we created a webhook with URL /webhook but it is your local application and it is not accessible publicly. We need a URL which can be accessed by Dialogflow, so to do that we need a tool to call webhook from the local server. For that purpose we can use a web tunneling tool NGROK. You can download it from here.

After installing NGROK, run below command in the new terminal. Our app is running on port 8000.

ngrok http 8000

You should get output look like below.

NGROK generates random URL of the local server.

We can start our Django application now but it won’t work on the NGROK URL. We have to add the NGROK URL in ALLOWED_HOSTS in /Back_Function/Back_Function/settings.py file.

ALLOWED_HOSTS = [
       '8d14d11e.ngrok.io',
       '127.0.0.1'
]

Once NGROK URL is added in the ALLOWED_HOSTS start django application using runserver command. You can access your webhook on NGROK URL now.

Set Fulfillment URL

Now open fulfillment section from the left panel of the Dialogflow. And enable the webhook to communicate with the local server. Add the URL of the webhook generated by the NGROK here.

Then hit the SAVE button at the end of the fulfillment page.

Make sure you are adding url + /webhook/ not just NGROK URL.

We are done with the setup. Let’s test and confirm.

Results

Now try in the test console of the right side of the Dialogflow window. You will see that when you give the training phrases as per the context flow it will give the responses and change in the activated context. And by giving “back”, it will give previous responses back and also activate the respective output context.

Code Download

We have created a zip file containing the code for back-functionality explained above. You are welome to download the code and give it a try.

Fill up the form below to download your back functionality webhook for Dialogflow.

* indicates required

You will receive zipped file containing back functionality webhook code.

Do let us know in comment if you have any question.

Leave a Reply

Your email address will not be published. Required fields are marked *