Machine learning/Chatbot

[위로봇 프로젝트]. 오복이 육아일기 3일차 - 데이터 추가하기

Acdong 2022. 12. 26. 21:47
728x90

2022.12.06 - [Chatbot] - [위로봇 프로젝트]. 오복이 육아일기 2일차 - 설계

[위로봇 프로젝트]. 오복이 육아일기 2일차 - 설계

2022.12.06 - [Chatbot] - [위로봇 프로젝트]. 오복이 육아일기 1일차 - 소개 위로봇 오복이의 프로세스는 아주 간단하게 설계되어있습니다. 웹 서버는 Python 언어를 기반으로한 FastAPI를 사용했습니다.

acdongpgm.tistory.com


챗봇 사용 데이터

1. 송영숙 님의 챗봇 데이터
https://github.com/songys/Chatbot_data
2. AI-HUB 웰니스 상담 데이터
https://aihub.or.kr/opendata/keti-data/recognition-laguage/KETI-02-006
3. AI-HUB 감성대화 말뭉치
https://aihub.or.kr/aihubdata/data/view.do?currMenu=115&topMenu=100&aihubDataSe=realm&dataSetSn=86
위 3가지의 데이터를 종합해서 사용했 대답이 질문으로 끝나는 경우는 제거 *싱글턴 대화이기 때문


위 데이터를 합쳐서 질문과 답변만 남겨서 하나의 파일로 만들었다.
거의 10만건의 QA 쌍 데이터를 확보 *데이터셋은 직접 다운받으시길 바랍니다.

데이터 예시)

질문 답변
상실감이 느껴지고 내가 진 것 같은 기분이 들어요. 마음이 헛헛해서 힘드셨군요. 돌아보면 즐거웠던 일, 행복했던 일, 뿌듯했던 일이 많을 거예요. 너무 상심 마세요.
내가 한심스럽게 느껴지니까 그냥 한숨만 나오고 자꾸 눈물을 쏟게 되는것 같아 자존감이 떨어져 속상하고 고민이 많이 드셨겠어요.
그렇게 앉아서 몇 시간을 울었거든요. 00님이 걱정되네요. 얼른 기분이 좀 나아지셔야 할 텐데 말이에요.
한 발자국도 못 움직일 것 같고 온몸에 힘이 빠지고… 많이 힘드셨겠군요. 휴식을 충분히 취하셔야 할 것 같아요.
그럼 또 나는 엄청 걱정이 되는 거야. 신경이 예민해지셨군요. 00님이 받는 스트레스가 컸을 것 같아 저 또한 걱정스러워요.
조금밖에 못 자서 미치기 일 보 직전이야 수면의 질이 떨어지면 피곤이 쌓여서 낮 생활에도 안 좋은 영향을 끼치잖아요. 00님 힘드셨겠어요.


좋은 대답도 있지만 성의없는 답변도 많다.
하지만 이런 데이터가 존재하기 때문에 프로젝트도 가능한 것!
인공지능 프로젝트는 데이터로 부터 아이디어가 나오는게 대부분인 것 같다.
데이터가 없으면 말짱꽝..


이제 전처리 완료된 데이터를 엘라스틱 서치 검색엔진에 업로드 해주어야한다.
엘라스틱서치는 데이터베이스로써의 기능과 검색엔진 기능 두 가지를 동시에 할 수 있다.

엘라스틱서치 검색엔진은 TF-IDF 의 길이 보정 버전인 BM25 알고리즘을 통해 검색한다.
간단하게 설명하면 중요키워드 기반으로 검색의 품질을 높힌다고 볼 수 있다.

딱히 구현할 필요는 없고 DB의 스키마처럼 엘라스틱서치 맵핑을 정의해서 데이터를 Index(Table과 동일)에 넣어주기만하면
한국어 노리(Nori) 토크나이저가 자동으로 토큰으로 분리해서 저장한다.

엘라스틱 서치 버전은 현시점 가장 최신버전인
8.5.2 버전을 사용했다.

2022.04.01 - [ElasticSearch] - [ElasticSearch] . ES , KB Download , setting - (2)
설치 가이드는 이전 글 참고

mapping.json

{
    "settings": {
        "number_of_shards": 5,
        "number_of_replicas": 1,
        "index": {
            "analysis": {
                "analyzer": {
                    "nori_token_analyzer": {
                        "type": "custom",
                        "tokenizer": "nori_base_tokenizer"
                    }
                },
                "tokenizer": {
                    "nori_base_tokenizer": {
                        "type": "nori_tokenizer",
                        "decompound_mode": "none",
                        "discard_punctuation": false
                    }
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "system": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 512,
                        "doc_values": false
                    }
                }
            },
            "user": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    },
                    "nori": {
                        "type": "text",
                        "analyzer": "nori_token_analyzer"
                    }
                }
            },
            "idx": {
                "type": "integer"
            }
        }
    }
}

upload.py

import pandas as pd
from pathlib import Path
import os
import json
from elasticsearch import Elasticsearch, helpers
from config import ELASTIC_HOST

BASE_DIR = Path(__file__).resolve().parent.parent
DATA_PATH = os.path.join(BASE_DIR,'data','base_datasets.xlsx')
MAPPING_PATH = os.path.join(BASE_DIR,'mapping.json')
MAPPING = json.load(open(MAPPING_PATH))

df = pd.read_excel(DATA_PATH)
df['idx'] = df.index

client = Elasticsearch(hosts=ELASTIC_HOST)

def filterKeys(document, use_these_keys):
    return {key: document[key] for key in use_these_keys}

def doc_generator(df, index):
    df_iter = df.iterrows()
    cols = df.columns.to_list()
    temp = list()

    for idx, document in df_iter:
        temp.append(
            {
                "_index": index,
                "_id": f"{idx}",
                "_source": filterKeys(document, cols),
            }
        )
    return temp

def upload(df, index):
    client.indices.create(index=index, body=MAPPING)
    data = doc_generator(df, index)
    helpers.bulk(client, data)

upload(df,"chatbot")
client.close()


데이터 업로드 확인

curl -GET http://localhost:9200/_cat/indices\?v


데이터 조회

curl -GET http://localhost:9200/chatbot/_doc/20 #20번째 데이터

반응형