본문 바로가기

STUDY/실전 RAG 기반 생성형 AI 개발

2. 임베딩과 벡터저장소를 활용한 RAG

반응형

 

키워드 검색의 한계

 

검색 엔진이 초기에 의존했던 키워드 매칭 방식은 단어 자체가 일치해야만 문서를 찾을 수 있습니다. 예를 들어 “비오는날 음식”이라는 쿼리로 파전 을 추천하려면, 파전 문서 안에 “비오는날 음식”의 키워드가 정확히 있어야 합니다. 하지만 파전을 설명하는 문서에는 다음과 같이 있습니다. "파전: 한국 요리 중의 하나로서, 반죽한 밀가루에 파를 넣어 부친 전". 문장에 ‘비오는날 음식’이라는 키워드가 없으므로 전통적인 키워드 검색으로는 해당 문서를 찾지 못합니다.즉, 의미와 상관없이 표현이 다르면 검색이 빗나가는 구조적 한계가 존재합니다.

중복되는 키워드가 없기때문에 아무런 문서도 검색되지 않는다

 

 


임베딩이란

 

이러한 문제를 해결하기 위한 대표적인 기술이 바로 임베딩(Embedding) 입니다. 임베딩이란 텍스트를 고차원 벡터 공간으로 변환하는 기술입니다. 그리고 두 텍스트간의 벡터 거리를 비교함으로써, 텍스트 간의 유사도를 확인할 수 있습니다. 예를 들어 ] “비 오는 날 생각나는 음식 뭐가 있을까?”, “파전이 생각나는 날씨다.” 이 두 문장은 키워드로 보면 거의 겹치지 않지만, 실제 의미는 서로 매우 밀접합니다. 임베딩을 적용하면 이 두 문장은 벡터 공간 상에서 가까운 위치에 존재하게 됩니다. 

 

OpenAI에서는 text-embedding-3-small이라는 경량 모델을 제공하고 있습니다. 이 모델은 다음과 같은 특징을 갖습니다. 이 임베딩 모델을 활용하면, “비 오는 날 음식”이라는 질문을 했을 때, “파전”이 포함된 문서가 높은 점수를 받고 검색되는 구조를 만들 수 있습니다.

 

"비오는날 먹을 음식 추천해줘"라는 텍스트가 벡터로 변환되었다.

 


벡터저장소란

 

임베딩이 의미를 간직한 벡터를 만들어 준다 해도, 그 벡터들을 메모리에 흩뿌려 두면 아무 소용이 없습니다. 벡터저장소(Vector Store) 는 이 숫자 덩어리들을 체계적으로 보관하고, “새 쿼리가 들어오면 순식간에 가장 비슷한 벡터들을 찾아내는” 역할을 담당합니다. 일반적인 관계형 데이터베이스가 SELECT ... WHERE id=... 같은 정확 일치 조회에 최적화되어 있다면, 벡터저장소는 근접 검색(Nearest-Neighbor Search) 에 특화되어 있습니다. 즉 벡터저장소는 ‘숫자로 표현된 지식’을 빠르고 유연하게 꺼내 쓸 수 있게 해 주는 특수 DB 입니다.

 

 


임베딩, 벡터저장소를 활용한 RAG 구현

 

!pip install openai==1.55.3 httpx==0.27.2 --force-reinstall
!pip install deeplake==3.9.18
pip install langchain-community

from langchain.vectorstores import DeepLake
from langchain.embeddings import OpenAIEmbeddings
import os
import openai
os.environ['OPENAI_API_KEY'] = ""
openai.api_key = os.getenv("OPENAI_API_KEY")

reference_document_list = [
    "파전: 한국 요리 중의 하나로서, 반죽한 밀가루에 파를 넣어 부친 전.",
    "햄버거: 햄버거(hamburger)는 패티를 구운 후 다양한 부재료와 함께 빵 사이에 끼워 먹는 음식. 전 세계에서 가장 유명한 미국 요리이자 세계화의 바이블급 인지도를 자랑하는 넘버원 패스트푸드이다.",
    "카레: 카레(カレー)는 인도 요리인 커리(curry)가 영국과 일본을 거치며 현지화, 재창조된 음식이다."
]

embedding = OpenAIEmbeddings(model="text-embedding-3-small")

deeplake_path = "./my_deeplake_vectorstore"

vectorstore = DeepLake.from_texts(reference_document_list, embedding=embedding, dataset_path=deeplake_path)

랭체인을 사용해서 OpenAI의 text-embedding-3-small 모델을 적용한 벡터 저장소를 만들었다. 만들어진 벡터저장소를 통해 "비오는날 먹을 음식 추천해줘"라는 문장에 가장 가까운 문서를 찾은 결과, 파전에 대한 문서가 나왔다.

 

import openai
from openai import OpenAI

client = OpenAI()
gptmodel="gpt-4o"

def sendQueryWithVectorSearch(query):
    # Join all lines to form a single string
    best_reference_document = vectorstore.similarity_search(query, k=1)
    prompt = f"다음 질문에 공손하고 친밀하게 응답하세요: {query}\n다음 내용을 참조하세요: {best_reference_document}"

    response = client.chat.completions.create(
        model=gptmodel,
        messages=[
          {"role": "user", "content": prompt}
        ],
      )
    return response.choices[0].message.content.strip()

사용자의 쿼리가 왔을 때, 벡터 스토어에서 문서를 검색해서 LLM에 전달하는 메소드를 만들었다. 이제 "비오는날 먹을 음식 추천해줘"라는 질문에 파전 문서를 참조해서 답변하는걸 볼 수 있다.

반응형

'STUDY > 실전 RAG 기반 생성형 AI 개발' 카테고리의 다른 글

4. 멀티모달 RAG  (1) 2025.06.17
3. RAG 검색 성능 개선  (1) 2025.05.30
1. LLM의 한계와 RAG(검색 증강 생성)  (1) 2025.05.21