8 분 소요

프로젝트 소개

:link: Github :link: ArmyBot 트위터 계정

“BTS 덕질하는 트위터 친구”라는 컨셉의 챗봇을 개발하고 서비스한 경험을 정리해 본다. 일상 대화는 물론 컨셉에 맞게 BTS 관련 정보를 물어보는 질문이나 BTS 관련 chitchat도 가능하게끔 훈련시켰으며, 간편하게 트위터 계정(“@armybot13”)으로 트윗을 보내면 사용이 가능하다.

시연

서비스 사용 예시

파이프라인

image

사용자가 우리 봇계정을 멘션하고 트윗을 보내면 악성 트윗인지 스팸필터가 확인하고, 악성 트윗으로 판단하면 완곡한 거절 메시지를 보낸다. 악성 트윗이 아니면 Elastic Search로 유저 메시지와 구축해 놓은 템플렛을 비교하여 BM25점수를 계산, 일정 점수 이상이면 해당 템플렛의 인텐트를 유저 메시지의 인텐트로 보고 템플렛에 맞는 답변을 만든다. 이 점수가 기준치보다 낮을 경우에는 T5 기반 생성모델로 답변을 생성한다. 유저의 인풋과 챗봇의 응답 등은 연결된 몽고DB에 저장한다.

기술 스택

  • selenium, beautifulsoup :point_right: 크롤링
  • regex, KoNLPy, Kiwi, datasets (HuggingFace) :point_right: 데이터 전처리, 형태소 분석 및 문장 분리, 데이터셋 공유
  • scikit-learn :point_right: 클러스터링 기반 중복 데이터 제거
  • tweepy, Twitter API v2.0 :point_right: 트위터 API 사용
  • Elastic Search :point_right: 템플렛 기반 답변 추출
  • transformers, Flax (Jax) :point_right: 생성모델 T5 추가 사전학습 및 파인튜닝

:bulb: 기획

BTS 덕질 트위터 챗봇이라는 기획은 예전부터 구상을 했던 아이디어로 처음 팀원을 모을 때부터 공유가 되었다. 애초에 파이널 프로젝트을 구상할 때 고려한 사항은 다음과 같다.

챗봇을 선택한 이유 :robot:

  • 실제로 유저들에게 서비스하고 피드백을 받을 수 있는 제품이어야 한다
  • 상품성이 있는 NLP 분야여야 한다
  • 팀원들부터 흥미를 갖고 개발할 수 있는 프로젝트여야 한다
  • 데이터 수집, 라벨링부터 해보고 싶다

기업에 취업하는 것을 목표로 하다보니 데이터를 모으고 언어모델을 훈련시키는 것뿐만 아니라 상품성을 고려해 서비스까지 하는 경험이 중요했다. 또 뭔가 중소기업 사장님 같은 말이지만 팀원들도 “내 프로젝트다”라는 마음으로 치열히 개발하고 꾸준히 개선할 수 있도록 구미가 당기는 프로젝트여야 했다. 작년에 KoGPT2를 기반으로 5대 일간지별 논조를 담은 사설 생성기를 만들었는데, 기획자인 나만 애정을 갖고 열심히 만들었던 경험이 있어 이번에는 팀원들과 이 프로젝트의 비전을 공유하는 것이 중요했다. 마지막으로 코퍼스 구축 및 데이터 라벨링을 해봐야 한다고 생각했다. 원래도 데이터는 다다익선이라고 했지만, 현재 헤드라인을 장악하고 있는 ChatGPT의 핵심이 고품질의 데이터이다 보니 데이터 제작 및 관리의 중요성을 날이 갈수록 중요해지고 있다. 챗봇을 만드면서 훈련데이터용 웹 데이터를 모으고 전처리를 많이 해 볼 수 있다고 생각했고 실제로도 정성을 많이 들였다.

트위터를 선택한 이유 :bird:

그래서 왜 트위터 챗봇을 만들었냐 하면

  • 타겟 유저(BTS, 아이돌 팬)가 애용하는 플랫폼이다
  • 데이터 수집이 용이하다
  • 한국어 트윗은 최대 140자이다
  • 응답 시간을 줄이기 위해 답변 품질을 포기하지 않아도 된다

