---
# System prepended metadata

title: Spring 프로젝트

---

# Spring 프로젝트
- 최초 작성일: 2021년 7월 19일(월)

## 목차
[TOC]
## 이슈사항
### 09.07
1. (해결)모바일을 utterance로 추론하면 ne가 lob랑 payment_method가 추출됨
    - 납부방법 변경 할 때 lob를 모바일이라고 말하면 payment_method도 같이 채워져서 납부방법을 물어보지 않고 변경완료가 되버림.
    --> NE pos_start, post_end가 겹치는 건 CONTEXT에서 삭제
2. (해결)추가학습 필요한 CONFIRM 개체
    - "없어"라는 발화를 CONFIRM 개체(phrase: "NO")로 인식될 수 있게 학습필요
### 09.14
1. (해결)FAQ 답변 미응답 : faq confirm이 작동이 안됨 : 약정 갱신이 뭐예요? -> 네
2. context 응답 : 로그내용이 이상 => 수정(김성현)
3. (해결)개체명 여러개일 때 최장 일치 개체명 선택: 09.07 이슈 해결 확인 
4. (해결)CONFIRM NO 처리가 안됨 : 시나리오에 없는건가?






## 데모 시나리오
### 요약
1. 의도탐침 (Select형 탐침) -> slot-filling (auto slot-filling으로 NE를 채움) -> 시나리오 -> 끼어들기 -> 끼어들기 시나리오 수행 -> 원 시나리오 컴백  -> 원 시나리오 완결 -> FAQ 요청 -> FAQ 응답
2. 정책 수정 (의도 threshold 수정 등 --> **어떤 걸 수정할지? 논의 필요**)
3. 새로운 의도 요청 -> session/context를 이용하여 일부 slot skip -> 시나리오 수행 -> 시나리오 완결 후 추가 문의 질의 -> 고객 reject -> good bye 멘트



    
### 봇-고객 발화 (시나리오1)
- 고 : 이번달 얼마 내 ? 
    - 납부금액_확인
- 봇 : 인터넷인가요? 모바일인가요?
    - 납부금액_LOB확인
- 고 : 핸드폰 요금
    - 모바일(Entry)
- 봇 : 이번달 모바일 납부 요금은 {0}입니다.
    - 납부금액_LOB확인_요금안내
- 고 : 납부 방법 변경 해줘
    - 납부방법_변경_대표(Intent)
- 봇 : 모바일 요금 납부 방법 알려드리겠습니다. 모바일 요금은 e-mail로 납부 중입니다. 어떤 납부 방법으로 변경 해드릴까요?
    - 납부방법_변경
- 고 : WIFI 패키지도 종류가 있나요? 
    - FAQ
- 봇 : 와이파이 패키지는 인터넷 속도에 따라, 10기가 인터넷 최대 2.5기가 플러스, 기가 인터넷 최대 1기가 플러스와 500메가 플러스, 인터넷 최대 100메가 플러스 상품이 있습니다. 휴대폰 납부 반경 변경을 진행할까요?
- 고 : 그래
- 봇 : 모바일 요금 납부 방법 알려드리겠습니다. 모바일 요금은 e-mail로 납부 중입니다. 어떤 납부 방법으로 변경 해드릴까요?
- 고 : 카카오페이로 변경 해주세요
    - 카카오페이(Entry)
- 봇 : 변경 하였습니다.
    - 납부방법_변경_완료

#### 필요한 의도
    납부금액_확인
    
 
#### 상태 전이
    납부금액_LOB확인 / LOB / 납부금액_LOB확인_요금안내
    납부방법_변경 / (지로|카카오페이|모바일) / 납부방법_변경_완료
 
#### 상태별 발화 (상태명 / 발화)
    납부금액_LOB /인터넷인가요? 모바일인가요?
    납부금액_LOB확인_요금안내 / 이번달 {0} 납부 요금은{1}입니다.
    납부방법_변경 / 모바일 요금 납부 방법 알려드리겠습니다. 모바일 요금은 e-mail로 납부 중입니다. 어떤 납부 방법으로 변경 해드릴까요?
    납부방법_변경_완료 / 납부 방법을 #0에서 #1으로 변경하였습니다.
    납기일_변경 / 인터넷인가요? 모바일인가요?    납기일
    납기일_변경_LOB / 원하시는 납기일이 언제인가요?
    상담종료 / 상담을 종료하겠습니다. 더 문의하실 내용은 없으신가요?
    
