Сейчас каждый строит своего бота и сегодня мы расскажем как написать бота на Python/Flask. Исходники можно взять здесь.
Мы будем использовать следующие технологии:
- На бэкенде: Flask
- Безопасное туннелирование к localhost: Ngrok
- Платформа обработки естественного языка: API AI
- Развёртываем в Facebook Messenger
- Python wrapper для OpenWeatherMap API для погоды
Мы сделаем следующую штуку: запрашиваем у чат-бота погоду в заданном месте, а он отвечает погодной сводкой.
Пример:
Вопрос: What is the current weather of New Delhi? (Какая погода в Нью-Дели?)
Ответ: Current weather report of New Delhi : max temp: 42.0 min temp: 40.0 current temp: 40.95 wind speed :2.6 humidity 20{33d8302486bd10b0fde64d2037652320e6f176a736d71849c0427b0d7398501a} (Погода в Нью-Дели: макс. темп: 42.0 мин. темп: 40.0 текущая темп: 40.95 скорость ветра :2.6 влажность 20{33d8302486bd10b0fde64d2037652320e6f176a736d71849c0427b0d7398501a})
1. Настраиваем API AI
API AI это платформа для построения приложений, основанных на общении. Зарегистрируйтесь там и создайте агента для доступа к тестовой консоли. Перейдите в настройки агента и получите Client Access Token.
Создаём intent
Intent (намерение) это связка пользовательского запроса и желаемого ответа. Мы добавим его со следующим пользовательским запросом: «What’s the weather in Singapore?» («Какова погода в Сингапуре?»)
где Singapore задан как сущность типа @sys.geo-city. Т.е. этот параметр принимает любые запросы в диалоге для построения корректного ответа.
И мы добавим такой ответ на этот запрос: «Current weather report of $geo-city :»
Python клиент к API AI
Мы будем использовать python SDK API AI для обработки естественного языка.
2. Настраиваем Open Weather Map
У Open Weather Map есть хороший API для доступа к погодным условиям в любой точке планеты. И также есть отличная обёртка на python для этого API. Регистрируйтесь на OWM и получайте свой API ключ для доступа к API погоды.
owm = pyowm.OWM('your_open_weather_map_api_key') # You MUST provide a valid API key
forecast = owm.daily_forecast(input_city)
observation = owm.weather_at_place(input_city)
w = observation.get_weather()
print(w)
print(w.get_wind())
print(w.get_humidity())
max_temp = str(w.get_temperature('celsius')['temp_max'])
min_temp = str(w.get_temperature('celsius')['temp_min'])
current_temp = str(w.get_temperature('celsius')['temp'])
wind_speed = str(w.get_wind()['speed'])
humidity = str(w.get_humidity())
Если же у вас есть PRO-подписка, запрос будет немного другим:
owm = pyowm.OWM(API_key='your-API-key', subscription_type='pro')
3. Создаём Flask Server
import apiai
Добавляем все токены и верифицируем их:
CLIENT_ACCESS_TOKEN = 'your_client_access_token_from_api_ai'
PAGE_ACCESS_TOKEN = 'your_facebook_page_access_token'
VERIFY_TOKEN = 'verification_token_for_facebook_chatbot_using_python'
ai = apiai.ApiAI(CLIENT_ACCESS_TOKEN)
Теперь нужно отправить запрос к Facebook webhook от приложения с проверкой корректности токена, заданного в приложении facebook:
@app.route('/', methods=['GET'])
def handle_verification():
if (request.args.get('hub.verify_token', '') == VERIFY_TOKEN):
print("Verified")
return request.args.get('hub.challenge', '')
else:
print("Wrong token")
return "Error, wrong validation token"
Приложение будет обрабатывать все сообщения от facebook messenger
@app.route('/', methods=['POST'])
def handle_message():
'''
Handle messages sent by facebook messenger to the applicaiton
'''
data = request.get_json()
if data["object"] == "page":
for entry in data["entry"]:
for messaging_event in entry["messaging"]:
if messaging_event.get("message"):
sender_id = messaging_event["sender"]["id"]
recipient_id = messaging_event["recipient"]["id"]
message_text = messaging_event["message"]["text"]
send_message_response(sender_id, parse_natural_text(message_text))
return "ok"
Вызовем facebook Graph API с помощью библиотеки python requests для отправки сообщения пользователю facebook
def send_message(sender_id, message_text):
'''
Sending response back to the user using facebook graph API
'''
r = requests.post("https://graph.facebook.com/v2.6/me/messages",
params={"access_token": PAGE_ACCESS_TOKEN},
headers={"Content-Type": "application/json"},
data=json.dumps({
"recipient": {"id": sender_id},
"message": {"text": message_text}
}))
Используем API AI для разбора сообщения от пользователя, получим ответ боту от API AI. Затем получаем погодные данные от open weather map и добавляем их к ответу бота
def parse_user_text(user_text):
'''
Send the message to API AI which invokes an intent
and sends the response accordingly
The bot response is appened with weaher data fetched from
open weather map client
'''
request = ai.text_request()
request.query = user_text
response = json.loads(request.getresponse().read().decode('utf-8'))
responseStatus = response['status']['code']
if (responseStatus == 200):
print("Bot response", response['result']['fulfillment']['speech'])
weather_report = ''
input_city = response['result']['parameters']['geo-city']
#Fetching weather data
owm = pyowm.OWM('edd197717da7951b85f8f6936fc27b13') # You MUST provide a valid API key
forecast = owm.daily_forecast(input_city)
observation = owm.weather_at_place(input_city)
w = observation.get_weather()
print(w)
print(w.get_wind())
print(w.get_humidity())
max_temp = str(w.get_temperature('celsius')['temp_max'])
min_temp = str(w.get_temperature('celsius')['temp_min'])
current_temp = str(w.get_temperature('celsius')['temp'])
wind_speed = str(w.get_wind()['speed'])
humidity = str(w.get_humidity())
weather_report = ' max temp: ' + max_temp + ' min temp: ' + min_temp + ' current temp: ' + current_temp + ' wind speed :' + wind_speed + ' humidity ' + humidity + '{33d8302486bd10b0fde64d2037652320e6f176a736d71849c0427b0d7398501a}'
print("Weather report ", weather_report)
return (response['result']['fulfillment']['speech'] + weather_report)
else:
return ("Please try again")
def send_message_response(sender_id, message_text):
sentenceDelimiter = ". "
messages = message_text.split(sentenceDelimiter)
for message in messages:
send_message(sender_id, message)
if __name__ == '__main__':
app.run()
Активируйте виртуальную среду, установите необходимые пакеты
pip install -r requirements.txt
Запустите скрипт
python fb-chatbot.py
Настраиваем теннелирование к localhost
Для вывода локального сервера в интернет мы воспользуемся утилитой ngrok, с помощью которой к нему можно будет достучаться через webhook от приложения facebook
sudo apt-get update
sudo apt-get install ngrok-client
Запустим клиента
./ngrok http -bind-tls=true 5000
Помните, что secure callback URL (https) нужен для верификации.
Настраиваем facebook messenger
Создайте страницу facebook и приложение facebook. Добавьте Webhook к приложению.
Получите ID приложения и обновите его в скрипте.
Добавьте Messenger к приложению и создайте token для страницы, которую будете использовать для чата.
Включите интеграцию webhook с callback URL и верифицируйте token
Задайте события в подписке на странице
Перезапустите сервер и чатбот готов. Также Facebook предоставляет дополнительные элементы пользовательского интерфейса, потестировать их можно здесь.
По материалам «How to Create a Facebook Messenger Bot with Python Flask»
Разработчик: java, kotlin, c#, javascript, dart, 1C, python, php.
Пишите: @ighar. Buy me a coffee, please :).