Vector DB로 ChatGPT 보정하기 (feat. OpenAI)

Vector DB로 ChatGPT 보정하기 (feat. OpenAI)
Photo by Jonathan Kemper / Unsplash

Vector DB를 알아보다가 간단하게 OpenAI 에서 부족한 정보를 Vector DB를 통해 보완하는 과정을 남겨본다.

1. Vector DB에 대한 소개

1) Vector

일반적으로 벡터는 크기와 방향을 가지고 있는 수치를 나타내는 개념으로 다양한 분야에서 중요한 개념으로 사용된다.

2) Vector Embedding

Vector Embedding은 단어나 문장 또는 이미지, 동영상등 다양한 형태의 특징 데이터를 추출해서 고차원 벡터로 변환하는 것이라고 볼 수 있겠다. 이렇게 특징을 추출해서 고차원 벡터로 만들어 유사성이 짙은 패턴을 파악하거나 측정하는 등의 응용이 가능해 진다.

3) Vector Database

Vector Database 는 Vector Embedding을 저장하고 관리하는 데이터베이스다. 이러한 데이터베이스는 Vector Embedding을 효율적으로 저장하고 검색하는 데 사용하고 Vector Embedding의 활용처가 그러하듯 다음과 같이 동일한 사용처에 더욱 편리하게 사용할 수 있겠다.

  • 유사도검색 (Similarity Search)
  • 추천시스템 (Recommendation Systems)
  • 자연어 처리(Natural Language Processing)

4) Vector Database 종류

TaskVibes: ADHD Simple Manage - Apps on Google Play
ADHD 를 겪는 사람들을 위한 일정관리 앱

2. Vector DB, Chroma DB 설치 사용

: Chroma DB 로 드라마 데이터 저장하고 검색하기

1) Korean Dramas Dataset (Top 250 K-Drama)
Top 250 Korean Dramas (KDrama) Dataset | Kaggle

2) Dataset Load

3) Chroma DB 사용
: 📖 API Cheatsheet | Chroma (trychroma.com)

# movie 데이터 로드
import pandas as pd
df = pd.read_csv("./kdrama.csv")

filter_df = df.drop(["Aired Date","Aired On","Duration","Content Rating","Production companies", "Rank"], axis=1);

import chromadb
client = chromadb.PersistentClient(path="../data")

collection = client.get_or_create_collection(
    name="k-drama",
    metadata={"hnsw:space": "cosine"}
)

# 데이터 준비
# 인덱스
ids = []
# 메타데이터
doc_meta = []
# 벡터로 변환 저장할 텍스트 데이터로 ChromaDB에 Embedding 데이터가 없으면 자동으로 벡터로 변환해서 저장한다고 한다. 
documents = []

for idx in range(len(filter_df)):
    item = filter_df.iloc[idx]
    id = item['Name'].lower().replace(' ','-')
    document = f"{item['Name']}: {item['Synopsis']} : {str(item['Cast']).strip().lower()} : {str(item['Genre']).strip().lower()}"
    meta = {
        "rating" : item['Rating']
    }
    
    ids.append(id)
    doc_meta.append(meta)
    documents.append(document)

# DB 저장
collection.add(
    documents=documents,
    metadatas=doc_meta,
    ids=ids
)
# DB 쿼리
collection.query(
    query_texts=["medical drama about doctors"],
    n_results=5,
)

4) Chroma DB, 쿼리

