如何使用Javascript ajax调用在DialogFlow v2上进行http调用

时间:2018-05-31 14:47:22

标签: javascript google-cloud-platform google-cloud-datastore dialogflow

我在使用Node.js的DialogFlow官方网站上找到了这个例子,它工作正常,但我不知道如何将它集成到我的Web应用程序中。

我可以将它集成到我的其他javascript jquery代码中吗?在这里我需要运行节点index.js,但如果我与我的代码集成,我还需要这样做吗?

const projectId = 'xxx'; //https://dialogflow.com/docs/agents#settings
const sessionId = 'xxxxx';
const query = 'Hello';
const languageCode = 'en-US';

// Instantiate a DialogFlow client.
const dialogflow = require('dialogflow');
const sessionClient = new dialogflow.SessionsClient();

// Define session path
const sessionPath = sessionClient.sessionPath(projectId, sessionId);
console.log(sessionPath);
// The text query request.
const request = {
  session: sessionPath,
  queryInput: {
    text: {
      text: query,
      languageCode: languageCode,
    },
  },
};

// Send request and log result
sessionClient
  .detectIntent(request)
  .then(responses => {
    console.log('Detected intent');
    const result = responses[0].queryResult;
    console.log(`  Query: ${result.queryText}`);
    console.log(`  Response: ${result.fulfillmentText}`);
    if (result.intent) {
      console.log(`  Intent: ${result.intent.displayName}`);
    } else {
      console.log(`  No intent matched.`);
    }
  })
  .catch(err => {
    console.error('ERROR:', err);
  });

有没有其他选择,我们可以使用普通的javascript jquery,ajax使用DialogFlow v2,而不必每次我想使用对话框流时都要做节点index.js。

DialogFlow v1使用起来非常简单。我有这样的事情:

fetch(url, {
    body: JSON.stringify(data),
    // cache: 'no-cache',
    // credentials: 'same-origin',
    headers: {
        'content-type': 'application/json',
        "Authorization": "Bearer " + configs.accessToken,
    },
    method: 'POST',
    mode: 'cors',
    redirect: 'follow',
    referrer: 'no-referrer',
})
    .then(response => response.json()) // parses response to JSON

6 个答案:

答案 0 :(得分:0)

You can easily call Dialogflow's V2 API detectIntent endpoint from jQuery.

The API docs show the URL and request formats:

POST https://dialogflow.googleapis.com/v2/{session=projects/*/agent/sessions/*}:detectIntent

{
  "queryParams": {
    object(QueryParameters)
  },
  "queryInput": {
    object(QueryInput)
  },
  "inputAudio": string
}

Authentication works slightly differently; instead of using an access token, you'll create a service account and key using the Cloud dashboard. This documentation page explains how.

答案 1 :(得分:0)

https://dialogflow.com/docs/reference/v2-auth-setup

完成上述页面并创建服务密钥后,您必须拥有如下所示的json文件:

{
    "type": "",
    "project_id": "",
    "private_key_id": "",
    "private_key": "",
    "client_email": "",
    "client_id": "",
    "auth_uri": "",
    "token_uri": "",
    "auth_provider_x509_cert_url": "",
    "client_x509_cert_url": ""
  }  

使用此文件,执行这两个命令(如果还没有,则需要安装gcloud CLI):

gcloud auth activate-service-account --key-file=<service-account-key-file.json>
gcloud auth print-access-token

之后,复制访问令牌并将其作为环境变量提供给您的程序(如果您不在意,则将其提供给硬编码)。然后,您只需发出HTTP post请求。我在我的React项目中使用axios,这是detectIntent:

的示例代码
import axios from "axios";

const DIALOG_FLOW_TOKEN = process.env.REACT_APP_DIALOG_FLOW_TOKEN;
const DIALOG_FLOW_API_ROOT_URL = "https://dialogflow.googleapis.com/v2";
const YOUR_PROJECT_ID = <YOUR_PROJECT_ID>;
const SESSION_ID = <SESSION_ID>;
const URL = `${DIALOG_FLOW_API_ROOT_URL}/projects/${YOUR_PROJECT_ID}/agent/sessions/${SESSION_ID}:detectIntent`;

var config = {
    headers: {
        "Authorization": "Bearer " + DIALOG_FLOW_TOKEN,
        "Content-Type": "application/json"
    }
};

export function sendText(text) {
    var bodyParameters = {
        "queryInput": { "text": { "text": text, "languageCode": "en" } },
    };

    const request = axios.post(
        URL,
        bodyParameters,
        config
    );

    return request;
} 

答案 2 :(得分:0)

以下代码段说明了如何从Web应用程序与dialogflow NLU通信。要获取访问令牌,我们可以利用Google云SDK来获取令牌,但是它具有一小时的有效期,因此将其用于其他服务中并在调用dialogflow之前获取它将提供一种解决方法。

