1. 상대방의 말 잠시 기억하기


User> 저는 씨엘을 특히 좋아해요

Bot> 그럼 씨엘을 직접 본 적도 있어요?




A. u: (~씨엘*~2좋아*)

룰A는 “씨엘을 좋아해요”, “저는 씨엘을 가장 많이 좋아해요”, “CL이 좋아” 등을 매칭


B. u: (_~씨엘*~2좋아*)

사용자가 말하는 씨엘을 변수로 저장

컨셉 앞에 _(under bar)를 붙이면 사용자가 컨셉 ~씨엘에 포함되어 있는 여러 단어 중에 한 단어를 입력할 경우 그 단어를 임시 변수에 저장한다.

룰이 유효할 때까지 이 변수도 유효

= 출력문이 출력될 때까지만 유효한 변수임





Match변수 

_(under bar)명령어로 저장되는 변수

사용자가 입력한 단어에 매칭되는 변수





_0

_0을 출력문에 포함시키면 이 변수에 보관해 둔 사용자 입력 단어가 함께 출력된다.


ex)

A.     u: ( _~씨엘 *~2 좋아*) 그럼 _0 직접 본 적도 있어요?


사용자가 ~씨엘 컨셉에 포함되어 있는 단어 중 어느 하나를 입력하면 매칭에 성공하고

그 단어를 첫번째 임시변수(0번 변수)에 저장한다

출력문에서는 첫번째 임시변수 (_0)를 호출하고 있으므로

저장해 두었던 사용자 입력 단어를 출력하게 되는데

이 때, _0는 CS가 기본형(canonical form)으로 바꾼 값이고





만약 사용자가 입력한 최초의 형태를 출력하고 싶으면  '(어퍼스트로피)를 붙여야 한다


ex)

B. u:(_~씨엘**~2좋아*) 그럼'_0 직접 본 적도 있어요?





여러개 저장하려면 _0, _1, _2 등으로 사용한다


ex)

C. u: (_*1_*1_*1_*1*~2좋아*) 그럼 _3,_1,_0,_2 중 길러 본 과일이 있어요?


"딸기, 사과, 포도, 수박을 좋아해요"라는 사용자의 말에

"그럼 수박, 사과, 딸기, 포도 중 길러 본 과일 있어요?"라는 챗봇의 질문을 가능하게 한다





D.     u: ( _[ 사과 배 포도 딸기 ] )

사과, 배, 포도, 딸기 중의 어느 하나를 입력했을 경우에만 저장



E.     u: ( _{ 사과 배 포도 딸기 } )

사용자가 사과, 배, 포도, 딸기 중의 어느 하나를 입력하였다면 저장하고 입력 안했다면 저장 하지 않는다. 



F.      u: ( _*)

사용자가 입력한 것이 무엇이든 무조건 저장



G.     u: (_*1)

무엇을 입력하든 한 단어만 저장




이 단기 기억을 위한 장소는 0~19까지 총 20개가 있다.





투애니원 멤버를 하나의 컨셉으로 만들기

H. concept: ~투애니원멤버 [~씨엘 ~박봄 ~산다가 ~민지]

u : (!안_~투애니원멤버 *~2좋아*) 그럼 _0 직접 본 적도 있어요?



I. (_*_0?~투애니원멤버)_0 투애니원 콘서트에서 보셨어요?










2. 대화 내용을 오래 기억하기





룰C의 말걸기는 $Concert에 값이 할당되었을 때만 참이 되며, 조건이 참일 때만 실행된다.





위 변수의 4가지 경우의 수


①    룰C의 앞쪽 어디에도 $Concert 변수가 없다 (거짓)

조건이 참인지 알아보려고 했는데 앞쪽 어느 대화에서도 $Concert라는 변수가 선언된 적도 사용된 적도 없다. 

즉 이곳에 처음 나타나는 변수이다. 

변수가 처음 언급되면 자동으로 null값 (=할당된 값 없음)을 갖게 되므로 위의 조건은 거짓이 되어 룰C는 실행되지 않는다.


②    룰 B가 실행되지 않았다 (거짓)

