RAG 시스템에서 벡터 검색 정확도 개선기

문제 상황

사내 문서 검색을 위한 RAG 시스템을 구축했는데, 사용자들로부터 관련 없는 문서가 자주 나온다는 피드백을 받았다. OpenAI의 text-embedding-3-small 모델을 사용하고 있었고, 문서를 512 토큰 단위로 청킹하고 있었다.

원인 분석

로그를 분석해보니 두 가지 문제가 있었다:

  1. 청크가 너무 작아서 맥락이 손실되는 경우
  2. 의미적으로는 유사하지만 실제로는 다른 내용이 검색되는 경우

특히 기술 문서의 경우 코드 스니펫과 설명이 분리되면서 정확도가 떨어졌다.

해결 과정

1. 청크 크기 조정

청크 크기를 512에서 1024 토큰으로 늘리고, 128 토큰 오버랩을 추가했다.

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1024,
    chunk_overlap=128,
    separators=["\n\n", "\n", ".", " ", ""]
)

2. 하이브리드 검색 도입

벡터 검색만으로는 한계가 있어서 BM25 키워드 검색을 함께 사용했다. Pinecone의 sparse-dense 인덱스를 활용했다.

const results = await index.query({
  vector: embedding,
  sparseVector: bm25Encoding,
  topK: 10,
  alpha: 0.7 // 벡터 검색 가중치
});

3. 메타데이터 필터링

문서 타입, 작성일, 부서 등의 메타데이터를 추가해 필터링 옵션을 제공했다.

const results = await index.query({
  vector: embedding,
  filter: {
    docType: { $eq: 'technical' },
    createdAt: { $gte: '2024-01-01' }
  },
  topK: 5
});

결과

테스트 쿼리 100개 기준으로 정확도가 63%에서 82%로 개선됐다. 사용자 피드백도 긍정적으로 바뀌었다.

하이브리드 검색의 alpha 값은 문서 특성에 따라 조정이 필요했다. 기술 문서는 0.7, 일반 문서는 0.5가 적당했다.

남은 과제

청크 경계에서 여전히 문맥이 끊기는 경우가 있다. 시맨틱 청킹을 고려 중이다.

RAG 시스템에서 벡터 검색 정확도 개선기