Heroku를 활용한 카카오챗봇 배포 - 응용편

Page content

읽기 전 공지

  • 본 글은 2022년 11월 28일까지만 유효합니다. 무료 버전이 사라지기 때문에, 앞으로 어떻게 될지는 현재 글 쓰는 시점에서는 모릅니다. 이 부분에 주의해서 참고 하시기를 바랍니다.

강의 홍보

개요

  • Flask를 활용하여 챗봇을 구현한다.

사전준비

사칙연산 구현

  • 사칙연산을 구현하기 위해서는 기존에서 배웠던 내용에서 엔티티를 구성하는 코드를 작성해야 한다.
  • 엔티티(Entity)란 봇이 이해할 수 있는 용어를 체계적으로 정리한 데이터 사전을 말한다.
  • 엔티티 구조는 크게 엔티티명, 대표 엔트리, 동의어 총 세 가지 요소로 구성된다.
  • 엔티티의 자세한 설명은 다음 링크에서 확인한다.
  • 사칙 연산을 예로 들면 아래와 같이 지정할 수 있다.
    • division, subtraction 등은 대표 엔트리를 말한다.
    • 동의어에 해당하는 값이 나오면 추후에 확인할 로그 값에는 대표 엔트리만 별도로 데이터를 수집할 수 있다.

(1) 엔티티 구성

  • 엔티티 구성에 대해 자세히 알고 싶다면 구체적인 도움말을 참조한다.
  • 우측 상단에 엔티티 버튼을 클릭한다.

Untitled

  • 우선 사칙연산에 해당하는 엔티티를 구성하도록 한다.
    • 우선 나의 엔티티 관리에서 operators 이름 하에 대표 엔티티 4개 (addition, subtraction, multiplication, division)로 구성한다.

Untitled

Untitled

  • 이번에는 시스템 엔티티에서 필요한 요소들을 확인한다. 만약 비활성화가 되어 있다면, 활성화를 해준다.

Untitled

(2) 사칙 연산 계산기 코드 구현

  • 다음과 같이 app.py를 수정한다.
# -*- coding: utf-8 -*-
from flask import Flask, request
import pandas as pd 
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
import json

## DB 연결 Local
def db_create():
	# Heroku
    engine = create_engine("postgresql://your_url", echo = False)

    engine.connect()
    engine.execute("""
        CREATE TABLE IF NOT EXISTS iris(
            sepal_length FLOAT NOT NULL,
            sepal_width FLOAT NOT NULL,
            pepal_length FLOAT NOT NULL,
            pepal_width FLOAT NOT NULL,
            species VARCHAR(100) NOT NULL
        );"""
    )
    data = pd.read_csv('data/iris.csv')
    print(data)
    data.to_sql(name='iris', con=engine, schema = 'public', if_exists='replace', index=False)

## 메인 로직!! 
def cals(opt_operator, number01, number02):
    if opt_operator == "addition":
        return number01 + number02
    elif opt_operator == "subtraction": 
        return number01 - number02
    elif opt_operator == "multiplication":
        return number01 * number02
    elif opt_operator == "division":
        return number01 / number02

application = Flask(__name__)

@application.route("/")
def index():
    db_create()
    return "DB Created Done !!!!!!!!!!!!!!!"

## 카카오톡 텍스트형 응답
@application.route('/api/sayHello', methods=['POST'])
def sayHello():
    body = request.get_json()
    print(body)
    print(body['userRequest']['utterance'])

    responseBody = {
        "version": "2.0",
        "template": {
            "outputs": [
                {
                    "simpleText": {
                        "text": "안녕 hello I'm Ryan"
                    }
                }
            ]
        }
    }

    return responseBody

## 카카오톡 이미지형 응답
@application.route('/api/showHello', methods=['POST'])
def showHello():
    body = request.get_json()
    print(body)
    print(body['userRequest']['utterance'])

    responseBody = {
        "version": "2.0",
        "template": {
            "outputs": [
                {
                    "simpleImage": {
                        "imageUrl": "https://t1.daumcdn.net/friends/prod/category/M001_friends_ryan2.jpg",
                        "altText": "hello I'm Ryan"
                    }
                }
            ]
        }
    }

    return responseBody