해외에서는 학계 사람들부터 대통령까지 여러 분야의 전문가들이 실명으로 트위터를 운영하지만, 우리나라에서는 뭔가 비실명제로 덕질(팬질)하는 대표 플랫폼이 트위터이다. 즉 우리 서비스의 타겟 유저가 애용하는 플랫폼이기 때문에 우리 서비스를 홍보하고, 초기 사용자를 모으고, 데이터를 모으기에 가장 유리한 곳이 트위터였다. 프로젝트 기획이 아무리 좋아도 관련 데이터를 모으면 시작도 못하는 게 현실인데, 우리 프로젝트에 필요한 BTS 관련 팬들의 대화는 트위터 API로 쉽게 구할 수 있었다(물론 전처리는 또다른 문제…). 또 트위터가 한국어 트윗의 최대 글자수를 140자로 설정해 놓은 것도 서비스 개발에 용이했다. 언어모델은 인풋이 길면 길수록 이해도 어렵고 생성도 어려워지는데, 140자라는 제약이 있고 또 실제로 팬들끼리 대화는 짧기 때문에 언어모델을 훈련시키는 데 부담과 비용이 트위터 챗봇이 타플랫폼 기반 챗봇에 비해 적다. 또 트위터 사용 패턴상 트윗으로 대화가 이뤄지는 만큼 응답 속도를 높이기 위해 품질을 포기하지 않아도 된다는 장점도 있다. 웹페이지나 카톡으로 대화를 한다고 하면 화면이 고정되어 있기 때문에 답변이 바로바로 오지 않을 경우 바로 서비스를 이탈하게 된다. 그러나 트위터에서는 트윗을 보내놓고 다른 트윗을 확인하거나 어플을 끄기 때문에, 애초에 챗봇의 답변이 1초내로 올 거라는 기대가 없다. 요약하자면 현실적으로 우리가 구현할 수 있는 최대한의 챗봇을 서비스하기에 가장 좋은 플랫폼이 트위터이다.

:briefcase: 내 역할

서비스 기획 외에 PM, 깃헙 PR 관리/코드 리뷰, 네이버 기사/지식인 크롤링 및 전처리, 트위터 연결을 담당했다.

기사, 네이버 지식인 크롤링 및 전처리

수집 대상

우리 서비스는 트위터 봇게정이다 보니 K-Pop, BTS라는 도메인의 한국어 구어체 데이터를 제대로 이해하고 생성하는 것이 중요했다. 또한 BTS 멤버 이름 등 UNK 토큰으로 인코딩하면 안되는 단어들을 확보하고자 트위터는 당연하고 네이버 뉴스나 지식인, 더쿠와 같은 사이트에서 팬들의 실제 대화를 수집해야 했다. 역할을 나눠 나는 뉴스 기사와 지식인 데이터를 수집하고 전처리를 했다. 우선 사용한 생성모델(paust/pko-t5-base)이 뉴스나 위키 백과 등으로 학습이 되었으나, BTS 관련 지식을 주입하기 위해 BTS 관련 연예뉴스로 domain-adaptive pre-training을 하기로 했다. AiHub에서 구할 수 있는 데이터셋 대규모 웹데이터 기반 한국어 말뭉치 데이터 중에 BTS 관련 기사들만 추출했다. 해당 데이터셋이 2021년도에 구축되었기 때문에 최신 기사들을 모으기 위해 직접 네이버뉴스에서 BTS 관련 최신 기사들을 크롤링했다. 기사 외에도 BTS 관련 네이버 지식인 데이터도 수집했다. 이는 팬들이 BTS와 관련하여 많이 물어보는 질문과 답변을 파악하고 생성모델을 파인튜닝하는 데 사용하기 위해서였다.

클러스터링을 통한 중복 제거

BTS 관련 기사/지식인 데이터를 크롤링하고 전처리할 때 중복 데이터를 제거하기 위해 심혈을 기울였다. 특히 연예뉴스의 경우 통신사(연합뉴스)의 기사를 바탕으로 수십개의 언론사가 대동소이한 내용의 기사를 쓰고, 홍보성 뉴스도 많다보니 중복 기사를 제거하는 것이 핵심이었다. 우선 중복으로 판단하는 기준을 세워야 했는데, 한국어는 어미와 조사가 발달된 굴절어다 보니 영어에 비해 이 기준을 세우는 것도 매우 어려웠다. 일례로 T5 훈련에 쓰인 C4는 4개의 연속 (구두점이 있는) 문장이 겹칠 때 중복으로 보는데, 뉴스 기사의 경우 어미만 다른 경우가 많기 때문에 보다 구체적인 기준이 필요했다. 결국 기사들을 주제별로 클러스터링을 하기로 했다. 뉴스를 수집할 때부터, 네이버 자체적으로 주제별로 묶어놓은 기사 중의 대표 기사만을 수집했다.

image
네이버 자체적으로 주제별로 뉴스 기사를 클러스터링 한다