#### 필요한 개체
    LOB / 모바일 / 휴대폰
    LOB / 인터넷
    MON / 이번달 -> 8월(상대적 날짜 추출 가능?)


### 봇-고객 발화 (시나리오2)
- 봇: 안녕하세요. 가상 상담사 지니입니다. 무엇을 도와드릴까요? (인사말)
- 고: 인터넷 요금
    - 탐침의도 => 추후 고민 해야 할 사항
- 봇: 고객님이 문의하신 내용이 납기일 문의인가요? 납기일 변경인가요? (select형 의도 탐침)
- 고: 납기일 문의예요
- 봇: 납기일 문의는 본인만 하실 수 있습니다. 본인이신가요?
    - 납기일_문의
- 고: 납기일 확인 전에 자동납부 날짜 먼저 바꿀게요 (끼어들기)
- 봇: 고객님이 문의하신 내용이 납기일 변경인가요? (의도 confirm)
    - 납기일_변경
- 고: 네 (고객 confirm)
- 봇: 납기일 변경은 본인만 하실 수 있습니다. 본인이신가요?
    - 납기일_변경_본인
- 고: 네 (고객 confirm)
- 봇: 고객님의 생년월일 6자리를 키패드로 입력 후 우물정자를 눌러 주세요.
    - 납기일_변경_본인_생년월일
- 고: 123456# (dtmf 입력)
- 봇: 며칠로 변경해드릴까요? (day NE slot-filling)
    - 납기일_변경_본인_생년월일_월_일
- 고: 25일
- 봇: 납기일 변경이 완료 되었습니다. 납기일 문의를 다시 진행할까요? (leaf 노드 이후 끼어들기 이전 시나리오 confirm)
    - 납기일_변경_본인_생년월일_월_일_완료
- 고: 네 (고객 confirm)
- 봇: (lob(인터넷) NE auto slot-filling으로 lob slot-filling 생략)
- 봇: (session의 본인인증 여부를 확인하여 본인인증 생략)
- 봇: 고객님의 인터넷 요금 납기일은 25일입니다. 더 문의하실 사항 있으실까요? (시나리오 leaf 노드)
    - 납기일_문의_확인


#### 필요한 의도
- 시나리오 의도
    - #납기일_문의
    - #납기일_변경

#### 필요한 NE
    - MON / 8월
    - DAY / 25일  => system객체로 할지 논의가필요(김성현)
    네,아니오 (컨펌객체, 미리 정의)

#### 상태 전이 정보 (from / event / to)
    납기일_문의 / 네 / 납기일_문의_확인
    납기일_변경 / 네 / 납기일_변경_본인
    납기일_변경_본인 /[1-9][0-9]{5} / 납기일_변경_본인_생년월일
    납기일_변경_본인_생년월일 / MON / 납기일_변경_본인_생년월일_월
    납기일_변경_본인_생년월일_월 / DAY / 납기일_변경_본인_생년월일_월
    납기일_변경_본인_생년월일_월_일 / yes /납기일_변경_본인_생년월일_월_일_완료

    


> 정책 수정 (의도 threshold 수정 등 --> **어떤 걸 수정할지 논의 필요?**)

- 고: 이번달 핸드폰 요금이 어떻게 되는지도 알려주세요.
- 봇: 고객님이 문의하신 내용이 청구요금 확인인가요? (의도 confirm)
- 고: 네 (고객 confrim)
- 봇: (lob(핸드폰) NE auto slot-filling으로 lob slot-filling 생략)
- 봇: (session의 본인인증 여부를 확인하여 본인인증 생략)
- 봇: 몇월달 요금을 알려드릴까요? (month slot-filling)
- 고: 8월
- 봇: 고객님의 8월 모바일 요금은 xxxx원입니다. 더 문의하실 사항 있으실까요? (시나리오 leaf 노드)
- 고: 아니 (고객 reject)
- 봇: 지금까지 가상 상담사 지니였습니다. 감사합니다. (good bye 멘트)



### start api
url : http://localhost:8080/start
``` json
response = {
    "contextKey": "a42fd8eb-6d82-43ea-aff7-2f49a872f68a",
    "utterance": "안녕하요 스프링프로젝트 챗봇입니다. 무엇을 도와드릴까요?"
}
```


### talk api
url : http://localhost:8080/talk

``` json
request = {
    "contextKey": "a42fd8eb-6d82-43ea-aff7-2f49a872f68a",
    "utterance": "모바일"
}


response = {
    "contextKey": "a42fd8eb-6d82-43ea-aff7-2f49a872f68a",
    "utterance": "이번달 모바일 납부요금은 1000원입니다 더 문의하실 내용이 있으면 말씀해주세요",
    "log": {
        "currentIntent": "납부금액_확인",
        "intents": [],
        "entities": [
            {
                "entity": "LOB",
                "value": "모바일",
                "type": null,
                "phrase": null,
                "pos_start": null,
                "pos_end": null
            }
        ]
    }
}
```

### 실제 개체 목록
``` json
"entities": [
            {
                "entity": "USER/LOB",
                "value": "휴대폰",
                "pos_start": 0,
                "pos_end": 2,
                "type": "synonym",
                "phrase": "모바일"
            },
            {
                "entity": "USER/LOB",
                "value": "폰",
                "pos_start": 2,
                "pos_end": 2,
                "type": "synonym",
                "phrase": "모바일"
            },
            {
                "entity": "SYSTEM/CONFIRM",
                "value": "그래",
                "pos_start": 0,
                "pos_end": 1,
                "type": "phrase"
            }
        ]
```


### 시연용 개체 목록

```python
entities = [
    {
        "type": "USER",
        "name": "LOB",
        "phrase_set": [
            {
                "phrase": "모바일",
                "synonym_set": [
                    {
                        "synonym": "휴대폰",
                    },
                    {
                        "synonym": "핸드폰",
                    },
                    {
                        "synonym": "폰",
                    },
                ],
            },
            {
                "phrase": "인터넷",
            },
        ],
    },
    {
        "type": "USER",
        "name": "PAYMENT_METHOD",
        "phrase_set": [
            {
                "phrase": "$payment_method",
                "synonym_set": [
                    {
                        "synonym": "지로",
                    },
                    {
                        "synonym": "카카오페이",
                    },
                    {
                        "synonym": "모바일",
                    },
                ],
            }
        ],
    },
    {
        "type": "SYSTEM",
        "name": "MON",
        "regex_set": [
            {
                "regex": "[123456789]월",
            },
            {
                "regex": "1[012]월",
            },
        ],
        "phrase_set": [
            {
                "phrase": "$this_month",
                "synonym_set": [
                    {
                        "synonym": "이번달",
                    },
                    {
                        "synonym": "이번 달",
                    },
                ],
            }
        ],
    },
    {
        "type": "SYSTEM",
        "name": "DAY",
        "regex_set": [
            {
                "regex": "[123456789]일",
            },
            {
                "regex": "[12][0123456789]일",
            },
            {
                "regex": "3[01]일",
            },
        ],
        "phrase_set": [
            {
                "phrase": "$today",
                "synonym_set": [
                    {
                        "synonym": "오늘",
                    },
                ],
            }
        ],
    },
    {
        "type": "SYSTEM",
        "name": "BIRTHDAY",
        "regex_set": [
            {
                "regex": "[0-9]{6}",
            },
        ],
    },
    {
        "type": "SYSTEM",
        "name": "CONFIRM",
        "phrase_set": [
            {
                "phrase": "YES",
                "synonym_set": [
                    {
                        "synonym": "예",
                    },
                    {
                        "synonym": "네",
                    },
                    {
                        "synonym": "응",
                    },
                    {
                        "synonym": "맞아",
                    },
                    {
                        "synonym": "맞아요",
                    },
                    {
                        "synonym": "그래",
                    },
                ],
            },
            {
                "phrase": "NO",
                "synonym_set": [
                    {
                        "synonym": "아니",
                    },
                    {
                        "synonym": "아니오",
                    },
                    {
                        "synonym": "아니요",
                    },
                    {
                        "synonym": "싫어",
                    },
                    {
                        "synonym": "싫어요",
                    },
                    {
                        "synonym": "없어",
                    },
                ],
            },
        ],
    },
]
```

### 시연 시나리오

#### '납부 금액 확인' 후 '납부 방법 변경' 중 FAQ 발생

