12주차 내용 정리 - RAG

해피해피슈크림·2025년 6월 15일

13. Langchain 07: RAG 개요

RAG란?

  • 검색 증강 생성 (Retrieval-Augmented Generation)
  • 모델을 다시 학습시키지 않고, 외부 지식 기반에서 정보를 검색한다.
  • RAG는 "정보 저장" -> "검색, 생성" 두 단계로 나뉜다.

1. 정보 저장

1. Load - 데이터(문서) 불러오기
2. Split - 문서 분할
3. Embed - 임베딩해서 특징 벡터 생성
4. Store - 임베딩 벡터를 Vector DB에 저장

⭐ 왜 벡터 DB? (관계형 DB 말고)

결론부터 말하자면, LLM은 '일치'하는 게 아니라, '유사성'을 가지고 찾아야 하기 때문이다. 일치하는 항목을 찾는 건 관계형 DB, 유사성을 검색하는 건 벡터 DB로 한다.

벡터 데이터베이스는 임베딩 모델 알고리즘의 아웃풋인 벡터 임베딩을 저장한다. 또한 제목, 설명 및 데이터 유형을 포함한 각 벡터의 메타데이터를 저장하며, 메타데이터 필터를 사용하여 쿼리할 수 있다.
벡터 데이터베이스는 이러한 임베딩을 수집하고 저장함으로써 유사성 검색을 빠르게 조회하여 사용자의 프롬프트와 유사한 벡터 임베딩을 일치시킬 수 있다.

예를 들어, "삼국 통일은 어느 나라가 했어?"라는 질문 Input이 들어온다면? 참고 문헌은 고조선/삼국시대/고려시대로 나뉘어져 있다.

벡터DB를 사용한다면 참고 문서 중 유사도가 높은 삼국시대 문서 안에서 답을 찾을 것이다. 반면 관계형 DB는 '일치하는' 항목을 찾기 위해 아래와 같은 코드를 칠 것이다.

select * from table
where 문서내용 like "삼국 통일"

(치고 나서 보니 꽤 잘 친 것 같기도) 하지만 우리가 하려는 건 질문과 유사한 문서를 참고해 답을 찾으려는 거지, 참고 자료 안에서 질문과 일치하는 걸 찾으려는 게 아니다.

따라서 유사도 계산을 위해 정보를 임베딩해 벡터 DB에 저장한다.

2. 검색 및 생성

  1. 검색 (retrive)
  2. 질의 생성 (query)
  3. 응답 생성 (generation)

    원래는 프롬프트에 사용자의 질문만 넣었다면, RAG는 검색 결과도 같이 넣는다.

문서 불러오기 - Document Loader

✅ Langchain을 이용해 RAG를 구현할 때 꼭 Langchain의 Document Loader를 사용해야 하는 건 아니다.

문서 분할 - Chunking

Load한 문서를 지정한 기준의 덩어리(chunk)로 나누는 작업을 진행한다. 이때 LLM을 이용하는 것이 아니라 "알고리즘 적으로" 자른다.

주요 Spliter로는 CharacterTextSpliter와 ReculsiveCharacterTextSpliter가 있다.

CharacterTextSpliter

  • 가장 기본적인 Text spliter이다.
  • 한개의 구분자를 기준으로 분리한다. (default: "\n\n")

ReculsiveCharacterTextSpliter

  • 긴 텍스트를 지정된 최대 길이(chunk_size) 이하로 나누는 데 효과적인 텍스트 분할기(splitter)이다.

  • 여러 구분자(separators)를 순차적으로 적용한다.

    1. 두 개의 줄바꿈 문자 ("\n\n")
    2. 한 개의 줄바꿈 문자 ("\n")
    3. 공백 문자 (" ")
    4. 빈 문자열 ("")
  • 작동 방식

    1. 먼저 가장 높은 우선순위의 구분자("\n\n")로 분할을 시도한다.
    2. 분할된 조각 중 chunk_size를 초과하는 조각에 대해 다음 우선순위 구분자("\n" → " " → "")로 재귀적으로 재분할한다.
    3. 이 과정을 통해 모든 조각(chunk)이 chunk_size를 초과하지 않도록 만든다.
  • 주요 파라미터

    • chunk_size: 각 조각의 최대 길이를 지정.

    • chunk_overlap: 연속된 청크들 간의 겹치는 문자 수를 설정. 새로운 청크 생성 시 이전 청크의 마지막 부분에서 지정된 수만큼의 문자를 가져와서 새 청크의 앞부분에 포함시켜, 청크 경계에서 문맥의 연속성을 유지한다. 예) 분할을 시/도한다. 이렇게 나뉘어질 수도 있음

      • 구분자에 의해 청크가 나눠지면 정상적인 분리이므로 overlap이 적용되지 않는다.
      • 청크를 합치는 경우 기준이 된다. 예를 들어 chunk_size가 1000인데 200, 300 이런 식으로 쪼개져서 둘이 합쳐도 1000이 안 넘을 때 합친다.
      • 정상적 구분자로 나눌 수 없어 chunk_size에 맞춰 잘라진 경우 문맥의 연결성을 위해 overlap을 적용한다.
    • separators(list): 구분자를 지정한다. 지정하면 기본 구분자가 지정한 것으로 변경된다.


13. Langchain 08-01: RAG Embedding Vector DB

Embedding

  • 분할된 텍스트를 벡터 표현(임베딩 벡터)으로 변환한다.
  • 메서드
    • embed_documents: 여러 문서
    • embed_query: 하나의 문서

Vector DB

  • Embedding 된 문서Vector DB에 저장한다.
  • 이후 질문(query)과 관련된 내용유사도를 이용해 검색질문과 함께 프롬프트로 만든다.

Vector DB란?

  • 벡터 임베딩을 저장하고 관리하는 DB를 의미.
  • 임베딩해서 데이터를 벡터화 한 뒤 DB에 저장하면, 임베딩 벡터 간의 거리 계산을 통해 데이터간 유사도를 검색할 수 있다.
  • DB는 이러한 벡터 간 거리 계산에 특화된 DB이다.
  • 주요 기능: 저장, 검색, 결과 반환

Langchain - Vector Store 연동

  • Langchain은 다양한 벡터 DB와 연동할 수 있다.
  • 벡터 DB마다 API가 다르기 때문에, Langchain을 사용하면 동일한 인터페이스로 사용할 수 있다.

Vector Store

  • Langchain이 지원하는 모든 벡터 DB는 VectorStore 인터페이스를 구현한다. ➡️ Langchain에서는 Vector DB를 Vector Store라고 한다!

0개의 댓글