이렇게 해도 여전히 중복되는 내용의 기사들이 많았기 때문에 추가적으로 클러스터링을 해야 했다. 2차 클러스터링은 뉴스 제목을 scikit-learn의 TfidfVectorizer로 임베딩한 후 코사인 유사도를 계산했다. Tf-idf 벡터는 코퍼스의 최빈도 어휘들을 기반으로 만들어지는데 한국어 문장은 별도의 전처리 없이 어절 단위로 임베딩을 하면 “BTS는”, “BTS가”, “BTS” 등이 모두 다른 차원으로 매핑이 된다. 이를 방지하기 위해 기호 제거 후 Kiwi 형태소 분석기로 형태소 분석 후 임베딩을 했다. 또 “BTS”와 “bts”, “방탄소년단”을 다른 토큰으로 인식하는 것을 막고자 “방탄소년단”으로 표준화를 했다. 또 같은 주제의 (홍보성) 기사들이 같은 날 발행될 확률이 높아, 기사 작성일 기준으로 하루 이내인 기사면 위에서 계산한 코사인 유사도에 1.5, 하루 초과면 0.8의 가중치를 곱해줬다. 이렇게 중복을 제거하면 데이터 양이 대략 85% 정도 감소한다.

노이즈 제거

우리 챗봇 서비스에 인풋으로 들어오지 않을 문장들을 노이즈로 보고 제거했다.

  • 네이버 뉴스 주로 한문단으로 이뤄진 포토/영상 뉴스 등은 수집하지 않으며, 기자명, 언론사명, 이미지 설명 외에 관련 뉴스 추천 및 제보 요청 문장들도 노이즈로 제거했다.
  • 지식인 지식인에서도 사진이나 영상의 출처를 물어보는 질문 등은 수집하지 않았으며, 수집한 질의응답쌍에서도 “답변 채택 부탁드립니다”, “답변 시 내공 100 드림” 등의 문장들은 추가로 제거했다.

트위터 API 연결

서비스 파이프라인을 처음 만들 때는 팀원이 만든 트위터 API 연결 모듈을 그대로 사용했다. 그런데 해당 모듈의 코드가 예전 버전의 tweepy를 사용할 뿐만 아니라 트위터 API 1.1버전을 바탕으로 만들어졌기 때문에 기능을 추가하려고 할 때마다 예전 버전의 reference를 찾아야 했다. 애초에 서비스를 계속 유지하고 개선하려면 최신 tweepy 버전(4.0 이상)과 트위터 API 2.0으로 업그레이드 해야 한다고 생각하여 업그레이드를 담당하였다. 확실히 2.0 버전이 직관적이고, 무엇보다 내가 직접 새로 구현하다 보니 새 기능을 추가할 때 어떤 메타데이터가 필요한지 또 해당 데이터를 어떻게 구할 수 있는지 알게되어 서비스를 확장하는데 자신이 생겼다.

PM

원래 팀을 구성할 때부터 각자도생하지 말고, 모두가 모든 과정을 같이 해보자라는 합의를 했기 때문에 따로 PM을 정하지 않았다가, 중반쯤 급하게 PM을 정하게 되었고 서비스 기획자인 내가 PM을 맡게 되었다. 솔직히 말하자면 PM이라는 자리가 요구하는 책임을 제대로 하지 못했다. 이번에 배운 PM의 책임과 이와 관련하여 내 부족함을 반추해 본다.

일정 관리 :calendar:

박장원(monologg) 멘토님은 프로젝트 진척사항을 논의할 때마다 일정이 얼마나 걸릴 것 같은지, 해당 일정 안에 할 수 있을지 물어봤다. 개발을 천년 만년할 수는 없기 때문에 데드라인을 정하는 것은 당연하다. 내가 어려웠던 것은 어떤 기능을 추가할 때마다 얼마나 걸릴지 견적을 내는 것이었다. 데이터는 얼마나 모을 수 있을지, 전처리하는 데는 얼마나 걸릴지, 훈련시간은 대략 얼마나 걸릴지, 우리 팀의 실력은 얼마나 되는지 등을 제대로 파악을 해야 한다. 즉 다양한 프로젝트를 해 본 경험이 있어야 견적을 낼 수가 있다.
관련하여 최소기능제품(MVP)의 중요성을 체감하였다. 이루다 개발자도 비슷한 조언을 했는데, 일단 end-to-end로 제대로 돌아가는 파이프라인을 만들어 놔야 어떤 부분을 개선시키고 또 개선을 위해 어떤 데이터를 모아야 하는지 구체적인 논의가 가능하다

팀원들과 소통 :speech_balloon:

이번 프로젝트를 하며 내가 가장 부족하다고 느꼈던 부분이다. 원활하게 “팀웍”이 이뤄지려면 거시적으로는 우리 프로젝트의 방향성을, 챗봇 시스템을 어떻게 구현해야 하는지 비전을 공유하고 미시적으로는 팀원마다 해야할 일이 무엇인지, 왜 그 일을 해야하는지 확실히 짚고 넘어가야 한다. 그런데 나는 어떤 기능을 추가할지만 고민했고 어떻게 구현할지, 즉 챗봇의 구성요소는 무엇이 있고 어떤 난제가 있을지 등은 고민하지 않았기 때문에 팀원들에게 전반적인 로드맵을 제시하지 못했다. 챗봇을 만든다고 하면 응당 인텐트 분류와 개체명 인식을 어떻게 할지 긴시간 논의를 했어야 했는데, 그냥 목적없이 데이터만 모았던 것 같다. 뒤늦게 챗봇의 기본 구조와 구성요소등을 공부하고 팀원들에게도 큰 그림을 그려주려고 나름 노력했다. 어떻게 챗봇을 만들어야 하는지 글과 동영상 링크를 공유하고 우리도 이런 방향으로 개선해야 한다고 여러번 말은 했는데… 구차한 변명을 하자면 내가 경험이 많은 멘토도 아니고, 같은 부스트코스 수강생의 입장에서 이걸 꼭 읽어라, 저걸 어떻게든 구현을 해라 말을 할 처지인가 싶었다. 이렇게 큰 그림을 같이 그리지 못하다보니 지금 우리가 하고 있는 작업이 무엇을 위한 작업인지 계속 묻는 팀원도 있었고 동기부여가 제대로 되지 못한 팀원도 있었던 것 같다. 그래서 앞으로 서비스를 개선할 때에는 모듈별로 하는 기능이 무엇인지 또 해당 기능을 제대로 실행하려면 어떤 식으로 코드를 구현해야 하는지 등을 확실하게 미리 짚어보기로 했다.

코드 리뷰 :computer:

팀원과의 소통과도 연결된 부분이다. PM으로서 프로젝트의 전체적인 진척사항을 확인하고 팀원별로 진행할 작업을 분배하려면 나도 팀원들의 코드를 파악해야 했다. 또 프로젝트 레포의 PR 검토도 내가 하다보니 전반적인 코드리뷰도 해야 했다. 처음에는 내가 맡은 일(네이버 기사 수집 및 전처리)에만 집중하고 싶고 방해물로만 여겨졌는데, 억지로라도 팀원들의 코드들을 본 게 전체적인 구조 파악에 도움이 되었다.

:book: 소감 및 배운 점

데이터 전처리의 중요성

AI 개발할 때 모델보다 데이터 구축하고 정제하는 데 시간이 배로 든다는 말은 여러번 들었지만, 이번 프로젝트로 제대로 체감했다. 프로젝트 기간의 절반 이상을 데이터 모으고 전처리 하는 데 썼다. 일례로 뉴스 기사에서 각종 노이즈를 제거하기 위해서 며칠 동안 십여개의 정규표현식을 짰다가 결국엔 다 버리고 어말어미 ‘-다.’로 끝나는 스트링을 노이즈가 아닌 문장으로 보는 정규표현식 하나로 귀결됐다. 서비스가 다룰 데이터가 주로 구어체 대화다 보니 띄어쓰기나 맞춤법이 제대로 갖춰진 경우가 거의 없었다. 또 공개된 관련 라이브러리도 주로 기사로 훈련되었다보니 구어체 데이터에서는 성능이 제대로 나오지 않았다. 그래서 이번 프로젝트로 수집한 데이터로 한국어 구어체 텍스트에 특화된 띄어쓰기 라이브러리를 만들어 볼 계획이다.

청사진의 필요성

멘토님들은 BTS 관련 트위터 챗봇이라는 기획을 많이 칭찬해 주셨고, 또 계획 그대로 파이프라인이 완성되어 뿌듯하다. 그런데 디테일적인 면에서 아쉬움이 많다. 특히 챗봇의 핵심이라고 할 수 있는 intent classification과 entity recognition 부분을 세련되게 하지 못해 아쉽고 가장 먼저 개선할 예정이다. 프로젝트 초반에 이루다 및 다른 챗봇 서비스의 구조에 대해서 팀원들과 세미나를 열기는 했지만 정확히 어떻게 챗봇이 이뤄지는지 공부하지 않았다가 중반부가 되서야 아차 싶었다. 앞으로는 우선 end-to-end 파이프라인(MVP)을 만들고, 파이프라인의 각 부분부분을 어떻게 구성할지 꼼꼼히 공부하고 미리 청사진을 그려보는 습관을 체화하고자 한다.

업데이트: