Press enter to see results or esc to cancel.

Integrating DialogFlow (API.ai) into Qiscus SDK Chat Application

Just recently on October 10th, Google announced a change in name of API.AI into DialogFlow. There are a couple of new features following this change. Regardless of what has been changed, in this post we are going to share a simple way of how to integrate your agents that is created using DialogFlow into any Qiscus chat SDK application.

As DialogFlow doesn’t have a famous ‘one-click integration’ feature for Qiscus (yet), we need to make a workaround to do so. Fortunately, DialogFlow provides some integration ways through its SDK options, here in the image, you can see several programming languages that you can use for your agent integration.

chat sdk, chat, sdk, in-app chat, app chat, qiscus sdk, qiscus, rtc, communication, messenger
Image of DialogFlow SDK for integration

For our simplicity purpose, we are going to use our last article on how to create a simple chat application using QiscusSDK and how to integrate a simple echo bot into it as prior requirement to this post. You can find the codes here. Since it uses Python as the webhook, in this article we are going to use DialogFlow SDK for Python as well called called apiai (this might changes later as the effect of name change).

Another thing to note is that we assume you already have an agent or two created in DialogFlow, if not please refer to the basic tuts to create one.

Add DialogFlow SDK Python Package

Alright, let’s get started! First thing first, let’s add DialogFlow SDK python package (apiai) into our project, come on open setup.py file, and add it,

 

from setuptools import setup, find_packages

setup(
    name='simplebot',
    version='1.0',
    long_description=__doc__,
    packages=find_packages(),
    include_package_data=True,
    zip_safe=False,
    install_requires=[
        'apiai',
        'flask', 
        'requests'
    ],
)

and let’s import that package intoour simplebot/views.py file then instantiate new object from this package,

import apiai
import json
import requests

from flask import render_template, request
from simplebot import app

app_id = "YOUR_APP_ID"
secret_key = "YOUR_SECRET_KEY"
sender_email = "YOUR_BOT_EMAIL"
bot_name = "YOUR_BOT_NAME"
qiscus_sdk_url = "https://{}.qiscus.com".format(app_id)

client_access_token = "YOUR_DIALOGFLOW_CLIENT_ACCESS_TOKEN"

ai = apiai.ApiAI(client_access_token)
...
.

Notice in the code above, we need client_access_token to initiate new object from the package. So please make sure you already got this token from your agent DialogFlow console dashboard and assign it to the client_access_token, you may want to see this image to locate where it is.

chat sdk, chat, sdk, in-app chat, app chat, qiscus sdk, qiscus, rtc, communication, messenger
Image of console

Incoming Message and Agent Response

After you got this package set, let’s implement it in our index() function. First we will need to get query from Qiscus chat app to be passed to the DialogFlow agent before we send it to get the response from agent.

...

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        payload = request.get_json().get('payload')

        room_id = payload.get("room").get("id")
        message = payload.get("message").get("text")

        # let's prepare the incoming message (query) we want to send to dialogflow agent
        conv = ai.text_request()
        conv.session_id = "ADD_YOUR_UNIQUE_SESSION_ID(ANY_SESSION_ID_WOULD_WORK)"
        conv.query = message    

        # and let's get the response from dialogflow agent
        response = conv.getresponse()
        response_json = json.loads(response.read().decode('utf-8'))
        response_messages = response_json.get("result").get("fulfillment").get("messages")
    
        post_url = "{}/api/v2/rest/post_comment".format(qiscus_sdk_url)
        headers = {"QISCUS_SDK_SECRET": secret_key}

        data = {
            "sender_email": sender_email,
            "room_id": room_id,
            "message": message,
            "type": "text",
            "payload": {}
        }
        
        req = requests.post(post_url, headers=headers, params=data)

...

 

Also read: “Making your Apps “Chatable”

 

What we need to do next is just to send back any response we got from agent to the Qiscus chat app. This can be anything: plain text or any additional payload. So, before we return it back, we need to know the structure of payload that is returned by our agent at DialogFlow, please have a look at JSON code below, this JSON code is the payload that is returned from our agent in DialogFlow.

