1

We have a chatbot for our website today, that is not build using Google technology. The bot has a JSON REST API where you can send the question to and which replies with the corresponding answers. So all the intents and entities are being resolved by the existing chatbot.

What is the best way to wrap this functionality in Google Assistant / for Google Home?

To me it seems I need to extract the "original" question from the JSON that is send to our webservice (when I enable fullfilment).

But since context is used to exchange "state" I have to find a way to exchange the context between the dialogflow and our own chatbot (see above).

But maybe there are other ways ? Can it (invoke our chatbot) be done directly (without DialogFlow as man in the middle) ?

mpjjonker
  • 917
  • 1
  • 6
  • 28
  • Can you update your question to elaborate on what you mean by "but then I have to find a way to exchange the context". Are you currently using Dialogflow to build your bot? Why do you [think you] want to use Dialogflow if not? – Prisoner Jan 05 '18 at 16:07

3 Answers3

1

This is one of the those responses that may not be enough for someone who doesn't know what I am talking about and too much for someone who does. Here goes:

It sounds to me as if you need to build an Action with the Actions SDK rather than with Dialog flow. Then you implement a text "intent" in your Action - i.e. one that runs every time the user speaks something. In that text intent you ask the AoG platform for the text - see getRawInput(). Now you do two things. One, you take that raw input and pass it to your bot. Two, you return a promise to tell AoG that you are working on a reply but you don't have it yet. Once the promise is fulfilled - i.e. when your bot replies - you reply with the text you got from your bot.

I have a sample Action called the French Parrot here https://github.com/unclewill/french_parrot. As far as speech goes it simply speaks back whatever it hears as a parrot would. It also goes to a translation service to translate the text and return the (loose) French equivalent.

Your mission, should you choose to accept it, is to take the sample, rip out the code that goes to the translation service and insert the code that goes to your bot. :-)

Two things I should mention. One, it is not "idiomatic" Node or JavaScript you'll find in my sample. What can I say - I think the rest of the world is confused. Really. Two, I have a minimal sample of about 50 lines that eschews the translation here https://github.com/unclewill/parrot. Another option is to use that as a base and add code to call your bot and the Promise-y code to wait on it to it.

If you go the latter route remove the trigger phrases from the action package (action.json).

William DePalo
  • 615
  • 4
  • 8
  • William can you expand a bit on your note about the example not being "'idiomatic' Node or JavaScript"? I be got a lot of JS experience but am a real Node newbie. I'm curious about what you mean and your approach that is different. – hofo Jan 06 '18 at 17:00
  • Idioms describe the common patterns seen in languages. I stray off the beaten path because I tend to use closures much less frequently than others do in JS, I don't like to define functions inline as arguments to other functions where I can help it, I use the very symmetrical (and to my mind logical) Allman style for braces and my Callback class bridges the gap between Node's fondness for callbacks and Google's for Promises in a way that allows me to write in the way I think. None of that is required, write in whatever style suits you. I mentioned it just to point out that it is a choice. – William DePalo Jan 07 '18 at 00:29
  • Thanks for taking the time to respond. I am new at this, and more accustomed with serverside languages like Java and C#. But I will inspect your code and try to see what I can make of it. I will report back with my results – mpjjonker Jan 07 '18 at 11:49
  • 1
    You are welcome. Just btw, there is no requirement to use JS or Google's library. You might want to read this https://developers.google.com/actions/tools/fulfillment-hosting page on setting up a reverse proxy/tunnel to your development environment. Then run my sample or any other Action sample one on your dev machine. That done, browse to http://127.0.0.1:4040 and click on each post of the conversation which ngrok captured. You will see the JSON payloads that were sent by AoG and the sample's JSON response. Your mission is to put up an endpoint in C# or Java that responds in the same ways. – William DePalo Jan 07 '18 at 17:45
  • Thanks @WilliamDePalo I have reached the first milestone: initial request and reponse. Where can I find the place in the JSON that holds "state" or "context" ? E.g. I have given my name and in the next question / answers I want to use this name as part of the answer. – mpjjonker Jan 08 '18 at 14:49
  • "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "KEYBOARD", "query": "my name is will" } ], "arguments": [ { "name": "text", "rawText": "my name is will", "textValue": "my name is will" } ] } ], – William DePalo Jan 08 '18 at 16:09
  • Sorry about the last comment. I was trying to paste the JSON here but I only have 500 characters. I think you will find the request defined by Google here: https://developers.google.com/actions/reference/rest/Shared.Types/AppRequest – William DePalo Jan 08 '18 at 16:12
1

So you already have a Backend that process user inputs and sends responses back and you want to use it to process a new input flow (coming from Google Assistant)?

That actually my case, I've a service as a Facebook Messenger ChatBot and recently started developing a Google Home Action for it.

It's quite simple. You just need to:

  {
  "locale": "en",
  "actions": [
    {
      "name": "MAIN",
      "description": "Default Welcome Intent",
      "fulfillment": {
        "conversationName": "app name"
      },
      "intent": {
        "name": "actions.intent.MAIN",
        "trigger": {
          "queryPatterns": [
            "Talk to app name"
          ]
        }
      }
    }
  ],
  "conversations": {
    "app name": {
      "name": "app name",
      "url": "https://your_nodejs_middleware.com/"
    }
  }
}
//require express and all required staff to build a Node.js server,
//look on internet how to build a simple web server in Node.js 
//if you a new to this domain. const {
ActionsSdkApp } = require('actions-on-google');

app.post('/', (req, res) => {
req.body = JSON.parse(req.body);
const app = new ActionsSdkApp({
    request: req,
    response: res
});

// Create functions to handle requests here
function mainIntent(app) {
    let inputPrompt = app.buildInputPrompt(false,
        'Hey! Welcome to app name!');
    app.ask(inputPrompt);
}

function respond(app) {
    let userInput = app.getRawInput();
    //HERE you get what user typed/said to Google Assistant. 
    //NOW you can send the input to your BACKEND, process it, get the response_from_your_backend and send it back
    app.ask(response_from_your_backend);
}

let actionMap = new Map();
actionMap.set('actions.intent.MAIN', mainIntent);
actionMap.set('actions.intent.TEXT', respond);
app.handleRequest(actionMap); });

Hope that helped!

hzitoun
  • 5,492
  • 1
  • 36
  • 43
0

Thanks for all the help, the main parts of the solution are already given, but I summarize them here

  • action.json that passes on everything to fullfilment service
  • man in the middle (in my case IBM Cloud Function) to map JSON between services
  • Share context/state through the conversationToken property

You can find the demo here: Hey Google talk to Watson

mpjjonker
  • 917
  • 1
  • 6
  • 28