天气机器人:DialogFlow + OpenWeather + Python

问题的提法



任务设置如下:编写一个电报机器人,该机器人将识别有关特定城市今天的天气问题并给出有关天气的信息。



对话流



已经内置了ML的DialogFlow框架最适合人类语音识别。让我们开始工作。



点击链接https://dialogflow.cloud.google.com/,登录到您的Google帐户,然后转到机器人创建页面。单击“创建新代理”,然后输入代理的名称:“ weather-bot”。我们选择默认语言俄语。



图片



DialogFlow使用的主要对象是意图。与机器人进行交互时,此意图始终有效,作为开发人员的您的任务是将每个意图与各种训练短语一起使用,以便机器人每次都能尽可能正确地猜出该意图。



因此,转到“意图”选项卡。创建漫游器时,会自动创建两个意图:“默认后备意图”和“默认欢迎意图”。当漫游器启动或您向其写入欢迎消息时,将调用“欢迎意图”。当漫游器不了解您正在编写的内容时,即在所有情况下都会调用后备广告在所有情况下,如果没有其他意图起作用。保持默认意图不变,然后单击“创建意图”,将其称为“ get-weather”。出于这种意图,我们将继续本文的工作。



图片



转到我们的“获取天气”意图,然后转到“训练短语”选项卡并创建几个训练短语,例如,以下内容:



图片



请注意,DialogFlow会自动将城市检测为位置参数。这非常方便,因为我们会将这些参数传递给应用程序的后端。



DialogFlow本身几乎没有什么可做的-允许它的Webhooks与我们的机器人的后端进行交互。为此,向下滚动到底部,展开“实现”选项卡,然后在“为此意图启用webhook调用”上打勾。



背部



让我们开始编写我们的机器人的服务器端。我们将与Flask一起使用Python编写。选择OpenWeather API来获取天气信息在此站点上注册,然后您将通过邮件收到API密钥-我们的应用程序中将需要它。另外,由于此API中有关天气的信息是由纬度和经度参数(宽度和经度)返回的,因此我们需要以某种方式将城市转换为其宽度和经度。geopy Python库将帮助我们解决这一问题。



我们导入所需的一切:



from flask import Flask, request, make_response, jsonify
import requests
import json
from geopy.geocoders import Nominatim


创建Flask应用程序:



app = Flask(__name__)


并将我们的API KEY插入API_KEY变量中:



API_KEY = '<your_API_KEY_here>'


我们为“ /”路径写一条路由:



@app.route('/')
def index():
    return 'Hello World!'


然后是result()函数,其中将实现程序的所有逻辑:



def results():
    req = request.get_json(force=True)

    action = req.get('queryResult').get('action')

    result = req.get("queryResult")
    parameters = result.get("parameters")

    if parameters.get('location').get('city'):
        geolocator = Nominatim(user_agent='weather-bot')
        location = geolocator.geocode(parameters.get('location').get('city'))
        lat = location.latitude
        long = location.longitude
        weather_req = requests.get('https://api.openweathermap.org/data/2.5/onecall?lat={}&lon={}&appid={}'.format(lat, long, API_KEY))
        current_weather = json.loads(weather_req.text)['current']
        temp = round(current_weather['temp'] - 273.15)
        feels_like = round(current_weather['feels_like'] - 273.15)
        clouds = current_weather['clouds']
        wind_speed = current_weather['wind_speed']

    return {'fulfillmentText': '   - {} ,   {} ,  - {}%,   - {}/'.format(str(temp), str(feels_like), str(clouds), str(wind_speed))}


剩下的就是添加过渡到我们的应用程序所经过的路径,我们称之为webhook:



@app.route('/webhook', methods=['GET', 'POST'])
def webhook():
    return make_response(jsonify(results()))


并运行该应用程序:



if __name__ == '__main__':
   app.run(debug=True)


我们做到了!



这就是全部吗?



并不是的。该程序在我们的本地计算机上,但是DialogFlow对此一无所知。要将我们的机器变成可以在Internet上使用的服务器,我们需要一个特殊的实用程序。Ngrok满足这些要求下载它,启动它,然后在控制台中输入以下内容:“ ngrok http 5000”。将出现一个https链接,必须将其复制并放置在DialogFlow中。复制,转到DialogFlow中的Fulfillment,将Webhook置于启用状态,然后将链接粘贴到结果字段中。我们添加路线,即 “ / webhook”。您应该最终得到类似于以下内容的内容:



图片



现在,我们启动Python应用程序。剩下的很少-将集成与Telegram连接起来。转到“集成”选项卡,选择电报,然后按照说明获取令牌,插入令牌,然后瞧-应用程序已准备就绪!仍然需要测试:



图片



我希望本文对您有所帮助,并鼓励您自己在这一领域进行实验。项目代码可在此处获得



All Articles