```
> 안녕하세요 스프링프로젝트 챗봇입니다
>> 안녕하세요? 스프링 프로젝트 챗봇입니다. 무엇을 도와드릴까요?

이번 달 얼마 내?
> 고객님이 문의하신 내용이 납부금액 확인 인가요?
>> 고객님이 문의하신 내용이 납부 금액 확인인가요?

응
> 인터넷인가요? 모바일인가요?

핸드폰 요금
> 이번 달 핸드폰 납부 요금은 1000원입니다 더 문의하실 내용이 있으면 말씀해주세요
>> 이번 달 핸드폰 납부 요금은 1000원입니다. 더 문의하실 내용이 있으면 말씀해주세요.

납부 방법 변경해줘
> 고객님이 문의하신 내용이 납부방법 변경 대표 인가요?
>> 고객님이 문의하신 내용이 납부 방법 변경인가요?

응
> 인터넷인가요? 모바일인가요?

모바일
> 모바일 요금 납부 방법 알려드리겠습니다. E-MAIL로 납부 중입니다. 어떤 납부 방법으로 변경 해드릴까요?
>> 모바일 요금 납부 방법 알려드리겠습니다. 고객님은 현재 이메일로 납부 중입니다. 어떤 납부 방법으로 변경 해드릴까요?

와이파이 패지키도 종류가 있나요?
> 순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다. 납부방법 변경 대표을 계속 진행할까요?
>> 순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다. 납부 방법 변경을 계속 진행할까요?

그래
> 모바일 요금 납부 방법 알려드리겠습니다. E-MAIL로 납부 중입니다. 어떤 납부 방법으로 변경 해드릴까요?
>> 모바일 요금 납부 방법 알려드리겠습니다. 고객님은 현재 이메일로 납부 중입니다. 어떤 납부 방법으로 변경 해드릴까요?

카카오페이로 바꿔줘
> 모바일 요금 납부방법을 카카오페이로 변경했습니다 더 문의하실 내용이 있으면 말씀해주세요
>> 모바일 요금 납부 방법을 카카오페이로 변경했습니다. 더 문의하실 내용이 있으면 말씀해주세요.

아니 없어
> 안녕히 가세요
>> 지금까지 스프링 프로젝트 챗봇이었습니다. 감사합니다.
```

#### '납기일 문의' 중 '납기일 변경'
```
> 안녕하세요 스프링프로젝트 챗봇입니다
>> 안녕하세요? 스프링 프로젝트 챗봇입니다. 무엇을 도와드릴까요?

인터넷 요금 언제 내?
> 고객님이 문의하신 내용이 납기일 문의 인가요?
>> 고객님이 문의하신 내용이 납기일 문의인가요?

응
> 납기일 문의는 본인만 하실 수 있습니다. 본인이신가요?

맞아
> 고객님의 생년월일 6자리를 입력해주세요
>> 고객님의 생년월일 6자리를 입력해주세요.

납기일 확인 전에 자동납부 날짜 먼저 바꿀게
> 고객님이 문의하신 내용이 납기일 변경 인가요?
>> 고객님이 문의하신 내용이 납기일 변경인가요?

응
> 납기일 변경은 본인만 하실 수 있습니다. 본인이신가요?

응
> 고객님의 생년월일 6자리를 입력해주세요
>> 고객님의 생년월일 6자리를 입력해주세요.

010101#
> 며칠로 변경해드릴까요?

25일
> 납기일이 25일 로 변경되었습니다 납기일 문의을 계속 진행할까요?
>> 납기일이 25일로 변경되었습니다. 납기일 문의를 계속 진행할까요?

그래
> 고객님의 인터넷 요금 납기일은 25일 입니다 더 문의하실 내용이 있으면 말씀해주세요
>> 고객님의 인터넷 요금 납기일은 25일입니다. 더 문의하실 내용이 있으면 말씀해주세요.

없어
> 안녕히 가세요
>> 지금까지 스프링 프로젝트 챗봇이었습니다. 감사합니다.
```

## 채널 정보
### 페이스북
#### 페이스북 테스트 계정
- id: joonoh.oh95@gmail.com
- pwd: new1234!
#### 페이스북 메신저 사용방법
- 페이스붓 페이지 주소: https://www.facebook.com/Spring-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-100324435719020/
- 위 페이지 접속 후 "메시지 보내기"를 클릭하여 챗봇 테스트
- 발화 입력 후 봇 응답이 올때까지 delay가 발생할 수도 있습니다.

