Агент Dailogflow получает и сообщает данные из базы данных MySQL - PullRequest
0 голосов
/ 28 июня 2018

Прежде всего большое спасибо за это удивительное сообщество. Я должен сказать, что я очень новичок в программировании (я больше статистик), но до сих пор это кажется очень сложным и интересным! В последнее время я пытался создать агента Dialogflow, который запрашивает данные из базы данных по запросу. Я использую node.js. Конечно, для сборки я пытаюсь увидеть коды в интернете и согласованно изменить их под свои нужды, но вот уже три дня я застрял!

Я не могу понять, в чем проблема, пожалуйста, помогите !!! 1

Найдите ниже мой код:

'use strict';

const functions = require( 'firebase-functions' );
const mysql = require( 'mysql' );
const {WebhookClient} = require( 'dialogflow-fulfillment' );
const {Text, Card, Image, Suggestion, Payload} = require( 'dialogflow-fulfillment' );

process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements

// Wikipedia link and image URLs
const mysiteurl = 'site URL';


exports.dialogflowFirebaseFulfillment = functions.https.onRequest( ( request, response ) =>{
  const agent = new WebhookClient( {request, response} );
  console.log( 'Dialogflow Request headers: ' + JSON.stringify( request.headers ) );
  console.log( 'Dialogflow Request body: ' + JSON.stringify( request.body ) );

  function welcome( agent ){
    agent.add( `Welcome to infohub personal assistant, my name is Isobel` );
    agent.add( new Card( {
        title: `mysite`,
        imageUrl: mysiteurl,
        text: `Did you know already mysite if not visit it now! `,
        buttonText: 'mysite',
        buttonUrl: mysiteurl
      } )
    );
    agent.add( `I can help you get information already contained in mysite` );
    agent.add( new Suggestion( `population` ) );
    agent.add( new Suggestion( `avgincome` ) );
    agent.add( new Suggestion( `thisyeargdp` ) );
  }

  function getinfo( agent ){
    // Get parameters from Dialogflow to convert
    const country = agent.parameters.country;
    const info = agent.parameters.info;
    console.log( `User requested to get info on  ${info} in ${country}` );


    if( action === 'get.data' ){

      //Call the callDBJokes method
      output = callDB().then( ( output ) =>{
        // Return the results of the weather API to API.AI
        response.setHeader( 'Content-Type', 'application/json' );
        response.send( JSON.stringify( output ) );
      } ).catch( ( error ) =>{
        // If there is an error let the user know
        response.setHeader( 'Content-Type', 'application/json' );
        response.send( JSON.stringify( error ) );
      } );

    }


    // Sent the context to store the parameter information
    // and make sure the followup 
    agent.setContext( {
      name: 'info',
      lifespan: 1,
      parameters: {country: country, info: info}
    } );

    // Compile and send response
    agent.add( ` ${info} in ${country} is ${output}` );

    agent.add( `Would you like to know something else?` );
    agent.add( new Suggestion( `population` ) );
    agent.add( new Suggestion( `avgincome` ) );
    agent.add( new Suggestion( `thisyeargdp` ) );
  }


  function fallback( agent ){
    agent.add( `I didn't get that, can you try again?` );
  }

  function callDB( info, country ){
    return new Promise( ( resolve, reject ) =>{

        try{

          var connection = mysql.createConnection( {
            host: "sql7.freemysqlhosting.net",
            user: "sql7243950",
            password: "XXXXXXXX",
            database: "sql7243950"
          } );


          connection.query( 'SELECT' + info + 'FROM mocktable WHERE country=' + country, function( error, results, fields ){
            if( !error ){

              let response = "The solution is: " + results[0];
              response = response.toString();
              let output = {'speech': response, 'displayText': response};
              console.log( output );
              resolve( output );

            } else{

              let output = {
                'speech': 'Error. Query Failed.',
                'displayText': 'Error. Query Failed.'
              };
              console.log( output );
              reject( output );

            }
          } );
          connection.end();

        } catch
          ( err ){
          let output = {
            'speech': 'try-cacth block error',
            'displayText': 'try-cacth block error'
          };
          console.log( output );
          reject( output );

        }

      }
    )
      ;
  }


  let intentMap = new Map(); // Map functions to Dialogflow intent names
  intentMap.set( 'Default Welcome Intent', welcome );
  intentMap.set( 'get info about mycountry', getinfo );
  intentMap.set( 'Default Fallback Intent', fallback );
  agent.handleRequest( intentMap );
} )
;

1 Ответ

0 голосов
/ 28 июня 2018

Здесь есть несколько вопросов, некоторые из которых связаны, а некоторые нет. Давайте рассмотрим некоторые из них.

Для начала у вас есть сравнение

if( action === 'get.data' ){

но «действие» нигде не определено или не назначено. Таким образом, этот блок никогда не будет выполнен (и никогда не будет вызывать базу данных, похоже).

Не ясно, как вы выполняете некоторые задания. Когда вы получаете результат запроса, ваша строка

output = callDB().then( ( output ) =>{

, который, кажется, смешивает возвращение Обещания и пытается использовать результат выполнения Обещания. Я подозреваю, что второй «вывод» - это то, что вам нужно, а не первый, по причинам, которые, я надеюсь, немного яснее.

В этом предложении then() вы отправляете обратно JSON, но затем также (за пределами предложения then()) пытаетесь использовать библиотеку Dialogflow для установки контекста, установки ответа и предоставления подсказок. Смешивание этих двух методов не работает - либо отправьте JSON, либо используйте библиотеку.

Это усложняется, поскольку callDB() (который вы вызываете до then()) генерирует JSON для отправки обратно. Опять же - выберите один метод или другой. Я подозреваю, что лучшим подходом будет callDB() фактически вызвать DB и, возможно, помассировать и вернуть Promise с результатами для вызывающего метода для форматирования в то, что вы хотите, чтобы пользователь услышал / увидел.

Говоря об обещаниях, хорошо , что callDB() возвращает обещание. Однако вы не правильно воспринимаете это обещание двумя способами:

Во-первых, поскольку getInfo() вызывает вещи, которые выполняются асинхронно (т. Е. - вызов callDB()), он также должен возвращать Promise. Вот почему вы, вероятно, не хотели фиксировать результат из callDB(), как я отмечал выше. Самый простой способ сделать это для вашего кода сделать что-то вроде

return callDB().then( output => {
  // Output things are fine.
}).catch( err => {
  // Output the world is ending.
};

Вторая проблема с тем, как вы работаете с Promises, заключается в том, что ваша текущая реализация getInfo() имеет код после этого блока. В данный момент вы выполняете все вызовы agent.setContext() и agent.add(). Эти должны быть внутри блока then(). (Где мой комментарий "все хорошо" выше.)

...