{
  "id": "354eaf3c-c40e-42e4-acf6-fc2ef0e71799",
  "timestamp": "2017-10-26T08:11:58.239Z",
  "lang": "en",
  "result": {
    "source": "agent",
    "resolvedQuery": "yo",
    "action": "hi",
    "actionIncomplete": false,
    "parameters": {},
    "contexts": [],
    "metadata": {
      "intentId": "fe8dbb22-43bf-4cb4-b634-48c3a2af98ae",
      "webhookUsed": "false",
      "webhookForSlotFillingUsed": "false",
      "intentName": "hi"
    },
    "fulfillment": {
      "speech": "Hi! How are you doing?",
      "messages": [
        {
          "type": 0,
          "id": "948f5dad-550c-4fa1-93ba-3819d8e42fbb",
          "speech": "Hi! How are you doing?"
        }
      ]
    },
    "score": 1
  },
  "status": {
    "code": 200,
    "errorType": "success"
  },
  "sessionId": "d70073ae-0cdb-4bc4-b7d9-d8d0b16b98af"
}

From JSON code above, there is a fulfillment field. It has additional children fields that are actual responses from our agent which we are interested in.

Notice the messages field? its value is a list. So we may assume our agent could return one or more messages when we make a request to DialogFlow. This could be another text or additional custom payload, such as payload for button or card. However, to simplify this process, let’s handle text message only.

Ok, let’s modify our index() function in views.py file again.

 ...

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        payload = request.get_json().get('payload')

        room_id = payload.get("room").get("id")
        message = payload.get("message").get("text")

        # let's prepare the incoming message (query) we want to send to dialogflow agent
        conv = ai.text_request()
        conv.session_id = "ADD_YOUR_UNIQUE_SESSION_ID(ANY_SESSION_ID_WOULD_WORK)"
        conv.query = message    

        # and let's get the response from dialogflow agent
        response = conv.getresponse()
        response_json = json.loads(response.read().decode('utf-8'))
        response_messages = response_json.get("result").get("fulfillment").get("messages")
    
        post_url = "{}/api/v2/rest/post_comment".format(qiscus_sdk_url)
        headers = {"QISCUS_SDK_SECRET": secret_key}

        for msg in response_messages:
        
            data = {
                "sender_email": sender_email,
                "room_id": room_id,
                "message": msg.get("speech"),
                "type": "text",
                "payload": {}
            }
        
            try:
                requests.post(post_url, headers=headers, params=data)
            except requests.exceptions.RequestException as e:
                print(e)
                return "Something went wrong!", 401  
        
        return "OK", 200
    else:
        return render_template('index.html', appId=app_d, senderEmail=sender_email)

...

save and let’s run our webhook, and you may open http://locahost:5000 in your browser.

$ make run

chat sdk, chat, sdk, in-app chat, app chat, qiscus sdk, qiscus, rtc, communication, messenger

Webhook

Since we’ve been developing this integration locally, Qiscus SDK won’t recognise our webhook even though we are trying to add our local webhook address to the Qiscus SDK. So to help making our webhook open to the internet, we are going to use ngrok and add the generated temporary subdomain addresses into our Qiscus SDK, please refer to this for ngrok.

After you do that, please try to have a chat again through generated subdomain address in your browser. Voila, you got a reply from your agent in DialogFlow!

Accompanying codes can be found at https://github.com/qiscus/qiscus-dialogflow. You can also experience directly at https://qiscusdialog.herokuapp.com/.

Closing

To sum up, this article is only focusing on how we integrate our agent that is created in DialogFlow which returns plain text only. In order to leverage your agent capability, you may want to add additional custom payload as additional fulfillment response. For example you may want to return message that contains image and buttons from DialogFlow. You can refer to Qiscus docs for any type of comments that is supported by Qiscus as well as how to add custom payload in DialogFlow for more information.

Comments

Leave a Comment

Show Buttons
Hide Buttons