## 개발환경
### 서버
- 서버 ip: 211.253.26.219
- 관리자 계정
    - id: root
    - pwd: new1234!
- 사용자 계정
    - id: vbuser
    - pwd: new1234!
- 접속 명령어
    ```
    ssh root@211.253.26.219
    ```
### 서비스 정보
|서비스|접근 정보|비고|
|------|---|---|
|config-server|http://211.253.26.219:9000|spring cloud config 서버|
|service-discovery-server|http://211.253.26.219:9001|spring cloud netflix eureka 서버|
|channel-manager|http://211.253.26.219:8000|spring cloud gateway 사용|
|dialogue-manager|http://211.253.26.219:8001||
|ai-core-adaptor|||
|nlu-server|http://211.253.26.219:9091||
|jenkins|http://211.253.26.219:8080|id/pwd : admin/new1234! / gitlab 소스를 가져와 도커 컨테이너로 배포|
|elastic search|http://211.253.26.219:9200|단일 노드로 구성 (클러스터 X)|
|redis|http://211.253.26.219:6379|단일 노드로 구성 (클러스터 X)|
|postgresql|http://211.253.26.219:5432|id/pwd : posgres/new1234!|

### git 프로젝트
- gitlab: https://gitlab.com/mtbra1n/spring-2021

## CI/CD
### docker 설치
```
sudo yum -y update
sudo yum -y install docker docker-registry
sudo systemctl start docker
sudo docker ps
sudo systemctl enable docker
sudo systemctl status docker

출처: https://coding-start.tistory.com/326
```
### docker-compose 설치
```
rm -f /usr/local/bin/docker-compose
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose

출처: https://stackoverflow.com/questions/67010408/unable-to-start-docker-container-from-docker-compose-unknown-flag-iidfile
```
### jenkins 설치
- id / pwd : admin / new1234!
```bash
sudo docker pull jenkins/jenkins

sudo docker volume create jenkins-data

sudo docker volume ls

sudo chmod 666 /var/run/docker.sock

docker run -d -p 8080:8080 --privileged=true -v /var/run/docker.sock:/var/run/docker.sock --name jenkins -v jenkins-data:/var/jenkins_home getintodevops/jenkins-withdocker:lts

# 초기 암호 확인 (73a6bc1801264895b341cb20152f5a26)
sudo docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

출처: https://coding-start.tistory.com/326
출처: https://anomie7.tistory.com/50
```

### jenkins와 gitlab 연동
- 참조: https://oingdaddy.tistory.com/103
### jenkins로 docker에 배포
```bash
JAR_FILE='channel-manager-0.0.1-SNAPSHOT.jar'

cd ./aicc-spring/channel-manager
./gradlew build -x test

cd ./docker
cp ../build/libs/$JAR_FILE .
docker build --tag channel-manager:1.0 --build-arg JAR_FILE=$JAR_FILE .

# 실행 중인 도커 중지
docker container stop channel-manager

docker run -d -p 8000:8000 --rm --network voicebot-container-network --name channel-manager channel-manager:1.0

```

### docker container 간 통신
```bash
# docker network 생성
docker network create voicebot-container-network


출처: https://velog.io/@alvin/Referring-4.-Docker-Network%EB%A1%9C-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EC%82%AC%EC%9D%B4-%ED%86%B5%EC%8B%A0%ED%95%98%EA%B8%B0
```

## 발화문 추론 API 호출 방법

### 요청

```bash
curl --location --request POST 'http://211.253.26.219:9091/nluadaptor/inference/' \
--header 'Content-Type: application/json' \
-d '{
  "utterances": [
    "이번달 얼마 내?",
    "핸드폰 요금",
    "납부 방법 변경 해줘",
    "WIFI 패키지도 종류가 있나요?",
    "그래",
    "카카오페이로 변경 해주세요",
    "인터넷 요금",
    "납기일 문의예요",
    "납기일 확인 전에 자동납부 날짜 먼저 바꿀게요",
    "네",
    "네",
    "123456#",
    "25일",
    "네"
  ]
}'
```

### 응답

```json
[
    {
        "utterance": "이번달 얼마 내?",
        "intents": [
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.8318542838096619
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.17793279886245728
            },
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.09515319764614105
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.06840139627456665
            },
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.06166929006576538
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/MON",
                "value": "이번달",
                "pos_start": 0,
                "pos_end": 2,
                "type": "synonym",
                "phrase": "$this_month"
            }
        ],
        "answers": [
            {
                "score": 2.0423226,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            },
            {
                "score": 0.31866914,
                "answer": "인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."
            }
        ]
    },
    {
        "utterance": "핸드폰 요금",
        "intents": [
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.5478935241699219
            },
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.1855393648147583
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.18210606276988983
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.17237402498722076
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.1659400761127472
            }
        ],
        "entities": [
            {
                "entity": "USER/LOB",
                "value": "핸드폰",
                "pos_start": 0,
                "pos_end": 2,
                "type": "synonym",
                "phrase": "모바일"
            },
            {
                "entity": "USER/LOB",
                "value": "폰",
                "pos_start": 2,
                "pos_end": 2,
                "type": "synonym",
                "phrase": "모바일"
            }
        ],
        "answers": [
            {
                "score": 0.82525283,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            },
            {
                "score": 0.5754429,
                "answer": "인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."
            }
        ]
    },
    {
        "utterance": "납부 방법 변경 해줘",
        "intents": [
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.747612714767456
            },
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.15820924937725067
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.11283211410045624
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.031271692365407944
            },
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.018468432128429413
            }
        ],
        "entities": [],
        "answers": [
            {
                "score": 1.0049641,
                "answer": "인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."
            },
            {
                "score": 0.23252608,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            }
        ]
    },
    {
        "utterance": "WIFI 패키지도 종류가 있나요?",
        "intents": [
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.9350236654281616
            },
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.08205395936965942
            },
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.07661369442939758
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.06832979619503021
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.06421404331922531
            }
        ],
        "entities": [],
        "answers": [
            {
                "score": 0.82525283,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            }
        ]
    },
    {
        "utterance": "그래",
        "intents": [
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.8677433133125305
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.13758152723312378
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.13564550876617432
            },
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.13461558520793915
            },
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.1339903473854065
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/CONFIRM",
                "value": "그래",
                "pos_start": 0,
                "pos_end": 1,
                "type": "synonym",
                "phrase": "YES"
            }
        ],
        "answers": []
    },
    {
        "utterance": "카카오페이로 변경 해주세요",
        "intents": [
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.7837361693382263
            },
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.2429099977016449
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.07830920815467834
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.02467811293900013
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.012883174233138561
            }
        ],
        "entities": [
            {
                "entity": "USER/PAYMENT_METHOD",
                "value": "카카오페이",
                "pos_start": 0,
                "pos_end": 4,
                "type": "synonym",
                "phrase": "$payment_method"
            }
        ],
        "answers": [
            {
                "score": 1.0049641,
                "answer": "인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."
            },
            {
                "score": 0.23252608,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            }
        ]
    },
    {
        "utterance": "인터넷 요금",
        "intents": [
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.48556774854660034
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.2505702078342438
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.2029649317264557
            },
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.1814025491476059
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.1088436171412468
            }
        ],
        "entities": [
            {
                "entity": "USER/LOB",
                "value": "인터넷",
                "pos_start": 0,
                "pos_end": 2,
                "type": "phrase"
            }
        ],
        "answers": [
            {
                "score": 1.1069466,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            },
            {
                "score": 0.73260593,
                "answer": "인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."
            }
        ]
    },
    {
        "utterance": "납기일 문의예요",
        "intents": [
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.5129829049110413
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.2753902077674866
            },
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.09824170917272568
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.06599829345941544
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.02858041599392891
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/CONFIRM",
                "value": "예",
                "pos_start": 6,
                "pos_end": 6,
                "type": "synonym",
                "phrase": "YES"
            }
        ],
        "answers": [
            {
                "score": 1.3236332,
                "answer": "인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."
            },
            {
                "score": 0.21706991,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            }
        ]
    },
    {
        "utterance": "납기일 확인 전에 자동납부 날짜 먼저 바꿀게요",
        "intents": [
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.8892092704772949
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.7895545959472656
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.011582426726818085
            },
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.004720640368759632
            },
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.0007797676371410489
            }
        ],
        "entities": [],
        "answers": [
            {
                "score": 1.5592647,
                "answer": "인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."
            },
            {
                "score": 0.21706991,
                "answer": "순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."
            }
        ]
    },
    {
        "utterance": "네",
        "intents": [
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.931847095489502
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.10994765162467957
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.09707329422235489
            },
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.08523676544427872
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.07649587839841843
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/CONFIRM",
                "value": "네",
                "pos_start": 0,
                "pos_end": 0,
                "type": "synonym",
                "phrase": "YES"
            }
        ],
        "answers": []
    },
    {
        "utterance": "네",
        "intents": [
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.931847095489502
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.10994765162467957
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.09707329422235489
            },
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.08523676544427872
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.07649587839841843
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/CONFIRM",
                "value": "네",
                "pos_start": 0,
                "pos_end": 0,
                "type": "synonym",
                "phrase": "YES"
            }
        ],
        "answers": []
    },
    {
        "utterance": "123456#",
        "intents": [
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.8327212333679199
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.1981024146080017
            },
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.14735160768032074
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.1457497626543045
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.14005959033966064
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/BIRTHDAY",
                "value": "123456",
                "pos_start": 0,
                "pos_end": 5,
                "type": "regex"
            }
        ],
        "answers": []
    },
    {
        "utterance": "25일",
        "intents": [
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.6792857050895691
            },
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.6284176707267761
            },
            {
                "intent": "USER/납기일_문의",
                "confidence": 0.18376797437667847
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.08766059577465057
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.04395400360226631
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/DAY",
                "value": "5일",
                "pos_start": 1,
                "pos_end": 2,
                "type": "regex"
            },
            {
                "entity": "SYSTEM/DAY",
                "value": "25일",
                "pos_start": 0,
                "pos_end": 2,
                "type": "regex"
            }
        ],
        "answers": []
    },
    {
        "utterance": "네",
        "intents": [
            {
                "intent": "SYSTEM/negative",
                "confidence": 0.931847095489502
            },
            {
                "intent": "USER/납부금액_확인",
                "confidence": 0.10994765162467957
            },
            {
                "intent": "USER/납기일_변경",
                "confidence": 0.09707329422235489
            },
            {
                "intent": "USER/납부방법_변경_대표",
                "confidence": 0.08523676544427872
            },
            {
                "intent": "SYSTEM/FAQ",
                "confidence": 0.07649587839841843
            }
        ],
        "entities": [
            {
                "entity": "SYSTEM/CONFIRM",
                "value": "네",
                "pos_start": 0,
                "pos_end": 0,
                "type": "synonym",
                "phrase": "YES"
            }
        ],
        "answers": []
    }
]
```


## FAQ 데이터 색인 및 검색 방법
### kt_100_faq 인덱스 생성
- nori tokenizer를 사용하게 설정
```bash
curl --location --request PUT 'http://211.253.26.219:9200/kt_100_faq' \
--header 'Content-Type: application/json' \
-d '{
    "settings": {
        "analysis": {
            "analyzer": {
                "nori": {
                    "tokenizer": "nori_tokenizer"
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "questions": {
                "type": "text",
                "analyzer": "nori"
            },
            "answer": {
                "type": "text",
                "analyzer": "nori"
            }
        }
    }
}'
```
### kt_100_faq 인덱스에 document bulk 색인
```bash
curl --location --request POST curl --location --request POST 'http://211.253.26.219:9200/kt_100_faq/_bulk' \
--header 'Content-Type: application/json' \
-d '{"index":{"_id":"0"}}
{"questions": ["인터넷 TV 약정 갱신은 무엇인가요", "약정 갱신이 뭐예요?", "재계약하려고 하니까 약정 갱신을 하라던데 그건 뭐예요?", "재약정 대신에 약정 갱신을 추천받았는데 약정 갱신이 어떤 거예요?"], "answer":"인터넷, TV 약정 갱신은 약정만료 고객 대상으로 약정을 다시 가입하는 제도이며, 3년약정 갱신할 경우 요금할인과 사은품 중 하나를 선택할 수 있어요. 단, 재약정 할인, 장기할인 혜택 등을 중복으로 제공하지 않습니다."}
{"index":{"_id":"1"}}
{"questions": ["GiGA Wi 인터넷 최대 1G의 이용요금은 어떻게 되나요?", "기가 와이 1기가 인터넷은 얼마인가요?"], "answer":"순 망내무한 선택형 300분 2GB 요금제 월정액은 부가세 포함 49720원입니다."}
'
```
- 현재는 위 2개 문서만 색인되어 있음.

