Skip to Content
Technical Articles
Author's profile photo Ivan Femia

Application modernization with Google Cloud Platform: Chatbots

This is the second part of my blog series on Application modernization with Google Cloud Platform and today we will create a Dialogflow CX agent (aka chatbot) that consumes SAP data to improve user experience and provide different ways of interacting with SAP systems.
I’ve been passionate of chatbot since a long time and I also wrote a ebook about it
SAP Conversational AI: Developing and Training Chatbots

The scope of this blog is to give the architecture best practices and the code to extend, change and adapt the scope and the look and feel of your Dialogflow agent to your specific needs.

The sample code is not intended for production usage. 

Sample

Sample

Prerequisite

An API endpoint has been created following the guide in part 1.

Architecture overview

As we get started, it is important to describe the architecture:

  1. User interacts using a web browser with a web application hosted on Google Cloud Run
  2. Cloud Run application uses the Dialogflow Python client library to interact with Dialogflow CX agent
  3. Dialogflow CX agent manages the conversation flows
  4. Webhooks, published in Google Cloud Function, integrate with Apigee proxy
  5. Google Cloud Function handles the API calls to the endpoint in Apigee.
  6. Apigee secures and monitors access to the SAP backend OData endpoint.

Note: The SAP backend can be hosted on GCP, on premise, or on any other cloud.

Note: Before running your agent in production, be sure to implement the
productionization best practices.

Configure Cloud Function

We start putting together our building blocks. As a first step, assuming you API proxy has been configured as described in part 1, we want to create a cloud function to act as webhook for the Dialogflow agent.

  1. Create a new project in GCP
  2. Open the Cloud Functions service
  3. Click on Create Function
  4. Add a function name sapwebhook and leave all the other parameters as default
  5. Check that the Trigger type is set on HTTP
  6. Copy the URL of your Cloud Function and save it for future use
  7. Click Save

Cloud%20function

Cloud function

  1. Expand Variables, Networking and Advanced Settings section
  2. Switch to the environment variables tab
  3. Add two runtime environment variables
Parameter value
API_ENDPOINT your api proxy endpoint
APIKEY your api key for the application

Runtime%20variable

Runtime variable

  1. Click Next
  2. Switch the runtime to Python 3.8
  3. Change the entry point name to webhook
  4. Edit the requirements.txt file adding the following code
# Function dependencies, for example:
# package>=version
requests==2.18.4
  1. Edit the main.py file adding the following code
import json
import os
import requests

def webhook(request):
  url = os.getenv('API_ENDPOINT')
  apikey = os.getenv('APIKEY')
  request_json = request.get_json()
  if request_json.get('fulfillmentInfo', None):
    tag = request_json['fulfillmentInfo']['tag']
    print('Tag: {}'.format(tag))
  else:
    return ('Unrecognized request', 404)

  if tag == 'salesorder.list':
    params = dict(
      apikey=apikey
    )
    resp = requests.get(url=url, params=params)
    data = resp.json() # Check the JSON Response Content documentation below
    reply = {
        "fulfillment_response": {
          "messages": [
            {
              "payload": {
                "richContent": [
                  []
                ]
              }
            }
          ]
        }
      }
    for salesorder in data['results']:
      salesorderitem = {
                    "type": "list",
                    "title": salesorder['SalesOrderID'],
                    "subtitle": salesorder['Note'],
                    "event": {
                      "name": "salesorder.list",
                      "languageCode": "",
                      "parameters": {
                        "SalesOrderID": salesorder['SalesOrderID'],
                        "SalesOrderKey" : salesorder['SalesOrderKey']
                      }
                    }
                  }
      reply['fulfillment_response']['messages'][0]['payload']['richContent'][0].append(salesorderitem)
      reply['fulfillment_response']['messages'][0]['payload']['richContent'][0].append({"type":"divider"})
  elif tag == 'salesorder.detail':
    order = str(int(request_json['sessionInfo']['parameters']['ordernumber'])).zfill(10)
    params = dict(
      apikey=apikey,
      salesorderid=order
    )
    resp = requests.get(url=url, params=params)
    data = resp.json() # Check the JSON Response Content documentation below
    if len(data['results']):
      salesorder = data['results'][0]
      text = 'Sales order {} total value is {} {} and it has been {} and {}'.format(salesorder['SalesOrderID'],salesorder['TotalSum'],salesorder['Currency'],salesorder['DeliveryStatusDescription'],salesorder['BillingStatusDescription'])
    else:
      text = 'No sales order {} is available in the system'.format(order)
    reply = {
        "fulfillment_response": {
          "messages": [
            {
              "text": {
                "text": [text]
              }
            }
          ]
        }
      }

  return json.dumps(reply)
  1. The cloud function editor should look as below

Cloud%20function

Cloud function

  1. Click on Deploy and wait for the function to activate
  2. From the Cloud Function list click on the more options and select test function

Cloud%20function