룰B가 실행되지 않았다면 $Concert 변수는 이곳에서 처음 선언된 것과 같은 상태 값을 가지고 있다. 

즉 선언될 때 자동으로 할당 받는 null 값을 가지고 있고 따라서 조건은 거짓이 된다.


③    룰 B가 실행되었다 (참)

룰B가 실행되면 $Concert에 Yes라는 값이 할당된다. 

즉 null 이외의 값을 가지고 있으므로 조건은 참으로 판명된다.


④    $Concert에 No라는 값이 할당되어 있다.(참)

이 경우도 조건은 참으로 판명된다. 

룰C의 조건식은 $Concert에 할당된 값이 무엇이냐는 구별하지 않고 값이 할당된 적이 있느냐만 구별하기 때문이다.







만약 값이 Yes일 때만 실행하도록 하고 싶으면 룰C의 조건문을 다음과 같이 수정하면 된다.


 

D.     t: ($Concert==Yes) 그런데 투애니원 콘서트에는 누구와 갔었어요?


E.     t: ($Concert!=No) 그런데 투애니원 콘서트에는 누구와 갔었어요?


 

이때 Yes와 No의 의미는 챗봇의 작성자가 임의로 정한 것으로 본인이 파악할 수 있으면 된다. 

여기서 주의할 점은 등호의 왼쪽과 오른쪽에 빈칸이 없어야 한다는 점이다. 좌우를 비교하는 관계식은 빈칸없이 붙여 써야 한다.

















3. 모를 때만 질문하기


A.     u: ( _*1 좋아*) 그렇군요. 저도 _0 좋아해요. $Favorite = _0


_언더바 명령어

사용자가 입력한 단어가 무엇이든 한 단어를 단기기억 변수에 저장


(_*1)

언더바가 붙은 와일드 카드에 숫자 1을 지정


저장한 후 출력문에서 _0에 의해 호출되어 사용자에게 출력된다

동시에 $Favorite에 사용자가 입력한 단어 저장


임시기억장소->장기기억장소로 옮기는 것







B.     t: (!$Favorite) 투애니원 멤버 중에 특별히 좋아하는 멤버가 있어요?

a: (~박봄) $Favorite = 박봄

a: (~씨엘) $Favorite = 씨엘

a: (~산다라) $Favorite = 산다라

a: (~민지) $Favorite = 민지





출처 : http://exagen.tistory.com/notice/63 [혼자 힘으로 한국어 챗봇 개발하기]



룰타입: 라벨 (패턴) 출력문


?: TIME (지금 몇 시에요) 오후 5시 입니다.




룰타입


1. 챗봇의 발화(챗봇이 말할 때)

- t: Gambit(챗봇이 먼저 말할 떄)


2. 사용자의 발화(사용자가 말할 때)

- s: Statement(사용자가 평서문으로 말할 때)

- ?: Question(사용자가 의문문으로 말할 때)

- u: Utterance(문장의 종류 상관없이 사용자가 말할 때)


라벨


라벨을 가지면 다른 룰이 호출하여 재사용 가능

디버그 시, 호출하여 테스트 및 추적 가능

MyFavorite, Best_Singer 이런식으로 띄어쓰기 없이 작성






챗봇을 기준으로 룰의 3종류


1. 말걸기 gambit - 챗봇이 사용자에게 먼저 말 걸 때, 보통 화제 제시, 대화시작 위한 질문

2. 응답 responder - 사용자의 진술/질문에 어떻게 응답해야하는지 정의

3. 예상응답 rejoinder 챗봇이 사용자에게 질문 시, 사용자의 응답을 예상한 후, 챗봇이 재응답할 것을 정의






토픽 


연관된 룰을 모아놓은 논리적 집합체, 사람의 대화관리와 유사


토픽선언자: ~토픽이름 [키워드목록]


