[정리] RAG(Retrieval-Augmented GenerationToken)

img.png

서론

최근 AI를 활용해 옵시디언에 정리된 개인 자료들을 더 효과적으로 활용하는 방법에 대해 고민하게 되었다. 그 과정에서, 단순한 질의응답을 넘어 기존 문서를 기반으로 답변을 생성할 수 있는 RAG를 이용해보는것을 고려하고있다.

다만, 무작정 기술을 도입하기보다는 그동안 개념적으로만 들어왔던 RAG, Token, Embedding, Vector DB와 같은 기본 개념들을 먼저 명확히 이해하고 싶었다.

마침 관련 내용을 잘 설명한 강의가 있어 이를 참고하며 학습했고, 이 글에서는 공부하며 익힌 개념들을 정리해보려 한다.

RAG(Retrieval Augmented Generation)

정의

RAG(Retrieval-Augmented Generation)는 LLM(Large Language Model)에 Retrieval System을 결합하는 방식이다

여기서 Retrieval System란, 문서, DB, 지식 베이스(Knowledge Base) 등 외부 정보를 검색할 수 있는 시스템을 의미한다.

LLM은 기본적으로 학습된 지식만을 바탕으로 답변을 생성하지만, 보다 정확하고 최신의 답변을 위해서는 외부 정보를 필요로 한다.

동시에, Retrieval System은 LLM이 거대한 프롬프트로 과부화되는 것을 방지하는 역할도 한다.

실 사례

예를 들어, 우리가 수백 개의 내부 문서(사내 정책, 기술 명세서, 고객 가이드라인, 메뉴얼 등)를 보유한 회사에서 일하고 있다고 가정해보자.

이때, 어떤 질문이 이 문서들 중 하나에 포함된 내용으로 충분히 답변될 수 있다고 하자.

하지만 이 질문을 하기 위해 모든 문서를 한 번에 LLM에게 전달하고 묻는것은 현실적으로 불가능하다.

현실적으로 불가능한 이유는 바로 LLM에는 "context window", 즉 한 번에 처리할 수 있는 정보의 양에 한계가 존재하기 때문이다.

하지만 LLM + RAG 라면, 이 과정은 훨씬 더 효율적으로 처리될 수 있다.

이제 다음에 질문이 생기면, 자연어로 RAG 시스템에 질문하기만 하면 되고, RAG 시스템은 문서들 중에서 가장 관련 있는 정보만을 검색해 이를 기반으로 정확한 답변을 주게된다.

Token

언어 모델에서 Token이란, LLM이 텍스트를 처리할 때 사용하는 최소 단위를 의미한다.

Token은 언어와 문장 구조에 따라 한 글자일 수도 있고, 한 단어일 수도 있다.

예를 들어, "hello" 는 하나의 토큰이지만 "I'm" 은 보통 "I" 와 "m" 두 개의 토큰으로 분리된다.

Token을 이해하는 것이 중요한 이유는 LLM에는 한 번에 처리할 수 있는 토큰 수의 한계, 즉 "context window"가 존재하기 때문이다.

예를 들어, 만약 어떤 PDF 문서가 1,000만 토큰에 달한다면 이를 한 번에 LLM에게 입력하는 것은 불가능하다.

👉 이러한 제약을 해결하기 위해 RAG가 필요해진다.

RAG System 구성

Embedding

vector embedding 이란 단어, 문장, 혹은 이미지까지도 숫자로 표현하는 것을 의미한다.

예를 들어, "cat"이라는 단어는 다음과 같이 표현될 수 있다.

  • [34, 21, 7.5]

이것은 컴퓨터가 "cat"이라는 개념을 이해하는 방식이라고 볼 수 있다.

각 숫자는 "cat"이 가진 특정한 의미적 특징을 나타낸다.

예를 들어, "작다(small)", "털이 있다(furry)" 등과 같은 특성일 수 있다.

예시를 조금 더 들어보면 다음과 같다.

  • Cat → [34, 21, 7.5]
  • Kitten → [33, 8, 2]
  • Elephant → [2, 62, 2]
  • Dog → [47, 8, 2]

이때, vector embedding 안의 각 숫자를 dimension(차원) 이라고 부른다.

의미적으로 유사한 단어들은 서로 가까운 위치에 있는 차원을 가지는 경향이 있다.

즉, 다차원 공간에 vector embedding을 배치했을 때, "cat"이 위치한 지점은 "kitten"이 위치한 지점과 가깝게 된다.

우리는 예시에서 3차원 벡터만 보았지만, 실제로 OpenAI의 "text-embedding-3-large" 같은 모델은 최대 3,072 차원을 각 vector embedding 마다 생성한다.

중요한 점은 "cat" 같은 짧은 단어를 임베딩하든 긴 문단이나 문서를 임베딩하든 항상 3,072 차원을 가진 vector embedding이 생성된다는 것이다.

고차원 임베딩 모델의 장점은 텍스트의 의미를 더 풍부하게 표현할 수 있다는 점이다. 반면 단점은, 임베딩 생성 비용이 증가하고 저장하는 비용 또한 커진다는 점이다.

Embedding 모델 종류

임베딩 모델을 제공하는 서비스는 다양하지만, 자주 접하게 되는 대표적인 모델들을 정리해본다.

  • OpenAI
    • text-embedding-3-small
      • 기본 1536차원
      • 대부분의 유스케이스에 충분
      • 512, 1024 등으로 차원 축소 가능
    • text-embedding-3-large
      • 기본 3072차원
      • 성능은 가장 뛰어나지만 비용이 더 높음
      • 256, 512, 1024, 1536 등으로 축소 가능

두 모델 모두 차원을 줄이더라도 품질 손실이 크지 않다는 장점이 있다.

기타 임베딩 모델 제공자로는

  • Cohere
    • 다국어 지원이 뛰어나 글로벌 서비스에 적합
  • Voyage AI
    • 벤치마크에서 좋은 성능을 보이는 경우가 많음
  • Mistral
    • 빠르게 성장 중인 오픈소스 기반 모델

Vector DB

Vector DB란, 생성된 vector embedding들을 저장하고 검색하기 위한 데이터베이스를 의미한다.

vector를 저장하는 방식은 크게 두 가지가 있다.

  • 전용 Vector DB: Pinecone, Weaviate, ChromaDB, FAISS 등
  • 기존 SQL DB: 구조화된 데이터에 vector 저장

일관성(Consistency)이 중요

RAG 시스템에서 꼭 지켜야할 것 중 하나는 문서와 사용자 쿼리에 동일한 임베딩 모델을 사용하는 것이다.

임베딩을 다른 언어라고 생각해보자.

문서는 text-embedding-3-small로 임베딩하고 사용자 질문은 text-embedding-3-large로 임베딩한다면 서로 같은 의미 공간에 존재하지 않기 때문에 정확한 검색이 불가능해진다.

또한, 같은 모델을 사용하더라도 차원 수는 반드시 동일해야 한다.

예를 들어, 문서를 text-embedding-3-large (1536차원)로 임베딩했다면, 사용자 쿼리 역시 반드시 동일한 모델 + 동일한 차원을 사용해서 임베딩해야한다.

RAG 파이프라인을 설계할 때는 초기에 하나의 임베딩 모델과 차원을 선택하고 끝까지 유지하는 것이 중요하다.

만약 나중에 임베딩 모델이나 차원을 변경한다면, 모든 문서를 다시 임베딩해야 한다.

참고자료