Путаница с Google Assistant и WorldWeatherOnline API

Итак, я только начал создавать агенты API для Google Assistant. Я следил за всем в документации по API.ai на https://api.ai/docs/getting-started/basic-fulfillment-conversation, чтобы нижеприведенный агент получал информацию о погоде и возвращал ответ. Это рабочий код, но я хотел проявить творческий подход к ответу. Что я хочу сделать, так это получить страну из ответа и решить, отображать ли эквивалент возвращенной температуры в градусах Цельсия или Фаренгейта. Но после тестирования в консоли он продолжает использовать цельсий. Я также хочу вернуть дружеские напоминания в зависимости от температуры, которые я добавлю позже.

'use strict';
const http = require('http');
const host = 'api.worldweatheronline.com';
const wwoApiKey = '[api key]';
exports.weatherWebhook = (req, res) => {
  // Get the city and date from the request
  let city = req.body.result.parameters['geo-city']; // city is a required param
  // Get the date for the weather forecast (if present)
  let date = '';
 if (req.body.result.parameters['date']) {
date = req.body.result.parameters['date'];
console.log('Date: ' + date);
  }
  // Call the weather API
  callWeatherApi(city, date).then((output) => {
// Return the results of the weather API to API.AI
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': output, 'displayText': output }));
 }).catch((error) => {
// If there is an error let the user know
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ 'speech': error, 'displayText': error }));
 });
};
function callWeatherApi (city, date) {
  return new Promise((resolve, reject) => {
// Create the path for the HTTP request to get the weather
let path = '/premium/v1/weather.ashx?format=json&num_of_days=1' +
  '&q=' + encodeURIComponent(city) + '&key=' + wwoApiKey + '&date=' + date;


console.log('API Request: ' + host + path);
// Make the HTTP request to get the weather
http.get({host: host, path: path}, (res) => {
  let body = ''; // var to store the response chunks
  res.on('data', (d) => { body += d; }); // store each response chunk
  res.on('end', () => {
    // After all the data has been received parse the JSON for desired data


    let response = JSON.parse(body);
    let forecast = response['data']['weather'][0];
    let minTemp = forecast['mintempC'];
    let maxTemp = forecast['maxtempC'];
    let unit = '°C'; 
    let location = response['data']['request'][0];
    //get country
    let country = location['query'].split(",")[1];

    let conditions = response['data']['current_condition'][0];
    let currentConditions = conditions['weatherDesc'][0]['value'];

    if(country == "Liberia" || country == "Myanmar" || country == "United States of America")
    {
        minTemp = forecast['mintempF'];
        maxTemp = forecast['maxtempF'];
        unit = '°F';
    }

    // Create response
  let output =
   `Current conditions in the ${location['type']} 
    ${location['query']} are ${currentConditions} with a projected high of
    ${maxTemp} ${unit} and a low of 
    ${minTemp}${unit} on 
    ${forecast['date']} in ${country}`;
    // Resolve the promise with the output text
    console.log(output);
    resolve(output);
  });
  res.on('error', (error) => {
    reject(error);
  });
});
 });
}

person kcsting    schedule 27.08.2017    source источник
comment
Добро пожаловать в Stack Overflow! Эти типы вопросов (обзор) лучше подходят для просмотра кода. Я бы рекомендовал размещать сообщения там, если у вас нет конкретной проблемы (см. Как спросить).   -  person Nate Barbettini    schedule 27.08.2017
comment
Привет! прости за это. Тогда я перенесу этот пост туда. Благодарность!   -  person kcsting    schedule 27.08.2017
comment
Похоже, вы на самом деле просите не о проверке кода, а о помощи в исправлении вашего кода, который не делает то, что вы хотите. Вы должны отредактировать свой заголовок, чтобы лучше отразить это и предотвратить закрытие вашего вопроса.   -  person Cody Gray    schedule 27.08.2017


Ответы (2)