Topic: ~baseball [strike "home run: ball bat hit]


1. 토픽선언자 - 토픽을 만들라는 의미, 콜론으로 끝남

2. 토픽이름 - 반드시 ~로 시작, 한 단어로 사용자 임의대로 구성

3. 키워드목록 - []안에 띄어쓰기로 나열, 사용자가 입력한 단어가 키워드 목록에 있으면 토필이 호출된다.


이야기 토픽 Story topic - 대화 이끌어가기

반응전용 토픽 Reactor topic - 사용자 질문/응답에 반응하기

얼버무림 토픽 Quibble topic - 모르는 문제일 때 화제전환하기(무시받는 느낌 안들도록)







u: (집*  * 간다)

*자리에 어떤 단어라도 몇 개의 단어가 와도 매칭된다


u: (집* *~2 간다)

*~2의 의미는 단어가 없거나 or 하나 or 두개까지 어떤 단어가 와도 좋다


u: (!못 집* *~2 간다)

!뒤의 단어를 제외하라

사용자 입력문에 '못'이란 단어가 있으면 매칭에서 제외된다







최우선 업무는 사용자 입력문에 일치하는 규칙을 찾는 일

말걸기의 가장 중요한 기능은 화제거리를 제시하여 사용자와의 대화를 주도하는 것

질문을 하면 미리 준비해 놓은 주제로 대화의 범위를 좁히는 장점이 있다.






A. t: Voce gosta de K-pop?

B. t: MeuFavorito () Eu gosto de BTS. $MeuFavorito=1

C. t: ($Concert) Com quem voce fui concerto de BTS?


룰A

전형적인 말걸기 형식

룰 타입과 출력문만 있음


룰B

라벨을 가진 말걸기 규칙

이후에 이 라벨 호출하여 사용 가능

라벨을 붙일 때는 룰의 4가지 구성요소를 모두 작성해야 함

MeuFavorito가 라벨이라는 것을 CS에 알려주기 위해 () 사용

맨 끝에는 향후 사용을 위한 변수 선언 및 값 설정


룰C

변수 $Concert가 참일 때만 규칙 실행하라는 뜻


모든 말걸기 규칙(t:)은 모든 응답규칙(s: ?: u:)보다 앞에 위치해야 하고,

쓰여진 순서대로 시행된다.


또한 사용 후에는 사용되었다는 마크가 붙어 재사용 방지

하지만 규칙을 명시적으로 호출하면 재사용 가능







concept 명령 사용하여 연관 단어 집한을 만들고 여러 곳에서 호출 가능


컨셉 선언자: ~컨셉이름 [키워드목록]

concept: ~투애니원 [투애니원 투에니원 2NE1 2ne1 퉨원]






Topic: ~KPOP [~투애니원 ~마마무 가요 히트곡]

토픽의 키워드란에 컨셉 입력도 가능






Bot> Voce gosta de K-pop?

User> Sim, eu amo!

Bot> Ta bom, entao qual grupo e o seu favorito?





응답하기(responder) 룰

종류: (패턴) 출력문

A. u: (듣고) 말하기

A. u: (Sim, eu amo) Ta bom, entao qual grupo e o seu favorito?


사용자가 입력한 내용이 '패턴'과 일치하면 '출력문'을 출력한다.




사용자 답변은 다양하다

Bot> Voce gosta de K-pop?

User> Sim, eu amo!

Sim

amo

gosto sim

nossa claro

logico

eu muito gosto






사용자 응답 일반화 시키기

1. 선택매칭 []

A. u: ( [sim logico claro] gosto)

[]안에 단어들 중 무엇으로 대답해도 매칭된다

하지만 이런 답변은 여러 곳에서 반복 사용되기 때문에 비효율적


2. 컨셉 ~()

그래서 컨셉을 사용한다

concept: ~sim[sim logico claro]

u: (~sim gosto) entao, qual grupo e o seu favorito?


3. 와일드카드 *

*[스타 / 에스터리스크]

B. u:(~sim *~5 gosto*)

muito gosto, pouco gosto 같은 것과 함께 사용 가능





Topic: ~KPOP [ ~투애니원 ~티아라 ~마마무]

t: 혹시 K-POP 좋아하세요?

u: (~예 *~2 좋아*) 그럼, 좋아하는 가수가 있어요?






어순 무시

C.     u: (<< 좋아* 노래 >>) 예. I love you를 좋아해요.


<<>>명령어

CS엔진은 단어의 나열된 순서에 상관없이 그 단어들이 사용자 입력문에 나타나는가를 조사하여 매칭 여부를 판단.







예상응답 rejoinder

질문 하나에 응답이 여러개일 경우 

영문 소문자로 시작함으로써 CS에게 이들을 동일한 우선순위로 매칭 검토하라고 지시하는 것

t: 좋아하는 가수가 있어요?


a: ( ~2NE1) 예. 노래 정말 잘하는 걸그룹이지요.


a: ( ~티아라) 좋은 노래가 많은 걸그룹이에요.


a: ( ~마마무) 요즘 인기가 많은 신인 걸그룹이지요


a: (~아니오) 악동 뮤지션 노래를 들어 보셨어요? 좋아하게 될거에요.







A.     u: ( 좋아* [노래, 곡, 음악, 가사, song] 있어요) 예. I love you를 좋아해요

      B.     concept: ~노래 [노래, 곡, 음악, 가사, Song]

 u: ( 좋아* ~노래 있어요) 예. I love you를 좋아해요.



B.     b: ( [좋아* 아*] ~노래 있*) 예. I love you 를 좋아해요







concept에 추가하기

concept: ~강아지 MORE [ 마스티프 쉬나우저 테리어 도베르만]





한국어의 동사/형용사의 다양성 처리

각 단어의 기본형과 활용형을 사전(dictionary)에 등록한 후 룰을 기본형(canonical form)으로 작성하면 사용자가 어떤 형태를 입력하든 시스템이 알아서 매칭


A.     u: ( 야구* 좋아하다 ) 저는 축구를 좋아해요.


이 룰은 “야구를 좋아해요”, “야구를 좋아합니다”, “야구를 좋아했지만 농구를 더 좋아한다.”, “야구를 좋아하는 친구가 있어요.”,  “야구를 좋아해서 잠실 구장에 응원가요” 등과 모두 매칭 된다.






기본형~활용형 연결을 위한 방법


1. 외부 사전 구비

국립국어원의 세종전자사전(상업적 용도 아니면 자유롭게 사용 가능) : 동사나 형용사의 모든 활용형을 등재 하지 않아 추가작업 필요(사전에 등재된 동사와 형용사에 대해 canon 명령어로 활용형과 기본형을 연결시키는 작업) [https://ithub.korean.go.kr/user/main.do]

부산대학교의 KorLex(저작권 먼저 해결할 것) [http://korlex.pusan.ac.kr/]


2. concept으로 만든다

concept: ~좋아하다 [좋아해 좋아해요 좋아합니다 좋아하고 좋아해서 좋아하며 …… ]

모든 활용형을 하나의 컨셉으로 묶고 그 컨셉 이름을 기본형으로 정하는 방법


3. 직접 사전을 만든다

concept 명령어로 사용자 사전을 만들어 기본형과 활용형을 등록하고 canon 명령어로 활용형과 기본형을 연결시켜 준다


concept: ~좋아하다 VERB ( 좋아하다 좋아해 좋아하는 좋아해서 좋아하고 )

canon (좋아해 좋아하다)

canon (좋아하는 좋아하다)

canon (좋아해서 좋아하다)

canon (좋아하고 좋아하다)


concept 명령어로 사용자 사전을 만들 때는 컨셉이름 뒤에 VERB, ADJECTIVE, ADVERB, NOUN 등과 같은 품사명을 지정해 주면 된다.


4. 선택매칭([])을 사용한다

u: ( 야구* [좋아해 좋아해요 좋아합니다 좋아하고  좋아하며 좋아하니까] )


5. 부분 와일드 카드를 사용한다

“어근+*”의 부분 와일드 카드로 패턴을 작성


u: ( 야구* 좋아* )


불규칙 변화일 때는 아래와 같이 추가를 하면 된다. 이 방식의 단점은 기본형과 활용형의 장점을 활용하지 못한다는 점과 장차 지식베이스를 만들 때 활용하지 못한다는 점을 들 수 있다.


#! 강아지가 반갑게 꼬리쳤다

u: ( 강아지* [ 반가* 반갑* ] 꼬리* )





실용적인 측면에서의 추천안은 마지막 다섯 번째 방안

하지만 전문가 시스템은 3번째 방안 추천





사용자가 입력한 형태 그대로 매칭되도록 하고 싶을 때

형용사 “빨갛다”가 빨갛고, 빨개서, 빨갛지만, 빨가니까 등의 활용형과 함께 기본형으로 등록되어 있다고 가정할 때,


u: ( 사과* ‘빨갛다 )


이 룰은 “사과는 빨갛다”와는 매칭이 되지만 “사과가 빨갛고”, “사과는 빨갛지만” 등과는 매칭이 되지 않는다. 즉 ‘(어포스트로피)를 붙이면 기본형으로 일반화시키지 않고 그 형태 그대로를 유지하라는 뜻이 된다.






영어의 경우

사용자가 입력한 단어의 기본형(canonical form)을 정확히 알아냄


1. POS Tagging(Part-of-speech tagging 품사분류기)

단어를 명사, 동사, 형용사 등의 품사로 구별

CS는 영어에 대한 자체 POS Tagger내장함


2. Parsing

단어의 역할 기능을 분석하는 작업

문장 구조와 이웃 단어 관계를 기초로 한다


3. 사전

철자 검사  및 단어들 간의 상위관계, 하위관계, 동등관계 등 개념상의 관계를 파악








외래어 표기

컨셉으로 묶어야 한다

concept: ~씨엘 [ 씨엘 씨에루 CL 이채린 “투애니원 리더” ]

b: (~씨엘 *~2 좋아*) 그렇군요. 저는 박봄이 좀 더 좋아요.







문장을 한 단어의 고유명사로 취급하기

"최대 5 단어까지 가능" 큰따움표 사용

u: (“내가 제일 잘 나가” 들어 봤*) 그럼요, 저도 그 곡을 즐겨 들어요.






키보드 자판 이모티콘 알아듣기

LiveData 폴더에 있는 testing.txt파일에 등록해주면 된다.

ex)

기존등록

:( ~emosad

:) ~emohappy


신규등록

:'-( ~emosad






미리 정의되어 있는 감정분류 컨셉

웃음 ~emolaugh

지루 ~emobored

고통 ~emopain

화남 ~emoangry

회의 ~emoskeptic

애원 ~emobeg

오해 ~emomisunderstand

무시 ~emoignorance

악담 ~emocurse

혐오 ~emodisgust

사과 ~emoapology

항의 ~emoprotest







자주 틀리는 문법 알아듣기


와일드 카드 사용하기(미봉책)

ex) 

"단언컨대"를 "단언컨데"로 자주 틀림

u: (단언* 한류 그룹) 예. 정말 독창적인 그룹이지요.



replace 명령어로 보조 사전을 만들어 매칭 시도 전에 틀린 문법 교정(근본적인 방법)

ex)

