반응형

0. 들어가기

-. 이번 포스팅에선 카카오챗봇과 API 서버 (이 글에서는 앞서 포스팅한 FLASK를 이용한다)의 연동을 하여 조금 더 자유로운 챗봇 출력을 해본다. 

-. FLASK를 이용한 다양한 (글, 사진, etc.) 챗봇 출력 해보기. discord 챗봇과 매우 유사한 구조를 가진다. 차이는 카톡은 유료라는것..

1. 카카오챗봇에 API 서버 (SKILL) 연동하기 흐름도

-. 카카오챗봇은 api 서버를 거치는 응답 출력을 SKILL이라는 용어로 제공한다. 챗봇이 사용하는 스킬이라는 의미 같은데... 이름 참 재밌게 지었다고 생각한다. (내가 이해하기론) 앞의 포스팅에 첨부한 흐름도에서 출력 단을 API서버에 의존하는 방식이다.

2. 챗봇 → API 서버 parameter 전달

-. 챗봇과 서버는 POST 방식으로 통신을 한다. 챗봇에서 서버로 POST 방식으로 request를 날리면 그에 대해 서버에서 응답을 하면 된다. 

-. 챗봇 관리창에서 스킬 탭을 누르면 챗봇이 보유한 스킬 목록을 볼 수 있다.  

 

-. 스킬 응답을 위한  API 서버 설정은 매우 간단한데, 통신할 서버의 url(서비스봇, 테스트봇 각각)을 입력하면 끝난다. 친절하게도, 테스트용, 서비스용 서버를 동시에 설정할 수 있게 해줘서, 봇 응답 테스트를 실시간으로 할 수 있게 해준다. 전송 시 파라미터 헤더의 키/value 설정을 할 수 있는데, 아마 스킬서버에 요청할 응답의 종류 (뒤에 다룰 text응답, 사진응답 등)를 기재하기 위한 용도로 보인다.

-. 이후 아래로 내려가면 API 서버로 전송할 POST parameter의 예시값을 보여주고, 아래에 있는 "스킬서버로 전송" 버튼을 누르면 그대로 서버로 전송된다.

#카톡봇 payloads 샘플 확인
payloads = request.get_json()
pprint.pprint(payloads)

---->
{'action': {'clientExtra': None,
            'detailParams': {'key1': {'groupName': '',
                                      'origin': 'value1',
                                      'value': 'value1'}},
            'id': '----',
            'name': 'dxiadl3nro',
            'params': {'key1': 'value1'}},
 'bot': {'id': '----', 'name': '봇 이름'},
 'intent': {'id': '----', 'name': '블록 이름'},
 'userRequest': {'block': {'id': 'o4m9niud3z97dg1paozenaca', 'name': '블록 이름'},
                 'lang': None,
                 'params': {'ignoreMe': 'true'},
                 'timezone': 'Asia/Seoul',
                 'user': {'id': '158603',
                          'properties': {},
                          'type': 'accountId'},
                 'utterance': '발화 내용'}}

-. 위의 과정을 거쳐 스킬 파라미터가 서버로 원활하게 전달되는 것을 확인했다면, 해당 스킬을 카톡 챗봇에 연결해줘야 한다. 다시 시나리오로 돌아가서, 방금 설정한 스킬을 선택하고, 봇 응답을 "스킬데이터 사용"으로 설정해 준다.

-. 이후 카톡 챗봇 테스트를 시작하면, 해당 발화 내용을 포함한 파라미터가 서버로 날아가는 것을 확인할 수 있다.

#카톡봇 실제 출력 payloads 확인
payloads = request.get_json()
pprint.pprint(payloads)