## 카카오톡 Calculator 계산기 응답
@application.route('/api/calCulator', methods=['POST'])
def calCulator():
    body = request.get_json()
    print(body)
    params_df = body['action']['params']
    print(type(params_df))
    opt_operator = params_df['operators']
    number01 = json.loads(params_df['sys_number01'])['amount']
    number02 = json.loads(params_df['sys_number02'])['amount']

    print(opt_operator, type(opt_operator), number01, type(number01))

    answer_text = str(cals(opt_operator, number01, number02))

    responseBody = {
        "version": "2.0",
        "template": {
            "outputs": [
                {
                    "simpleText": {
                        "text": answer_text
                    }
                }
            ]
        }
    }

    return responseBody

if __name__ == "__main__":
    db_create()
    application.run()
  • Heroku에 배포까지 진행한다.
git add .
git commit -m "updated"
git push && git push heroku main
  • 배포 진행 후, 웹사이트가 열리는지 반드시 확인해야 한다.

Untitled

(3) 스킬 서버 등록

  • 기 작성된 코드에서 스킬 서버 등록을 저장 후, 아래 그림 처럼 API 를 호출한다.

Untitled

(4) 시나리오 작성

  • 사칙 연산 계산기 시나리오를 작성한다.
  • 패턴 발화에서 엔티티를 검색해서 하나씩 추가한다.

Untitled

  • 엔티티 구성 중 operators 는 사용자가 직접 설정한 것을 말한다.

Untitled

  • 또다른 발화를 만들어 보자.

Untitled

  • 패턴 발화 입력이 종료되었다면, 파라미터 설정 및 봇 응답을 추가하도록 한다.

Untitled

  • 이 때, 중요한 것은 일반 파라미터의 값과 아래 코드의 값이 일치해야 계산이 된다.
...
def calCulator():
    body = request.get_json()
    print(body)
    params_df = body['action']['params']
    print(type(params_df))
    opt_operator = params_df['operators']
    number01 = json.loads(params_df['sys_number01'])['amount']
    number02 = json.loads(params_df['sys_number02'])['amount']

    print(opt_operator, type(opt_operator), number01, type(number01))

...

카카오 챗봇 배포

  • 여기까지 진행했다면 배포를 진행한다.

Untitled

  • 배포가 완료가 되면 테스트를 진행하도록 한다.

Untitled

로그확인

  • 프로젝트 터미널에서 로그를 확인하도록 한다.
    • 명령어 : heroku logs
$ heroku logs
 »   Warning: heroku update available from 7.53.0 to 7.66.0.