replace: 단언컨데 단언컨대


이렇게 replace를 이용해서 만들어진 보조사전은 TOPIC폴더 내에 private1.txt로 저장되고 반영된다.








글자로 쓴 숫자 알아보기(text number 문자숫자)


1. 패턴 매칭 이전에 사용자 입력문에서 문자숫자를 아라비아 숫자로 변환하기


전처리를 한 후에 패턴 매칭을 하면 사용자가 문자숫자로 입력해도 CS 내부에서 숫자로 인식되어 연산이 가능


1) replace 명령어로 변환할 내용 명시


D.     replace: 열일곱 17

E.     replace: 열일곱살 17

F.      replace: 열_일곱 17

G.     replace: 열_일곱_살 17

H.     replace: 열일곱_살 17




2) CS에게 패턴매칭 전 전처리 단계 때 이 변활르 적용하라고 명시


소스파일의 압축을 해제하면 나오는 harry폴더 내의 simplecontrol.top 파일의 세 번째 줄에 #DO_PRIVATE를 추가함으로써 가능

이 지시자가 있으면 CS는 Topic 폴더 내에 private1.txt가 있는가 살피고 있다면 그 내용을 전처리 단계에서 적용함




3) 패턴을 하단과 같이 작성


I.      concept: ~나이 ( 10 11 12 13 14 15 16 17 18 19 20 )