---->
{'action': {'clientExtra': {},
            'detailParams': {'coffee_name': {'groupName': '',
                                             'origin': '라떼', #엔트리 해당 입력단어
                                             'value': '카페라떼' #대표 엔트리},
                             'number': {'groupName': '',
                                        'origin': '2', #엔트리 해당 입력단어
                                        'value': '{"amount": 2, "unit": null}' #대표 엔트리},
                             'suffix_order': {'groupName': '',
                                              'origin': '주세요', #엔트리 해당 입력단어
                                              'value': '주세요' #대표 엔트리}},
            'id': '61b33e07cf36345c835ba69f',
            'name': 'skill1',
            'params': {'coffee_name': '카페라떼', #각 파라미터 대표 엔트리
                       'number': '{"amount": 2, "unit": null}',
                       'suffix_order': '주세요'}},
 'bot': {'id': '----!', 'name': '챗봇1'},
 'contexts': [],
 'intent': {'extra': {'reason': {'code': 0, 'message': 'OK'}},
            'id': '----',
            'name': '커피 주문하기'}, #시나리오 네임

 'userRequest': {'block': {'id': '----', 'name': '커피 주문하기'},
                 'lang': 'kr',
                 'params': {'ignoreMe': 'true', 'surface': 'BuilderBotTest'},
                 'timezone': 'Asia/Seoul',
                 'user': {'id': '----',
                          'properties': {'botUserKey': '----',
                                         'bot_user_key': '----'},
                          'type': 'botUserKey'},
                 'utterance': '커피 주세요\n'}} #사용자 입력 발화

-. 앞의 포스트에서 내가 곤란해 했던, "대표 엔트리가 아니라 입력 단어가 출력되는" 현상을 해결할 방법이 보인다. 위의 payload에서 입력한 단어 '라떼'의 대표 엔트리에 해당하는 '카페라떼'를 출력하도록 API 응답을 설정하면 되는 것이다.

 

3. API 서버 → 챗봇에 응답 보내기

-. 카톡 챗봇을 위한 API 서버 응답은 카톡 챗봇 도움말에 정리되어 있다. 예~~ 전에 (대략 2년 전에) 카톡 비즈니스 채널을 써보려고 했었는데, 그땐 OBT라 개인은 접근이 되지 않았고, 2018. 12. 03 기준으로 OBT 시작하면서 일반 유저도 접근이 가능해 진 것 같다. 동시에, 해당 시점부터 오픈빌더를 이용한 식당 예약 등 서비스가 활성화되기 시작한 것으로 생각된다. 

-. 암튼, 현재의 카톡 API v2 기준으로는 아래와 같은 형태의 응답을 구성하면 되는 것 같다.

        if method == "POST":
            # payloads = request.get_json()
            # pprint.pprint(payloads)
            _ret = {"version": "2.0",
                    "template": {"outputs": [{"simpleText": {"text": "hello"}}] #"template"의 "outputs" 키 내에 
                                 }
                    }

            # pprint.pprint(_ret)
            return jsonify(_ret), 200

-. 위의 코드대로 응답을 보내게 API 서버를 설정하고, 카톡 챗봇 응답을 "스킬데이터 사용"으로 설정하면, 챗봇이 아래와 같은 답을 보낸다.

-. 이제, 위의 스킬을 배포하고 실제 챗봇에서 태스트해보면 위와 동일하게 출력되는 것을 볼 수 있다.

-. 스킬 API 서버가 정상 작동하는 것을 확인했으니, 이제 내가 의도한 "동의어 엔티티 입력하여 대표 엔티티를 응답으로 출력하기" 를 할 수 있다.

        if method == "POST":
            payloads = request.get_json()
            _string = f"{payloads['action']['params']['coffee_name']} " \
                      f"{json.loads(payloads['action']['params']['number'])['amount']}잔 주세요"
            # print(_string)
            # pprint.pprint(payloads)
            _ret = {"version": "2.0",
                    "template": {"outputs": [{"simpleText": {"text": _string}}] #"template"의 "outputs" 키 내에
                                 }
                    }

            # pprint.pprint(_ret)
            return jsonify(_ret), 200

-. 위와 같이 코드를 입력하면, "카페라떼에 대한 대표 엔티티" 만이 아니라, "숫자에 대한 대표 엔티티"도 사용 가능하여, 커피 잔 수를 단순히 숫자 응답만이 아니라 문자 (ex. '열 잔') 에도 대응이 가능해졌다.

-. 여기까지 작업한 git link

728x90
반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기