이제 본격적으로 내가 원하는 "나와 대화할 수 있는 봇" 만들기에 도전해보려고 한다.
제일 먼저 떠오른 대화의 시작 문장은 "야, 뭐해?" 이다.
우선 이 문장을 다음과 같이 분석해보았다.
"야," => 독립어(호격)
"뭐해?" = "무엇을 해?" => 목적어 + 서술어
"야," 를 독립어로 처리한 후 호격으로 받아들이는 것은 간단하게 아이디어가 떠올랐지만,,
도저히 저 "뭐해?" 를 처리할 방법이 떠오르지 않았다.
'뭐' 가 '무엇' 의 준말이니 이걸 복원하는 것은 가능하다고 해도.
뭐가 좋아?
뭐 먹을래?
처럼 "뭐" 는 목적어말고도 다른 위치에 얼마든지 올 수 있었다.
조사가 있다면 조사로 판단하고 싶지만, "뭐를 먹을래?" 같은 문장은 구어체에서 잘 안쓴다.
띄어쓰기로 판단한다는 생각도 해보았지만, 그 다음에 봉착한 문제는
뭐가 좋아?
에 사용된 조사 '가' 를 어떻게 판단할 것인가였다.
조사 '가'는 주격조사가 될 수 있으면서 동시에 보격조사도 될 수 있었다.
주어와 보격조사를 어떻게 구분할 것인지 감이 오지 않았다.
AI허브 라는 사이트에서 대화 처리 API를 발견했지만
http://aiopen.etri.re.kr/demo_conversation.php
여기서조차 조사 '가'의 보격조사와 주격조사를 구분해내지 못하였다.
"나는 네가 좋아" 라는 문장에서
"네가" 를 주어로 인식한다.
조사 '이/가' 가 주격조사로 기능하는 것만을 전제한 것 같다.
관련 내용을 국립 국어원에서 조사해본결과
"한국어에서 '나는 네가 필요하다'라는 문장을 분석하는 방식에는 여러 가지가 있습니다. 이중 주어문으로 보는 견해도 있고, 뒤의 '네가'를 보어로 보는 견해도 있으며, 앞의 '나는'을 부사어의 변형으로 보는 견해(원래는 '네가 나에게 필요해'라는 문장이 변형된 것으로 보는 견해에 해당함)도 있습니다. 각각의 견해 모두 나름의 논리를 가지고 있으므로, 무엇이 전적으로 맞는다거나 틀린다고 보기는 어렵습니다"
" '네가 좋아'와 '(나는) 너를 좋아해'라는 문장 간의 관계에 대해서도 여러 이견이 있습니다. 대체로 '-어하다'는 그러한 느낌을 가지는 것을 드러낸다고 설명하며, 이 점에서 문장 구조가 변형된다고 설명합니다"
https://www.korean.go.kr/front/onlineQna/onlineQnaView.do?&mn_id=&qna_seq=144184&pageIndex=1
내 생각엔 아직 인간도 이해하지 못한 "언어의 문법적 논리구조"를
논리 그 자체인 컴퓨터에게 이해시키려면 아직 연구가 더 필요한 것 같다.
그래도 만약 이 조사 판단에서의 문제를 해결한 경우를 가정해보았다.
그럼에도 여전히 문제는 남아있었다.
"뭐 해?" 라는 질문에 어떻게 대답할 것인가?
컴퓨터는 무엇을 하고 있는가?
결국 이것에 대한 대답은 내가 직접 타이핑한 문자열 목록중에서 랜덤하게 뽑거나
다른 사람들의 대화 데이터를 가져와 그 중에서 빈도수가 높은 것을 높은 확률도 뽑도록 하는 등
결국 자기 스스로가 아닌 인간에 의해 만들어진 데이터와 확률에 의존하는 것 말고는 아이디어가 안떠올랐다.
궁극적으로는 사전에 등록된 어휘 데이터를 직접 스스로 조합해서 문장을 만들어내면 좋겠지만..
이걸 직접 구현했다가는 "대화하는 봇" 이전에 "문장을 만드는 봇"을 만드는데 공을 들여야 할 것 같았다 ㅋㅋ
(생각해보니까 문장을 만들 줄 알아야 진짜 의미로 대화를 할 수 있네... 포기할까 ㅋㅋ)
그래서 일단 주제의 폭을 좁혀보려고 한다.
사람이 한 말이나 이야기를 보고, 그 상황에 관련된 '감정'을 캐치해서 공감해주는 봇을 만들어보려고 한다.
물론 관련 연구분야 영역도 이미 존재하고,
내가 기억하기로 몇년전에 본 다큐멘터리에서 일본에서 특정 상황에 대한 감정을 스스로 표현하는 인공지능까지
개발한 것으로 기억한다.
내 목표는 그런 '상황'을 판단한다기보다 상대방의 문자를 보고 그 상황에 대해 적절한 반응만 해주는 것이다.
"오늘 하루동안 연속으로 시험을 3개봤어"
"와.. 진짜 힘들었겠네 수고했어"
이 정도의 멘트를 해주는 것이 목표다.
우선 이 멘트를 하려면 문장에서 상황을 읽어야 하고,
문장에서 상황을 읽으려면 기본적으로 문장의 내용을 분석할 수 있어야 한다고 생각했다.
문장 내용 분석 -> 시험, 연속 -> "힘든 것 + 연속 = 더 힘들다" -> "와 진짜 힘들었겠다. 수고했어"
현재 단계에서 목표하는 것은 "문장 내용 분석 -> 시험, 연속" 이것까지 추출하는 것이다.
그것의 첫 단추로, 간단한 조사 분석을 시도해보았다.
전제사항으로
1. 모든 띄어쓰기는 문법에 맞게 이루어진다.
2. 조사는 생략되지 않는다.
3. 기본적인 어순은 "주어 - 목적어 - 서술어" 순으로 한다.
우선 다음과 같은 전제를 깔았다.
이 전제를 깔면 내가 원하는 "구어체"를 구현할 수가 없다.
"밥 먹었어" 라고 하지, "밥을 먹었어" 라고 하는 경우는 드물다.
하지만 아직 조사 없이 문장성분을 파악하기는 힘들 것 같아서
격조사를 이용해 문장성분의 위치를 알 수 있게 해보았다.
그렇다면 알고리즘은 간단하다.
보통 띄어쓰기는 조사를 기준으로 이루어진다.
띄어쓰기 기준으로 문장을 자르고, 매 어절마다 맨 뒷글자를 조사하면 된다.
우선 단어 정보를 저장할 객체를 만들어보았다.
객체 구조도는 다음과 같이 만들어보았다.
answer과 hello는... 우선 상대방이 보내는 인삿말에 반응하고, 대답말에 반응하지 않기 위해서
정보를 저장하고자 만든 임시 칸이다.
나중엔 문장 분석을 하고나서 그게 인사인지, 대답하는 말인지 파악하는 식으로 하고 싶다.
우선 조사쪽 큰 분류틀을 잡고, 그 안에 이,가,을,를 네개의 조사를 넣었다.
그리고 각각에 맞는 격 성격을 속성으로 넣어주었다.
function analize_reply(recv_msg)
{
let result = []; let words = recv_msg.split(' '); // 띄어쓰기 기준으로 쪼개기
result.push("동사: " + words[words.length-1]);
for (var i = 0; i < words.length-1; i++)
{
let check = words[i].trim();
if (check.length == 1)
{
if (check == "야")
{result.push("calling");}
else
{result.push("unknown");}
}
if (check.length > 1)
{
if (check.substr(check.length-1, 1) in dictionary["josa"])
{
result.push(dictionary["josa"][check.substr(check.length-1, 1)]);
}
}
if (check.length > 2)
{}
}
return result;
}
간단하게 함수를 만들어보았다.
문장을 띄어쓰기 기준으로 자른다음
각각의 잘라진 어절에 대해 반복한다.
만약 어절이 한글자면 조사가 있을 수 없다.
그 중에 "야" 라는 말이 있다면 그건 나를 부르는 말이니 calling 이라는 결과로 분석하게 한다.
그 밖에 상황은 아직 안만들었으니 unknown 으로 처리.
어절이 2글자 이상이라면 한글자 짜리 조사가 있을 수 있다.
맨 마지막 글자를 조사해서 그 글자가 "조사" 사전 목록에 있다면 조사로 인식시킨다.
물론 이렇게 분석하는 것도 무조건 맞는 건 아니다.
"이 수은 온도계는 얼마죠?" 라는 문장에서
'수은' 의 '은'을 조사로 판단할 것이 뻔하다.
그래도 '조사를 생략하지 않는 전제' 라면 어느정도 맞을 것이라고 생각해서 저렇게 해보았다.
나무위키로 조사에 어떤게 있는지 가볍게 한번 목록을 보니 두글자로된 조사도 있는 듯했다.
정확한 정보를 위해 국립 국어원의 '표준국어대사전'을 활용해 조사 목록을 검색해보았다.
178개..ㅋㅋㅋ 많다..
그리고 그 중에서 두글자도 보인다.
그래서 일단 두글자에 대한 경우체크를 위해 칸은 만들어두었다
그리고 우리가 평소에 쓰는 문장들을 생각을 해보았을 때,
동사는 언제나 마지막에 오는 것이 떠올랐다.
너 밥은 먹었니?
책 좀 갖다줘
내일 거기서 보자.
처럼 동사는 언제나 마지막에 온다.
물론 동사 위치가 마지막이 아니어도 의미전달은 되지만,
문학적인 요소가 아닌 이상 일상에서 어순을, 특히 동사는 바꿔 말할 일이 더더욱 없다.
그래서 우선 맨 마지막 어절을 동사로 취급하여 분석하도록 하였다.
(물론 이렇게 분석했을 때 틀린 반례데이터는 무수히 많다ㅋㅋ)
일단 간단하게 위에 적은 4개의 한글자 조사만 가지고 테스트를 해보기로 했다.
동사에 대한 판단을 먼저해서 result 배열에 넣고, 그 다음에 조사를 판단하게 하였다.
동사에 따라 필수 성분이 달라지기 때문에, 같은 소리가 나지만 다른 격을 갖는 조사를 판단할 때 도움이 될 것 같다고 생각했기 때문이다.
(아까 말했던 주격조사와 보격조사의 '이/가' 를 구분하는데 쓸 수 있지 않을까 싶었다.
예를 들어 '되다' 라는 서술어는 주어와 보어를 필수 성분으로 가진다.)
그래서 result 배열을 출력하면 저렇게 동사부터 결과가 나온다.
(자바 스크립트는 배열 오브젝트의 경우, 사용자 정의 오브젝트와 다르게 내용을 출력해준다ㅎㅎ)
교과서에서 문장의 성분 분석 기본 예제로나 보일 법한 문장이지만
좋아한다를 동사로, 아버지가를 주어로, 나를 을 목적어로 잘 판단한다.
=====================================================
다음에는 사전에 조사 데이터를 더 추가해서 더 많은 문장에 대해 성분 판단을 가능하게 만들고,
그렇게 판단한 성분을 문장분석 객체에 넣는 작업을 해볼 생각이다.
사실 형태소 분석 API가 아까 위에 언급한 사이트에서 오픈 API로 존재한다.
근데 아직 신청한 API 키가 승인 허가가 안나기도 했고, API를 적용하는 법을 몰라서 보류중이다.
아마 이 API를 활용하면 이 과정을 좀 더 간단하게 할 수 있지 않을까 싶기도 하다
API 사용 승인을 받고 적용법을 익힐 때까지는 한번 직접 문장을 분석해서 구현해보려고 한다.
'개인 프로젝트 > [2020] 카카오톡 봇' 카테고리의 다른 글
[카카오톡 봇 만들기] 4. 이야기를 들어주는 봇 만들기(1) : 문장분석(2) (0) | 2020.10.29 |
---|---|
[카카오톡 봇 만들기] 3. 카카오링크 전송하기(2) : 코로나 현황 웹 크롤링 (0) | 2020.10.22 |
[카카오톡 봇 만들기] 3. 카카오링크 전송하기(1) : 테스트 & 봇 기능 수정 (3) | 2020.10.22 |
[카카오톡 봇 만들기] 2. 명령어로 조작하기(3) : 테스트 (0) | 2020.10.18 |
[카카오톡 봇 만들기] 2. 명령어로 조작하기(2) : 알고리즘 구현(2) (2) | 2020.10.16 |