2022-11-10T03:47:05.521773+00:00 app[web.1]: [150 rows x 5 columns]
...
2022-11-10T06:07:47.811023+00:00 heroku[web.1]: State changed from starting to up2022-11-10T06:07:50.891532+00:00 app[web.1]: {'bot': {'id': '62f2f859fb4d7520b2bb5efb!', 'name': 'humanchatbot'}, 'intent': {'id': '636c8899e748f261c9b11bb8', 'name': '사칙 연산 계산기', 'extra': {'reason': {'code': 1, 'message': 'OK'}}}, 'action': {'id': '636c88d61a94d93e86de3835', 'name': '사칙연산 로직', 'params': {'sys_number': '{"amount": 1, "unit": null}', 'operators': 'addition', 'sys_number1': 
'{"amount": 1, "unit": null}'}, 'detailParams': {'sys_number': {'groupName': '', 
'origin': '1', 'value': '{"amount": 1, "unit": null}'}, 'operators': {'groupName': '', 'origin': '+', 'value': 'addition'}, 'sys_number1': {'groupName': '', 'origin': '1', 'value': '{"amount": 1, "unit": null}'}}, 'clientExtra': {}}, 'userRequest': {'block': {'id': '636c8899e748f261c9b11bb8', 'name': '사칙 연산 계산기'}, 'user': {'id': 'c7f6ce97f0103d79f92cc0a791663ff973fecbb7c3dbc9b0268aa017be9df71d1d', 'type': 'botUserKey', 'properties': {'botUserKey': 'c7f6ce97f0103d79f92cc0a791663ff973fecbb7c3dbc9b0268aa017be9df71d1d', 'bot_user_key': 'c7f6ce97f0103d79f92cc0a791663ff973fecbb7c3dbc9b0268aa017be9df71d1d'}}, 'utterance': '1+1\n', 'params': {'surface': 'BuilderBotTest', 'ignoreMe': 'true'}, 'lang': 'kr', 'timezone': 'Asia/Seoul'}, 'contexts': []}
2022-11-10T06:07:50.891553+00:00 app[web.1]: <class 'dict'>
2022-11-10T06:07:50.892548+00:00 app[web.1]: [2022-11-10 06:07:50,891] ERROR in app: Exception on /api/calCulator [POST]
2022-11-10T06:07:50.892549+00:00 app[web.1]: Traceback (most recent call last):  
...
2022-11-10T06:13:58.462055+00:00 app[web.1]: {'bot': {'id': '62f2f859fb4d7520b2bb5efb!', 'name': 'humanchatbot'}, 'intent': {'id': '636c8899e748f261c9b11bb8', 'name': '사칙 연산 계산기', 'extra': {'reason': {'code': 1, 'message': 'OK'}}}, 'action': {'id': '636c88d61a94d93e86de3835', 'name': '사칙연산 로직', 'params': {'sys_number01': '{"amount": 1, "unit": null}', 'operators': 'addition', 'sys_number02': '{"amount": 1, "unit": null}'}, 'detailParams': {'sys_number01': {'groupName': '', 'origin': '1', 'value': '{"amount": 1, "unit": null}'}, 'operators': {'groupName': '', 'origin': '+', 'value': 'addition'}, 'sys_number02': {'groupName': '', 'origin': '1', 'value': '{"amount": 1, "unit": null}'}}, 'clientExtra': {}}, 'userRequest': {'block': {'id': '636c8899e748f261c9b11bb8', 'name': '사칙 연산 계산 
기'}, 'user': {'id': 'c7f6ce97f0103d79f92cc0a791663ff973fecbb7c3dbc9b0268aa017be9df71d1d', 'type': 'botUserKey', 'properties': {'botUserKey': 'c7f6ce97f0103d79f92cc0a791663ff973fecbb7c3dbc9b0268aa017be9df71d1d', 'bot_user_key': 'c7f6ce97f0103d79f92cc0a791663ff973fecbb7c3dbc9b0268aa017be9df71d1d'}}, 'utterance': '1 + 1\n', 
'params': {'surface': 'BuilderBotTest', 'ignoreMe': 'true'}, 'lang': 'kr', 'timezone': 'Asia/Seoul'}, 'contexts': []}
2022-11-10T06:13:58.462129+00:00 app[web.1]: <class 'dict'>
2022-11-10T06:13:58.462242+00:00 app[web.1]: addition <class 'str'> 1 <class 'int'>
2022-11-10T06:13:58.463445+00:00 app[web.1]: 10.1.18.199 - - [10/Nov/2022:06:13:58 +0000] "POST /api/calCulator HTTP/1.1" 200 71 "-" "AHC/2.1"
2022-11-10T06:13:58.471918+00:00 heroku[router]: at=info method=POST path="/api/calCulator" host=human-cal-evan.herokuapp.com request_id=c9f33c50769b93d5e1bf320072120fba fwd="219.249.231.41" dyno=web.1 connect=0ms service=3ms status=200 bytes=216 protocol=https
2022-11-10T06:14:10.289581+00:00 heroku[router]: at=info method=POST path="/api/calCulator" host=human-cal-evan.herokuapp.com request_id=90f766a0a82ca64b263e875db0308666 fwd="219.249.231.41" dyno=web.1 connect=0ms service=5ms status=200 bytes=217 protocol=https
2022-11-10T06:14:10.290817+00:00 app[web.1]: {'bot': {'id': '62f2f859fb4d7520b2bb5efb!', 'name': 'humanchatbot'}, 'intent': {'id': '636c8899e748f261c9b11bb8', 'name': '사칙 연산 계산기', 'extra': {'reason': {'code': 1, 'message': 'OK'}}}, 'action': {'id': '636c88d61a94d93e86de3835', 'name': '사칙연산 로직', 'params': {'sys_number01': '{"amount": 5, "unit": null}', 'operators': 'multiplication', 'sys_nu(venv)
 "POST /api/calCulator HTTP/1.1" 200 72 "-" "AHC/2.1"
(venv) 
h@DESKTOP-NH6KA0O MINGW64 ~/Desktop/human-cal-evan (main)
$