챗봇 시작해보기
파이썬과 노드로 만들어 보는 챗봇
(Slack, facebook..)
ABCD, 한성일
0. 챗봇이란?
챗봇이란?
고객의 요청을 대신 응답해주는 채팅로봇
인공지능
빅데이터
자연어처리
프로그래밍
나이가 어떻게 되
시나요?
텍스트
음성
…
묻지 마세요..
응답요청
Chatbot
머신러닝
챗봇 예
심심이 페이스북 챗봇
어디에 쓸까요?
가장 쉽게 떠오르는 곳은 콜 센터입니다.
또 어디가 있을까요?
물건주문, 호텔예약, 비서…
생각보다 간단할지 모릅니다.
1. 챗봇 플로우
챗봇 프레임웍
http://kitt.ai/ https://dev.botframework.com/
챗봇 플랫폼
라인 슬렉
텔레그램 페이스북
일반적인 챗봇 플로우
http://www.lds.com/coepost/enabling-a-smart-user-experience-using-chatbots/
슬랙과 페이스북 API 를 이용해서 챗봇을 만들어보겠습니다.
간단한..
2. 파이썬으로 슬렉챗봇 만들기
선작업
1. 파이썬 설치
https://realpython.com/blog/python/getting-started-with-the-slack-api-using-python-and-flask/
참고
2. 슬랙 커뮤니티 생성
VIRTUAL ENV 설정
$ mkdir abcd-python-slack-bot
$ virtualenv venv
$ source venv/bin/activate
(venv)$ pip install slackclient==1.0.0
토큰생성
https://api.slack.com/web
토큰생성
https://api.slack.com/docs/oauth-test-tokens
토큰을 환경 변수로 지정
(venv)$ export SLACK_TOKEN=‘생성된 토큰'
ngrok 을 이용 외부 오픈 SSL 주소 생성
https://ngrok.com/download
(venv)$ ./ngrok http 5000
로컬 서버를 SSL 로 외부 오픈..
WEBHOOK
https://api.slack.com/outgoing-webhooks
WEBHOOK
https://abcds.slack.com/apps/new/A0F7VRG6Q-outgoing-webhooks
INTEGRATION SETTINGS
https://abcds.slack.com/services/B37GEBQBZ?added=1
ngrok 으로 생성된 주소 + /webhook
사용될 채널
웹훅 토큰
WEBHOOK
(venv)$ export SLACK_WEBHOOK_SECRET=‘생성된 웹훅 토큰'
FLASK 설치
(venv)$ pip install flask
RECEIVE.PY
# -*- coding: utf-8 -*-
import os
from flask import Flask, request, Response
from slackclient import SlackClient
app = Flask(__name__)
SLACK_WEBHOOK_SECRET = os.environ.get('SLACK_WEBHOOK_SECRET')
SLACK_TOKEN = os.environ.get('SLACK_TOKEN', None)
slack_client = SlackClient(SLACK_TOKEN)
def send_message(channel_id, message):
slack_client.api_call(
"chat.postMessage",
channel=channel_id,
text=message,
username='abcdBot',
icon_emoji=':monkey_face:'
)
@app.route('/webhook', methods=['POST'])
def inbound():
print("get " + request.form.get('token'))
print("username " + request.form.get('user_name'))
username = request.form.get('user_name')
if request.form.get('token') == SLACK_WEBHOOK_SECRET and username != 'slackbot':
channel_name = request.form.get('channel_name')
channel_id = request.form.get('channel_id')
username = request.form.get('user_name')
text = request.form.get('text')
inbound_message = username + " in " + channel_name + " says: " + text
send_message(channel_id, unicode("따라쟁이 ", 'utf-8') + " " + text)
print(inbound_message)
return Response(), 200
@app.route('/', methods=['GET'])
def test():
return Response('It works!')
if __name__ == "__main__":
app.run(debug=True)
receive.py
RECEIVE.PY
(venv)$ python receive.py
구동화면
실제 서버를 설정해서 포팅해봅시다.
3. 노드로 페이스북 챗봇 만들기 (HEROKU)
선작업
http://x-team.com/2016/04/how-to-get-started-with-facebook-messenger-bots/
nodejs 설치
참고
https://nodejs.org/ko/download/
선작업
heroku 가입이 되어있어야 함
https://heroku.com/
https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up
heroku CLI 가 설치되어있어야 함
프로젝트 생성
$ mkdir abcd-node-bot
$ cd abcd-node-bot/
$ npm init
$ npm install express body-parser request --save
{
"name": "testbot",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"start": "node index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.15.2",
"express": "^4.14.0",
"request": "^2.79.0"
}
}
express 설치
$ npm install express body-parser request --save
INDEX.JS 생성
index.js 생성
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));
// Server frontpage
app.get('/', function (req, res) {
    res.send('잘돈다.');
});
// Facebook Webhook
app.get('/webhook', function (req, res) {
console.log(req.query['hub.verify_token']);
if (req.query['hub.verify_token'] === 'abcd_verify_token') {
// webhook 설정에 입력된 토큰
res.send(req.query['hub.challenge']);
} else {
res.send('Invalid verify token');
}
});
node index.js
HEROKU 생성
$ heroku login
로컬 GIT 설정
$ git init
$ heroku create
$ git add .
$ git commit -m ‘ABCD 노드 봇 첫번째 커밋'
$ git push heroku master
.gitignore
node_modules
작동확인
https://warm-spire-76279.herokuapp.com/
페이스북 페이지 만들기
https://www.facebook.com/pages/create/
페이지 생성 완료
앱생성
https://developers.facebook.com/quickstarts/
기본설정으로 앱생성
제품추가
토큰생성
토큰생성
WEB HOOK 설정
https://developers.facebook.com/
heroku 경로
WEB HOOK 설정
페이지를 선택해주세요!
WEBHOOK 설정
PAGE_ACCESS_TOKEN 설정
PAGE_ACCESS_TOKEN
토큰 유효성 확인
https://warm-spire-76279.herokuapp.com/webhook?
hub.verify_token=abcd_verify_token
따라하기 봇 테스트
KITTEN
https://placekitten.com/
kitten 300 200
따라하기 & 키튼 봇 소스 1
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));
// Server frontpage
app.get('/', function (req, res) {
res.send('This is TestBot Server');
});
// Facebook Webhook
app.get('/webhook', function (req, res) {
console.log(req.query['hub.verify_token']);
if (req.query['hub.verify_token'] === 'abcd_verify_token') { // webhook 설정에 입력된 토큰
res.send(req.query['hub.challenge']);
} else {
res.send('Invalid verify token');
}
});
따라하기 & 키튼 봇 소스 2
// handler receiving messages
app.post('/webhook', function (req, res) {
var events = req.body.entry[0].messaging;
for (i = 0; i < events.length; i++) {
var event = events[i];
if (event.message && event.message.text) {
if (!kittenMessage(event.sender.id, event.message.text)) {
sendMessage(event.sender.id, {text: event.message.text});
}
} else if (event.postback) {
console.log("Postback received: " + JSON.stringify(event.postback));
}
}
res.sendStatus(200);
});
// generic function sending messages
function sendMessage(recipientId, message) {
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
method: 'POST',
json: {
recipient: {id: recipientId},
message: message,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
};
따라하기 & 키튼 봇 소스 3
// send rich message with kitten
function kittenMessage(recipientId, text) {
text = text || "";
var values = text.split(' ');
if (values.length === 3 && values[0] === 'kitten') {
if (Number(values[1]) > 0 && Number(values[2]) > 0) {
var imageUrl = "https://placekitten.com/" + Number(values[1]) + "/" + Number(values[2]);
message = {
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
"elements": [{
"title": "Kitten",
"subtitle": "Cute kitten picture",
"image_url": imageUrl ,
"buttons": [{
"type": "web_url",
"url": imageUrl,
"title": "Show kitten"
}, {
"type": "postback",
"title": "I like this",
"payload": "User " + recipientId + " likes kitten " + imageUrl,
}]
}]
}
}
};
sendMessage(recipientId, message);
return true;
}
}
return false;
};
4. 조금 더해보기
더하기봇
더하기 봇 소스 #1
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));
// Server frontpage
app.get('/', function (req, res) {
res.send('This is TestBot Server');
});
app.get('/forecast', function (req, res) {
forecast.get([35.9335, 139.6181], function(err, weather) {
if(err) return console.dir(err);
console.dir(weather);
console.dir(weather.latitude);
console.log("weather.latitude " + weather.latitude);
console.log("오늘 " + weather.timezone + "의 날씨는 " + weather.currently.summary + "입니다. ");
});
res.send('forecast');
});
더하기 봇 소스 #2
// Facebook Webhook
app.get('/webhook', function (req, res) {
if (req.query['hub.verify_token'] === 'abcd_verify_token') {
res.send(req.query['hub.challenge']);
} else {
res.send('Invalid verify token');
}
});
// handler receiving messages
app.post('/webhook', function (req, res) {
var events = req.body.entry[0].messaging;
for (i = 0; i < events.length; i++) {
var event = events[i];
if (event.message && event.message.text) {
addMessage(event.sender.id, event.message.text);
}
}
res.sendStatus(200);
});
더하기 봇 소스 #3
// generic function sending messages
function sendMessage(recipientId, message) {
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
method: 'POST',
json: {
recipient: {id: recipientId},
message: message,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
};
function addMessage(recipientId, text) {
text = text || "";
var values = text.split(' ');
if (values.length === 3 && values[0] === 'add') {
if (Number(values[1]) > 0 && Number(values[2]) > 0) {
addText = values[1] + " + " + values[2] + " = " + (Number(values[1]) + Number(values[2]));
message = {text: addText};
sendMessage(recipientId, message);
}
}
};
FORECAST 설치
$ npm install --save forecast
날씨봇
https://darksky.net/dev/
FORECAST KEY
날씨앱 테스트
날씨 봇 소스 #1
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen((process.env.PORT || 3000));
var Forecast = require('forecast');
// Initialize
var forecast = new Forecast({
service: 'darksky',
key: ‘your-api-key‘,
units: 'celcius',
cache: true, // Cache API requests
ttl: {
minutes: 27,
seconds: 45
}
});
날씨 봇 소스 #2
// Server frontpage
app.get('/', function (req, res) {
res.send('This is TestBot Server');
});
app.get('/forecast', function (req, res) {
forecast.get([35.9335, 139.6181], function(err, weather) {
if(err) return console.dir(err);
console.dir(weather);
});
res.send('forecast');
});
// Facebook Webhook
app.get('/webhook', function (req, res) {
if (req.query['hub.verify_token'] === 'abcd_verify_token') {
res.send(req.query['hub.challenge']);
} else {
res.send('Invalid verify token');
}
});
날씨 봇 소스 #3
// handler receiving messages
app.post('/webhook', function (req, res) {
var events = req.body.entry[0].messaging;
for (i = 0; i < events.length; i++) {
var event = events[i];
if (event.message && event.message.text) {
weatherMessage(event.sender.id, event.message.text);
}
}
res.sendStatus(200);
});
// generic function sending messages
function sendMessage(recipientId, message) {
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
method: 'POST',
json: {
recipient: {id: recipientId},
message: message,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
};
날씨 봇 소스 #4
function weatherMessage(recipientId, text){
text = text || "";
var values = text.split(' ');
if (values[0] === '날씨') {
forecast.get([35.9335, 139.6181], function(err, weather) {
console.log(weather);
weatherText = "오늘 " + weather.timezone + "의 날씨는 " + weather.currently.summary + "입니다. ";
message = {text: weatherText};
sendMessage(recipientId, message);
});
}
}
더하기와 날씨봇을 확장해 보세요.
또 어떤걸 해보고 싶으신가요?
머신러닝, 자연어처리, 음성인식…
파이썬
https://github.com/snowkiwi/slack-python-bot-tutorial
소스는 이곳을 참고하세요.
노드
https://github.com/snowkiwi/facebook-node-bot
Q & A
수고하셨습니다. :)
ABCD
http://abcds.kr
https://www.facebook.com/groups/562787713823026/
한성일
https://www.facebook.com/jamie.han.16
iheart79@gmail.com

챗봇 시작해보기