Build Intelligent Chatbot using Dialogflow
Tags: machinelearning, python, serverless, googlecloud
Published: 2020-06-28 17:57:22

Today chatbots have become a very important part for most websites, not only to answer FAQs or provide customer service but also to give intelligent service for website navigation. There are lots of chatbot tools available in the market from Amazon Lex, Google Dialogflow, to open source RASA, etc. We are going to look at how we can create chatbot using Google's Dialogflow and python cloud function.

Dialogflow is an end-to-end, build-once deploy-everywhere development suite provided by Google for creating conversational interfaces for websites, mobile applications, popular messaging platforms, and IoT devices.

### Dialogflow Setup -
1. Agent - First create a new Agent on dialogflow. Provide general information related to your project requirement under settings tab.

2. Intent - It categorizes an end-user's intention for one conversation turn. When a user says something, dialogflow matches with best intent in the agent.

3. Paraphrases - Training phrases are example phrases for what end-users might type or say. Each intent can have multiple Paraphrases. ![Intent and Paraphrases](https://dev-to-uploads.s3.amazonaws.com/i/kzmftshjysvhk2p51n7z.png)

4. Action and Parameters - The action field is a simple convenience field that assists in executing logic in your service. When an intent is matched at runtime, Dialogflow provides the extracted values from the end-user expression as parameters, which we can use in service triggered by using the above action field. ![Action and parameters](https://dev-to-uploads.s3.amazonaws.com/i/7h09rs8drxprnwnmef04.png)

5. Response - Each Intent has a response handler that can return responses after the intent is matched. we can set text or different response formats provided by dialogflow.

### Detect Intent -
Deploy small python program on cloud function which detect intents for user queries. you also have to get access key of dialogflow to run it from cloud function. Download it from service accounts in IAM and Admin. 

![Access key](https://dev-to-uploads.s3.amazonaws.com/i/xp8ig1qgl7eoatve7acs.png)

` requirements.txt `

```
Flask
dialogflow
functions-framework
```

`main.py`

```python
import dialogflow
import json, logging
from flask import request, jsonify
from google.protobuf.json_format import MessageToJson
from google.protobuf.struct_pb2 import Struct
from google.protobuf.struct_pb2 import Value

def detect_intent(request):
    response = {
        'status_code': 500,
        'message': 'Failed to fetch data from dialogflow.',
        'data': []
    }

    try:
        request_json = request.get_json(silent=True, force=True)

        project_id = "<project id>"
        session_client = dialogflow.SessionsClient.from_service_account_json('key.json')

        payload = {'project_id': project_id, 'session_id': request_json.get("session_id")}
        struct_pb = Struct(fields={
            key: Value(string_value=value) for key, value in payload.items()
        })
        params = dialogflow.types.QueryParameters(
            time_zone="IST", payload=struct_pb)
        session = session_client.session_path(project_id, request_json.get("session_id"))

        text_input = dialogflow.types.TextInput(
            text=request_json.get("text"), language_code='en-US')
        query_input = dialogflow.types.QueryInput(text=text_input)
        df_response = session_client.detect_intent(
            session=session, query_input=query_input, query_params=params)

        # Convert proto object and serialize it to a json format string.
        json_obj = MessageToJson(df_response)

        result = json.loads(json_obj)
        response['status_code'] = 200
        response['data'] = result
        response['message'] = "Successfully fetched response from dialogflow."
    except Exception as e:
        logging.error(e)

    return jsonify(response)
```

### Webhook Call -
For each Intent if you want to process some business logic using parameters extracted from query, you enable webhook call under fulfillment in Intent. Add webhook api endpoint in the fulfillment tab.

`requirements.txt`
```
pydialogflow-fulfillment
Flask
functions-framework
```

`main.py`
```python
import json
from flask import request
from pydialogflow_fulfillment import DialogflowResponse, DialogflowRequest
from pydialogflow_fulfillment.response import SimpleResponse, OutputContexts
import logging

def webhook(request):
    dialogflow_response = DialogflowResponse()
    try:
        dialog_fulfillment = DialogflowRequest(request.data) 
        action = dialog_fulfillment.get_action()
        if action == "welcome":
            dialogflow_response.add(SimpleResponse("This is a simple text response","This is a simple text response"))
        else:
            dialogflow_response.add(SimpleResponse("This is a fallback text response","This is a fallback text response"))

    except Exception as e:
        logging.error(e)
        dialogflow_response = DialogflowResponse()
        dialogflow_response.add(SimpleResponse("Something went wrong.","Something went wrong."))
        return json.loads(dialogflow_response.get_final_response())

    return json.loads(dialogflow_response.get_final_response())
```

Download code from [github](https://github.com/MrKanthaliya/dialogflow-cloud-function)