[처음 배우는 딥러닝 챗봇] Python을 이용한 딥러닝 챗봇 제작기 (7)

챗봇 API 서버 구현
지금까지 만든 챗봇 엔진을 카카오톡이나 네이버톡톡에서 사용할 수 있도록 챗봇 API 서버를 구현해보자. 카카오톡이나 네이버톡톡과 챗봇 엔진이 통신하기 위해서는 REST API 방식으로 챗봇 서버를 구현해야 한다. 이 때 REST API는 웹 상에서 호출할 수 있도록 웹 어플리케이션 형태로 만들어야 하므로 Flask를 사용한다.
이제 챗봇 API 서버를 구현한다. /chatbot_api 디렉터리를 생성하고 이 디렉터리에 app.py 파일을 생성하여 다음과 같이 코드를 작성한다.
from flask import Flask, request, jsonify, abort
import socket
import json
# 챗봇 엔진 서버 접속 정보
host = "127.0.0.1" # 챗봇 엔진 서버 IP 주소
port = 5050 # 챗봇 엔진 서버 통신 포트
# Flask 어플리케이션
app = Flask(__name__)
# 챗봇 서버와 통신
def get_answer_from_engine(bottype, query):
# 챗봇 엔진 서버 연결
mySocket = socket.socket()
mySocket.connect((host, port))
# 챗봇 엔진 질의 요청
json_data = {
'Query': query,
'BotType': bottype
}
message = json.dumps(json_data)
mySocket.send(message.encode())
# 챗봇 엔진 답변 출력
data = mySocket.recv(2048).decode()
ret_data = json.loads(data)
# 챗봇 엔진 서버 연결 소켓 닫기
mySocket.close()
return ret_data
# 챗봇 엔진 query 전송 API
@app.route('/query/<bot_type>', methods=['POST'])
def query(bot_type):
body = request.get_json()
try:
if bot_type == 'TEST':
# 챗봇 API 테스트
ret = get_answer_from_engine(bottype=bot_type, query=body['query'])
return jsonify(ret)
elif bot_type == "KAKAO":
# 카카오톡 처리
pass
elif bot_type == "NAVER":
# 네이버톡톡 처리
pass
else:
# 정의되지 않은 bot type인 경우 404 오류
abort(404)
except Exception as ex:
# 오류 발생시 500 오류
abort(500)
if __name__ == '__main__':
app.run()
카카오톡과 네이버톡톡을 처리하는 부분은 과정을 나누기 위해 일단 구현하지 않았다.
챗봇 API 서버에 카카오톡 연동
챗봇 API 서버와 카카오톡을 연동하기 위해 API 서버 프로토콜을 정의해야 한다. 이 때 프로토콜을 카카오톡에서는 스킬이라고 부른다.
카카오 스킬 템플릿을 생성하는 모듈을 구현한다. /chatbot_api 디렉터리에 KakaoTemplate.py 파일을 생성하여 다음과 같이 코드를 작성한다.
class KakaoTemplate:
def __init__(self):
# 템플릿 버전
self.version = "2.0"
# 단순 텍스트 출력 요소
def simpleTextComponent(self, text):
return {
"simpleText": {"text": text}
}
# 단순 이미지 출력 요소
def simpleImageComponent(self, imageUrl, altText):
return {
"simpleImage": {"imageUrl": imageUrl, "altText": altText}
}
# 사용자에게 응답 스킬 전송
def send_response(self, bot_resp):
responseBody = {
"version": self.version,
"template": {
"outputs": []
}
}
# 이미지 답변이 텍스트 답변보다 먼저 출력됨
# 이미지 답변이 있는 경우
if bot_resp['AnswerImageUrl'] is not None:
responseBody['template']['outputs'].append(
self.simpleImageComponent(bot_resp['AnswerImageUrl'], ''))
# 텍스트 답변이 있는 경우
if bot_resp['Answer'] is not None:
responseBody['template']['outputs'].append(
self.simpleTextComponent(bot_resp['Answer']))
return responseBody
또한 기존에 생성했던 /chatbot_api/app.py 파일에 카카오톡 스킬 처리 부분을 추가한다.
# 카카오톡 처리
body = request.get_json()
utterance = body['userRequest']['utterance']
ret = get_answer_from_engine(bottype=bot_type, query=utterance)
from KakaoTemplate import KakaoTemplate
skillTemplate = KakaoTemplate()
return skillTemplate.send_response(ret)
챗봇 API 서버에 네이버톡톡 연동
카카오톡과 마찬가지로, 챗봇 API 서버와 네이버톡톡을 연동하기 위해 API 서버 프로토콜을 정의해야 한다.
네이버톡톡 응답 이벤트를 생성하는 모듈을 구현한다. /chatbot_api 디렉터리에 NaverEvent.py 파일을 생성하여 다음과 같이 코드를 작성한다.
import requests, json
class NaverEvent:
def __init__(self, authorization):
self.authorization_key = authorization
# 텍스트 컨텐트 출력 요소
def textContentComponent(self, text):
return {
"textContent": {
"text": text
}
}
# 이미지 컨텐트 출력 요소
def imageContentComponent(self, imageUrl):
return {
"imageContent": {
"imageUrl": imageUrl
}
}
# 보내기 API로 메시지 전송
def send_message(self, user_key, component):
headers = {
'Content-Type': 'application/json;charset=UTF-8',
'Authorization': self.authorization_key,
}
data = {
"event": "send",
"user": user_key,
}
data.update(component)
# 보내기 API 호출
message = json.dumps(data) # JSON 문자열 변경
return requests.post(
'https://gq.talk.naver.com/chatbot/v1/event',
headers=headers,
data=message)
# 사용자에게 응답 전송
def send_response(self, dst_user_key, bot_resp):
# 이미지 답변이 텍스트 답변보다 먼저 출력됨
# 이미지 답변이 있는 경우
if bot_resp['AnswerImageUrl'] is not None:
image = self.imageContentComponent(bot_resp['AnswerImageUrl'])
self.send_message(user_key=dst_user_key, component=image)
# 텍스트 답변이 있는 경우
if bot_resp['Answer'] is not None:
text = self.textContentComponent(bot_resp['Answer'])
self.send_message(user_key=dst_user_key, component=text)
return json.dumps({}), 200
또한 기존에 생성했던 /chatbot_api/app.py 파일에 네이버톡톡 이벤트 처리 부분을 추가한다.
# 네이버톡톡 처리
body = request.get_json()
user_key = body['user']
event = body['event']
from NaverEvent import NaverEvent
authorization_key = '<보내기 API 인증키>'
naverEvent = NaverEvent(authorization_key)
if event == "open":
# 사용자가 채팅방에 들어왔을 때 처리
print("채팅방에 유저가 들어왔습니다.")
return json.dumps({}), 200
elif event == "leave":
# 사용자가 채팅방에서 나갔을 때 처리
print("채팅방에서 유저가 나갔습니다.")
return json.dumps({}), 200
elif event == "send":
# 사용자가 챗봇에 send 이벤트를 전송했을 때
user_text = body['textContent']['text']
ret = get_answer_from_engine(bottype=bot_type, query=user_text)
return naverEvent.send_response(user_key, ret)
출처
조경래 님이 집필하신 처음 배우는 딥러닝 챗봇 교재를 참고하여 글을 작성하였다.
예제 또한 저자 분의 Github 에서 발췌하였다.
Leave a comment