J.      u: ( _~나이 ) _0<19 아, 수능 준비를 하는군요.


_(언더바) : 단기 저장 명령어로 사용자가 입력한 단어를 잠시 저장해 놓는다

예를 들어 사용자가 "열입곱살"이라고 입력했다면, 17을 잠시 저장함


_0 : 첫 번째로 저장한 변수의 내용






*replace를 사용의 단점

최초 입력형 original input을 잃어버림

CS의 장점 중 하나가 입력형과 기본형을 늘 유지하며 사용할 수 있다는 점인데 그것이 불가능해짐


그래서 입력형을 살리고 싶다면 canon 명령을 사용





canon 명령형 사용하기


1)단어를 사전에 등록


K. concept: ~나이 NOUN ( 열일곱 열_일곱 열일곱살 열_일곱살 열_일곱_살 )


L. canon:

열일곱 17

열_일곱 17

열일곱살 17

열_일곱살 17

열_일곱_살 17


룰K는 concept을 선언할 때 NOUN이라는 지시자를 사용

(이 지시자의 완전한 목록은 소스화일과 함께 오는 ChatScript System Variables and Engine-defined Concepts.pdf 파일에 있다.)




2) canon 명령어로 입력형과 기본형 지정

^canon(활용형 기본형)도 가능하나, 대량의 데이터가 반복될 경우 위의 룰I와 같은 형식이 더 효율적