"의사에 관한 의료 드라마"를 쿼리 했는데, 전체적으로 잘나온듯 하다.

  • Doctor John (의사요한)
  • Dr. Romantic 2 (낭만닥터2)
  • Hospital Playlist (슬기로운 의사생활)
  • Doctor Prisoner (닥터프리즈너)
  • God's Quiz: Reboot (신의 퀴즈:리부트)
{
   "ids":[
      [
         "doctor-john",
         "dr.-romantic-2",
         "hospital-playlist",
         "doctor-prisoner",
         "god's-quiz:-reboot"
      ]
   ],
   "distances":[
      [
         0.34366244077682495,
         0.4573204517364502,
         0.4621426463127136,
         0.48155128955841064,
         0.5326414568521789
      ]
   ],
   "metadatas":[
      [
         {
            "rating":8.5
         },
         {
            "rating":8.7
         },
         {
            "rating":9.1
         },
         {
            "rating":8.4
         },
         {
            "rating":8.3
         }
      ]
   ],
   "embeddings":"None",
   "documents":[
      [
         "Doctor John: “Doctor John” is a medical drama about doctors specializing in pain management. In a refreshing take on the genre, “Doctor John” will portray the doctors’ search for the cause of their patients’ mysterious pain as a thrilling chase, almost like a detective hunting down the perpetrator behind an unsolved crime.  : ji sung, lee se young, lee kyu hyung, hwang hee, jung min ah, kwon hwa woon : mystery,  romance,  life,  medical",
         "Dr. Romantic 2: A “real doctor” story set in a small, humble hospital called Doldam Hospital. It is a story about people who meet Kim Sa Bu, a genius doctor, and discover “real romance.” : han seok kyu, ahn hyo seop, lee sung kyung, kim joo heon, shin dong wook, so ju yeon : romance,  drama,  medical,  melodrama",
         "Hospital Playlist: The stories of people going through their days that are seemingly ordinary but actually special, at the hospital, a place known as the microcosm of life, where someone is being born and someone's life meets their ending. The five doctors are long-time friends of 20 years who started their undergrad in 1999 in the same medical school and now are colleagues in the same hospital and have a band together. : jo jung suk, yoo yeon seok, jung kyung ho, kim dae myung, jeon mi do, shin hyun bin : friendship,  romance,  life,  medical",
         "Doctor Prisoner: Doctor Prisoner centers around an ace doctor in a university hospital’s emergency care center, a skilled professional who treats his patients with full devotion and without discrimination. However, his medical license gets suspended as a result of a medical malpractice incident that arises when the hospital board director causes a ruckus. He then gets his certificate as a medical internist and applies to work at a prison, where his plan is to cozy up to all the bigshots there—business tycoons, celebrities caught for doing drugs, sports stars guilty of gambling—and to win allies, with the ultimate goal of getting revenge against the hospital that ousted him. To do so, he’ll get rid of the existing prison chief doctor and claim the spot for himself. : namkoong min, kwon na ra, kim byung chul, choi won young, lee da in, jin hee kyung : thriller, law, crime, medical",
         "God's Quiz: Reboot: This is a drama about elite doctors and forensic scientists investigating mysterious deaths and solving mysteries related to rare diseases. Han Jin Woo is the tortured medical genius with a miracle brain that has been through its share of trouble. After he gets involved in an unexpected case, he returns to the medical examiner office for the first time in 4 years. : ryu deok hwan, yoon joo hee, park  hyo joo, park joon myun, kim ki doo, kim jae won : mystery, medical"
      ]
   ]
}

5) Chroma DB, 쿼리 필터링
: 아래 코드 처럼, where 절로 메타데이터에 넣은 릴리즈 연도를 필터링하거나 where_document 로 본문내 특정 단어를 필터링 할 수도 있다.

250개의 데이터는 부족해서 그렇지 필터링을 하면 거리가 좀 먼 데이터가 나오기도 했다.

collection.query(
    query_texts=["medical drama about doctors"],
    n_results=5,
    #where={"rating": { "$gt" : 8.0 }},
    #where_document={"$contains": "yoo yeon seok"}
)
TaskVibes: ADHD Simple Manage - Apps on Google Play
ADHD 를 겪는 사람들을 위한 일정관리 앱

3. OpenAI 에 질의 하기

OpenAI 는 한국 드라마에 대해 얼마나 알고 있을까?
: 전체적으로 크게 문제는 없어 보이는데, gpt-3.5 에서는 다소 정확하지 않은 정보를 주고 있는 듯 하다. ("김비서가 왜 그럴까" 라는 드라마는 메디컬 드라마나 의사가 등장하는 드라마가 아닌 걸로 알고 있다)

4. OpenAI 가 보정된 데이터를 바탕으로 답변을 하게 해보자

1) OpenAI API (Chat completions) 사용예시

import openai

openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
  	# 시스템 : 도우미의 동작을 설정
  	{"role": "system", "content": "You are a helpful assistant."},
  	# 사용자 : 사용자의 질문을 설정
  	{"role": "user", "content": "Who won the world series in 2020?"},
  	# 도우미 : 대화의 컨텍스트를 유지하기 위해 알아야 할 것을 전달
  	{"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
    ]
)

2) ChatGPT 3.5 turbo 에 질의하기
: ChatGPT 3.5 turbo 에 동일한 질문을 해보니 아래와 같이 만족스런 답변을 줬다.

3) VectorDB 검색결과를 ChatGPT 3.5 turbo 에 전달하여 응답받기
: ChatGPT 에 assistant 에 VectorDB 에서 정재한 json 만 전달했는데, 영문도 잘 번역해서 순서에 맞게 답변해주고 있다.

vector_res = collection.query(
    query_texts=["medical drama about doctors"],
    n_results=5,
)

srchres = [];
for v in vector_res['documents'][0]:
    item = v.split(':')
    srchres.append({
        "title" : item[0].strip(),
        "synopsis" : item[1].strip(),
        "cast" : item[2].strip(),
        "genre" : item[3].strip(),
    })
    
completion = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
            {"role": "user", "content": "의사들이 나오는 메디컬 한국 드라마 5개만 추천해줄래? 소개할때 시놉시스와 출연진도 같이 소개해줘"},
            {"role": "assistant", "content": f"{srchres}"},
        ]
    )
    
print(completion["choices"][0]["message"]["content"])
TaskVibes: ADHD Simple Manage - Apps on Google Play
ADHD 를 겪는 사람들을 위한 일정관리 앱

응답 메시지를 아래와 같이 다양하게 조정할 수 있겠다.