### kt_100_faq 인덱스에 색인된 데이터 확인
- http://211.253.26.219:9200/kt_100_faq/_search?pretty

### kt_100_faq 인덱스에서 문서 검색
- http://211.253.26.219:9200/kt_100_faq/_search?q=questions:%EC%9D%B8%ED%84%B0%EB%84%B7%20TV%20%EC%95%BD%EC%A0%95%20%EA%B0%B1%EC%8B%A0%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94&pretty
    - ?q=questions: 뒤에 질의문을 작성하면 됨.
    - &pretty는 없어도 됨.

### nori tokenizer 테스트
```bash
curl --location --request GET 'http://211.253.26.219:9200/_analyze' \
--header 'Content-Type: application/json' \
-d '{
    "tokenizer": "nori_tokenizer",
    "text": [
        "인터넷 TV 약정 갱신은 무엇인가요"
    ]
}'
```

## DB 설치
### redis 설치
```
docker pull redis

docker images

docker network create redis-net

docker run --name redis01 -p 6379:6379 --network voicebot-container-network -d redis redis-server --appendonly yes

# redis-cli로 접근
docker run -it --network voicebot-container-network --rm redis redis-cli -h redis01

출처: https://dingrr.com/blog/post/redis-도커docker로-redis-설치하기
```
### postgresql 설치
```
docker pull postgres

docker images

docker volume create postgres-data

docker volume ls

docker run -d -p 5432:5432 --name postgres01 -e POSTGRES_PASSWORD=new1234! -v postgres-data:/var/lib/postgresql/data postgres

출처: https://www.postgresql.kr/blog/when_useing_docker_official_postgres_image.html
```

## 프로젝트 구성
### 프로젝트 구조
```bash
aicc-spring
├── channel-manager
├── dialogue-manager
├── action-executor
├── ai-core-adaptor
├── nlu-server
├── eureka-server
└── config-server
```

- api 게이트웨이: channel-manager
- micro 서비스: dialogue-manager, action-executor, ai-core-adaptor, nlu-server
- 서비스 discovery: eureka-server
- config 관리: spring-config-server

## 하드웨어 구성
- 각 컴포넌트를 1개의 vm으로 구성, 각 vm은 2vCore / 4GB 예상
- 위 컴포넌트 이외 mw vm 필요
    - redis (1대, 개발서버는 클러스터 없이 구성)
    - posgres (1대, 개발서버는 클러스터 없이 구성)
    - ~~kafka (필요 시 도입)~~
- 총 vm 개수: 9대

## 소프트웨어 구성
### 기본 구성 정보
- spring boot 버전: 2.5.2
- java 버전: 8
- 빌드: gradle
- python 버전: 3.x

### 상세 구성 정보
- **channel-manager** => java, spring boot, spring cloud gateway, spring cloud netflix eureka client, lombok, gson
- **dialogue-manager** => java, spring boot, spring cloud config client, spring cloud netflix eureka client, lombok, gosn
- **action-executor** => java, spring, spring cloud config client, spring cloud config client, lombok, gson
- **ai-core-adapto** => java, spring, spring cloud config client, spring cloud config client, lombok
- **nlu-server** => python, pytorch, pytorch lightning, django, spring cloud config client, spring cloud netflix eureka client
- **eureka-server** => java, spring boot, spring cloud netflix eureka server, spring cloud config client, lombok
- **config-server** => java, spring boot, spring cloud config server, spring cloud bus, lombok


<!-- EAARCoHxERy0BAMYwu1JXLoxoaralJmJVQAmtNwTFZAV7PkNx7SwGhIjy6ZAykrw2FEoaqHXeSZBEIbrQMZBiFXz9NmDIA9KJJhIZBA3iXSvOp8tKsVwHDnXCHh3ZBRYKXqSWkXpLWHwJvQ8MVmOsaZCaVZAHjlGM26QqqqZAoNiQKtEpLdQp3JQH2 -->