Cloud function

  1. Edit the triggering event payload using the json below
{
    "fulfillmentInfo": {
        "tag" : "salesorder.list"
    }
}
  1. Press the Test the function button and confirm the response as below

Cloud%20function%20-%20test

Cloud function – test

The setup of the cloud function is completed and the webhook is now available for consumption

Create the Dialogflow CX agent

Next step is to create and configure the Dialogflow agent. For simplification we will use an already built agent for this scope

Enable Dialogflow APIs

  1. Enable Dialogflow API via the Cloud Console or the Cloud Shell using
gcloud services enable dialogflow.googleapis.com

 

Create the Dialogflow agent

  1. Open Dialogflow CX portal
  2. Select your GCP Project from the list

GCP%20Project

GCP Project

  1. Press Create agent
  2. Name for the agent SAP Sales Order and check the Enable stackdriver logging

Create%20agent

Create agent

  1. Press Create
  2. Dialogflow CX brings you into the agent creation developer tool. In this example we will use pre build agent.
  3. Open the Agent drop down on top and select View all agents
  4. Open the context menu of your newly created agent and select and select Restore

Restore%20agent

Restore agent

  1. In the restore popup select Google Cloud Storage and insert the GCS URI
gs://public-demo-assets/dialogflow/SAPSalesOrder.json

Restore%20agent

Restore agent

  1. Press Restore
  2. Your agent is imported successfully
  3. Open the agent
  4. Switch to Manage tab on the left and select Webhooks
  5. Select the existing webhook and change the URL with the one of your cloud function created above and press Save

Modify%20webhook

Modify webhook

  1. Return to the agent list
  2. From the context menu select Copy name, it will copy the agent details that we will need in the web application app configuration

Copy%20agent

Copy agent

Deploy the web application in Cloud Run

In this final step, we will deploy a simple Cloud Run web application that will be act as a front end.

  1. From the shell clone the GIT repository into a folder of preference
git clone https://github.com/ivanfemia/ccai-agent-client.git
  1. Configure the application to run in your GCP project
cd ccai-agent-client
cp .dockerignore.SAMPLE .dockerignore
cp Dockerfile.SAMPLE Dockerfile
  1. Edit config.py and configure PAGE_TITLE and PAGE_H1_TITLE
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     https://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Configuration file."""

PAGE_TITLE = 'SAP Dialogflow CX'
PAGE_H1_TITLE = 'SAP Sales Order Agent'

Note: Make sure you have an empty line at the end of the file

  1. Configure the application environment variable
  2. Edit the app.yaml file providing the DIALOGFLOW_PROJECT_ID and DIALOGFLOW_AGENT_ID
Parameter value
DIALOGFLOW_PROJECT_ID your GCP project id
DIALOGFLOW_AGENT_ID your agent id

Note: DIALOGFLOW_AGENT_ID is the unique identifier we copied in Dialogflow CX. In my case projects/sap-dialogflow/locations/us-central1/agents/644c170f-6543-4a7b-ab78-82736f9d05e9 the agent id is 644c170f-6543-4a7b-ab78-82736f9d05e9

  1. Final step deploy the web application in Cloud Run
  2. Build your container image using Cloud Build, by running the following
    command from the directory containing the Dockerfile
export DIALOGFLOW_PROJECT_ID=**your GCP project id***
gcloud builds submit --tag gcr.io/$DIALOGFLOW_PROJECT_ID/agent
  1. Deploy using the following command and following the instruction on screen
gcloud run deploy --image gcr.io/$DIALOGFLOW_PROJECT_ID/agent --platform managed

Note: For more details on Building and Running a Cloud Run application refer to the official documentation

Demo execution

Open the target url from the previous step

Sample script

Use this sample script to demo the use case

  1. Respond to the bot greetings

Sample

Sample

  1. Select Recent sales orders
  2. The agent lists the latest 10 sales orders in SAP ES5

Sample

Sample

  1. Select or type one of the Sales Order number in the list
  2. The agent provides the delivery status and payment status

Sample

Sample

  1. You can loop requesting the list again or a specific Sales order
  2. Finally just confirm that you completed the interaction

Sample

Sample

 

Assigned tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ze Vargas
      Ze Vargas

      Hi and thank you for this blog, very nice

      Is apigee for connection security like cloud connector? can I use cloud connector with google to connect to odata in SAP gateway? Like this example https://blogs.sap.com/2019/11/07/google-hangout-chatbot-integration-with-s-4hana/

      Author's profile photo Ivan Femia
      Ivan Femia
      Blog Post Author

      No, Apigee is the API Management layer to connect securely from you network to Apigee you can establish a secure VPN tunnel or considering Apigee hybrid (based on Anthos)

      Cloud Connector works only with SAP Cloud Platform.

      Author's profile photo Ze Vargas
      Ze Vargas

      So app engine can connect to SAP Gateway odata if I dont have apigee? Thank you

      Author's profile photo Ivan Femia
      Ivan Femia
      Blog Post Author

      yes it can