canon명령어가 성공적으로 수행되면 Topic 폴더 내에 canon1.txt 파일을 생성




3) 룰F와 룰G를 사용해서 사용자 입력문과 매칭


문자숫자를 매칭하면 사용자가 입력한 최초의 형태를 보존하면서동시에 필요한 사칙 연산을 모두 수행할 수 있다

반면 기본형에 대응시킬 문자숫자를 모두 사전(dictionary)에 등록해야 함

canon 사용이 정석









날짜, 시간 등 대답하기


u: ( 몇 시에요 ) 지금 %hour : %minute 이에요

u: ( 몇 시에요 ) %time 에요

u: ( 오늘 * [요일 며칠] ) 오늘은 %monthname %day %date 입니다.


그런데 시스템 변수는 숫자 값만 주기 때문에 위의 출력문은 다음과 같이 출력된다.


지금 15: 28 이에요.

15:28 에요

오늘은 April 15 Thursday 입니다








join함수 활용

join : 괄호 안에 포함된 인수들을 빈칸없이 하나로 합쳐서 하나의 문자열로 만드는 함수


ex)

t: 지금 시각은 ^join(%hour 시) ^join(%minute분) 이에요.

출력문 -> 지금 시각은 20시 35분이에요


$tmp=^compute(%hour mod 12)

t: 지금 시각은 ^join($tmp 시)^join(%minute 분) 입니다.

출력문 -> 지금 시각은 8시 35분 입니다




시간, 날짜 관련 시스템 변수











출처 : http://exagen.tistory.com/notice/63 [혼자 힘으로 한국어 챗봇 개발하기]



혼자 힘으로 한국어 챗봇 개발하기

http://exagen.tistory.com/notice/63


챗봇 개발에 도움을 주는 글 모음

https://blog.naver.com/koys007/221182681194


Python으로 챗봇 만들어보기

http://static.wooridle.net/lectures/chatbot/


챗봇 개발 플랫폼

http://mindmap.ai/


네이버 Hi Genius 블로그

https://blog.naver.com/chandong83/221067630252


텐서플로 블로그

https://tensorflow.blog/


딥러닝 강의

https://hunkim.github.io/ml/

https://blog.naver.com/atelierjpro/220697898876

https://cloud.google.com/blog/big-data/2016/08/how-a-japanese-cucumber-farmer-is-using-deep-learning-and-tensorflow

+ Recent posts