Хотя вы пометили это с помощью api.ai и action-on-google, и ваш код, похоже, получен из https://api.ai/docs/getting-started/basic-fulfillment-conversation#setup_weather_api., на самом деле это не проблема с самим API действий. Похоже, это связано с тем, как вы обрабатываете результаты API WorldWeatherOnline (WWO) и что вы ожидаете от ввода, предоставляемого помощником Google.

У вас есть несколько проблем, все они сосредоточены вокруг этой строки:

let country = location['query'].split(",")[1];

Эта строка получает значение, которое вы указали в запросе. В нем вы предполагаете ряд вещей, таких как:

  1. Пользователь указывает страну (WWO может взять только город, если он достаточно различим).

  2. Страна указывается вторым полем (применительно к городам США часто указывается штат, что делает страну третьим полем).

  3. Google Assistant указывает их с заглавной буквы имени страны (вероятно, но не гарантируется).

  4. Если страной является США, она указывается точной строкой «Соединенные Штаты Америки» вместо чего-то более короткого (но все же узнаваемого), например «США» или «Соединенные Штаты».

Кроме того, существует логическая проблема, заключающаяся в том, что человек, запрашивающий информацию, может захотеть получить ее в единицах, которые знакомы ему, а не в единицах, традиционных для этой страны. Американец, спрашивающий о погоде в Испании, вероятно, все еще хочет по Фаренгейту.

Несмотря на это, хорошим способом отладки было бы распечатать значение location['query'], чтобы увидеть, каково значение для различных входных данных, и соответствующим образом настроить.

Я не уверен, что есть прямой и хороший способ справиться с тем, что вы пытаетесь сделать. Некоторые мысли:

  • Вы можете попробовать искать страны как подстроку без учета регистра в любом месте строки запроса, но это может привести к ложным срабатываниям. Тем не менее ... это, вероятно, ваше самое простое решение.

  • Предложение @Shuyang хорошее, но языковой стандарт не всегда лучший способ сделать это, и вам нужно будет использовать расширения Google Actions для данных, предоставленных через API.AI.

  • Вы также можете запросить текущее местоположение пользователя (опять же, если вы используете Google Actions), а затем использовать геолокатор, чтобы выяснить, где он находится. Но это действительно грязно.

  • Вы можете рассматривать это как часть разговора — расширить фразы Intent, чтобы они могли указывать «в градусах Фаренгейта» или с другими возможными фразами, и выполнить преобразование. Или сохраните некоторую информацию в контексте, и если они представляют собой последующую фразу, такую ​​​​как «Что это в градусах Фаренгейта», предоставьте обновленную, преобразованную информацию.

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

Я думаю, что первый вариант самый простой, а последний наиболее естественный для разговора, но все зависит от того, каким на самом деле может быть значение location['query'].

person Prisoner    schedule 29.08.2017
comment
Эй, заключенный, твое первое предложенное решение — это именно то, к чему я стремился. location['query'] возвращает [город, страна] из данных ответа. поэтому в моем коде я получал страну и использовал ее в качестве основы для отображения градусов Цельсия или Фаренгейта. но вы правы, я, вероятно, должен рассматривать это как часть разговора. Еще слишком многому предстоит научиться. - person kcsting; 29.08.2017
comment
Это совершенно новый способ мышления, и мы все еще пытаемся выяснить, что работает лучше всего. Фундаментальное правило — думайте о том, что на самом деле говорят люди. Если ответ помог - всегда приветствуется принятие или голосование за ответ. - person Prisoner; 30.08.2017

Вместо того, чтобы пытаться узнать, из какой страны находится пользователь, вы можете узнать локаль пользователя, используя getUserLocale, который пользователь может изменить по своему усмотрению и не зависит от его местоположения, что может лучше отражать предпочтительную шкалу температуры.

С помощью этого метода вы получите строку типа 'en-US' или 'en-GB', которая связана со страной, и, таким образом, вы можете сопоставить ее с определенной температурной шкалой. Пример использования локализации можно найти здесь.

В Actions on Google Console Simulator вы можете изменить языковой стандарт в раскрывающемся списке Language, чтобы вы могли тестировать свое приложение, используя разные языковые стандарты.

person Shuyang Chen    schedule 28.08.2017