$(document).ready(function(){

$("button").click(function(){

    $.ajax({
        type: "POST",
        url: "https://dialogflow.googleapis.com/v2/projects/YOUR-PROJECT-NAME/agent/sessions/SESSIONIDOFYOURCHOICE:detectIntent",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        headers: {
            "Authorization": "Bearer " + "YOUR ACCESS TOKEN GOES HERE",
        },
        data: JSON.stringify({ "queryInput":{
            "text":{
                "text":"YOUR QUERY TO NLU",
                "languageCode":"en-US"
            }
        } }),
        success: function(data) {
            $("#div").html(data.queryResult.fulfillmentText);
        },
        error: function() {
            console.log("Internal Server Error");
        }
    });     

});

});

答案 3 :(得分:0)

正如其他人之前所说的那样,访问令牌的持续时间为一小时,在此之后它将变得无用。因此,有必要对API进行调用(在我的情况下为http调用),以便每小时一次请求一次访问令牌,然后按Satheesh的说明使用它。在https://developers.google.com/identity/protocols/OAuth2ServiceAccount中提供了有关如何生成签名以进行调用和稍后使用的说明。

一旦您从服务帐户获得带有私钥和您必须使用的电子邮件的json文件(不是您的电子邮件,而是由服务帐户生成的电子邮件),就可以使用jsrsasign库(使用纯JavaScript) ,您可以在https://github.com/kjur/jsrsasign中找到,以生成JSON Web签名(JWS),从而生成JSON Web令牌(JWT),这将是进行http调用以获取访问令牌所需的。

然后按照Satheesh的描述使用它,通过jQuery调用Dialogflow V2。

下一个代码是我用来实现此目的的代码:

要生成JWT(使用相关库):

function _genJWS() {
    var header = '{"alg":"RS256","typ":"JWT"}';
    var claimSet = jwtClaimSet();
    var privateKey = jwtPrivateKey();

    var sHead = newline_toDos(header);
    var head = KJUR.jws.JWS.readSafeJSONString(sHead);
    var sPayload = newline_toDos(claimSet);
    var sPemPrvKey = privateKey;

    var jws = new KJUR.jws.JWS();
    var sResult = null;
    try {
        prv = KEYUTIL.getKey(sPemPrvKey);

        sResult = KJUR.jws.JWS.sign(head.alg, sHead, sPayload, prv);
    } catch (ex) {
        alert("Error: " + ex);
    }
    return sResult;
}

要请求访问令牌:

function _requestAccessToken() {
    var access_token = accessToken;
    var assertion = _genJWS();
    console.log('Assertion: ' + assertion);
    jQuery.ajax({
        type: "POST",
        url: "https://www.googleapis.com/oauth2/v4/token",
        contentType: "application/x-www-form-urlencoded",
        dataType: "json",
        data: "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=" + assertion,
        success: function(response) {
            console.log("success");
            console.log(response);
            access_token = response.access_token;
            console.log(access_token);
        },
        error: function() {
            console.log("Error");
        }
    });
    return access_token;
}

然后使用该访问令牌对Dialogflow进行HTTP调用。

希望有帮助。

答案 4 :(得分:0)

我找到了一种完全从前端(浏览器)JavaScript获取有效访问令牌的方法。

1)从npm安装npm软件包jsrsasign

2)将要点中的文件添加到您的项目中:https://gist.github.com/Venryx/bfa9b69583638dfbf611a9f292721a75

3)在DialogFlowExample.ts的开头输入所有常量的值。

您的服务帐户信息可在以下网址找到:https://console.cloud.google.com/iam-admin/serviceaccounts

该服务帐户的电子邮件在表中列出,并且其私钥(如果已创建)在下载的密钥json文件中找到。如果您不记得将密钥json文件放在何处(或者尚未创建文件),则可以使用“操作->创建密钥”来创建一个新文件。

4)使用您的声明集和私钥致电GetAccessToken(例如,请参见Gist)。它将返回一个承诺。

5)一旦检索到访问令牌,便会使用检索到的访问令牌来解决承诺。 (该函数将访问令牌缓存60分钟。在此之后,令牌会过期,因此再次调用该函数将使其检索一个新令牌。)

示例

linked Gist包含使用DialogFlow将音频片段转换为文本的几乎完整的用法示例。它唯一未显示的部分是如何获取“音频片段”。

为此,请在此处查看我的答案的第1部分:https://stackoverflow.com/a/57859776/2441655

答案 5 :(得分:0)

这样对我有用。

const dialogflow = require('dialogflow');
var projectId = ""; // your dialogflow project id when you click on settings of the DF agent
var sessionId = ""; // session ID
var config = {
// use credentials or keyFilename i'm using keyFile
    // credentials: {
        // private_key: privateKey,
        // client_email: clientEmail,
    // }
        keyFilename: './google.json'
};

var sessionClient = new dialogflow.SessionsClient(config);

async sendTextMessageToDialogFlow(textMessage) {
        // Define session path
        const sessionPath = sessionClient.sessionPath(projectId, sessionId);
        // The text query request.
        const request = {
            session: sessionPath,
            queryInput: {
                text: {
                    text: textMessage,
                    languageCode: 'en'
                }
            }
        }
        try {
            let [responses] = await sessionClient.detectIntent(request)
            console.log(responses);
        } catch (err) {
            console.error('DialogFlow.sendTextMessageToDialogFlow ERROR:', err);
            throw err
        }
    };