RAG는 대규모 언어 모델의 한계를 보완하기 위해 등장한 기술입니다. 기존 LLM은 학습 데이터에만 의존하여 답변을 생성하기 때문에, 최신 정보 부족, 도메인 특화 지식 부족, 환각(hallucination) 문제 등이 발생합니다. RAG는 이를 해결하기 위해 외부 지식 베이스에서 관련 정보를 검색하여 모델에 제공하는 방식입니다.
RAG 시스템은 크게 두 단계로 구성됩니다:
청킹은 대용량 문서를 작은 단위로 분할하는 과정입니다. 이는 벡터 데이터베이스에서 효율적인 검색과 처리를 위해 필수적입니다.
고정 크기 청킹: 글자 수나 토큰 수를 기준으로 균등하게 분할합니다. 구현이 간단하지만 문맥이 끊어질 수 있습니다.
의미적 청킹: 문단, 문장, 섹션 등 의미적 경계를 기준으로 분할합니다. 문맥 보존에 유리하지만 청크 크기가 불균등할 수 있습니다.
겹치는 청킹: 인접한 청크들 사이에 일정 부분을 중복시켜 문맥 연속성을 보장합니다.
계층적 청킹: 문서 구조(제목, 소제목, 문단)를 반영하여 계층적으로 분할합니다.
벡터화는 텍스트를 고차원 벡터 공간의 수치형 표현으로 변환하는 과정입니다. 이를 통해 컴퓨터가 텍스트의 의미를 수학적으로 처리할 수 있습니다.
임베딩 모델은 텍스트의 의미적 정보를 고차원 벡터로 인코딩합니다. 유사한 의미의 텍스트는 벡터 공간에서 가까운 위치에, 다른 의미의 텍스트는 먼 위치에 배치됩니다. 이는 분산 표현(distributed representation) 원리에 기반합니다.
문장 수준 임베딩: Sentence-BERT, Universal Sentence Encoder 등은 문장 전체의 의미를 하나의 벡터로 표현합니다.
문서 수준 임베딩: Doc2Vec, BERT 기반 모델들은 긴 문서의 의미를 포착할 수 있습니다.
다국어 임베딩: Multilingual BERT, XLM-R 등은 여러 언어를 동일한 벡터 공간에 매핑합니다.
도메인 특화 임베딩: 의료, 법률, 과학 등 특정 도메인에 특화된 모델들입니다.
유사도 검색은 쿼리 벡터와 가장 유사한 벡터들을 데이터베이스에서 찾는 과정입니다. 이는 RAG 시스템의 핵심 기능입니다.
코사인 유사도: 두 벡터 사이의 각도를 측정합니다. 벡터의 크기에 무관하게 방향성만 고려하므로 텍스트 유사도 측정에 가장 많이 사용됩니다.
유클리드 거리: 두 점 사이의 직선 거리를 측정합니다. 벡터의 크기와 방향을 모두 고려합니다.
내적(Dot Product): 벡터의 크기와 방향을 모두 반영하며, 정규화된 벡터에서는 코사인 유사도와 동일합니다.
맨하탄 거리: L1 거리라고도 하며, 각 차원의 절댓값 차이의 합을 계산합니다.
정확한 검색: 모든 벡터와의 유사도를 계산하여 가장 유사한 k개를 반환합니다. 정확하지만 데이터가 많을 때 느립니다.
근사 최근접 이웃 검색 (ANN): 정확도를 약간 희생하여 검색 속도를 크게 향상시킵니다. HNSW, IVF, LSH 등의 알고리즘이 있습니다.
인덱싱: 벡터들을 특정 구조로 조직화하여 검색 속도를 높입니다. 트리 구조, 그래프 구조, 해시 기반 구조 등이 있습니다.
필터링: 메타데이터 기반으로 후보를 사전 필터링하여 검색 범위를 좁힙니다.
재순위 매기기: 초기 검색 결과를 더 정교한 모델로 재평가하여 정확도를 높입니다.
벡터 데이터베이스는 고차원 벡터를 효율적으로 저장하고 검색할 수 있도록 설계된 특수한 데이터베이스입니다.
고차원 벡터 최적화: 수백에서 수천 차원의 벡터를 효율적으로 처리할 수 있습니다.
확장성: 수백만에서 수십억 개의 벡터를 처리할 수 있는 확장성을 제공합니다.
실시간 업데이트: 새로운 벡터의 추가, 삭제, 수정을 실시간으로 지원합니다.
메타데이터 지원: 벡터와 함께 텍스트, 날짜, 카테고리 등의 메타데이터를 저장하고 필터링할 수 있습니다.
전용 벡터 DB: Pinecone, Weaviate, Qdrant 등은 벡터 검색에 특화되어 설계되었습니다.
확장 가능한 관계형 DB: PostgreSQL의 pgvector, MySQL의 벡터 확장 등은 기존 DB에 벡터 기능을 추가했습니다.
검색 엔진 기반: Elasticsearch, OpenSearch 등은 기존 검색 기능에 벡터 검색을 추가했습니다.
메모리 관리: 벡터는 메모리를 많이 사용하므로 효율적인 메모리 관리가 중요합니다.
디스크 I/O: 큰 벡터 데이터베이스는 디스크 기반 저장과 캐싱 전략이 필요합니다.
병렬 처리: 다중 쿼리를 동시에 처리할 수 있는 병렬 처리 능력이 중요합니다.
문서 로딩: 다양한 형식(PDF, HTML, JSON 등)의 문서를 읽어들입니다.
전처리: 불필요한 내용 제거, 텍스트 정규화, 언어별 처리를 수행합니다.
청킹: 앞서 설명한 전략에 따라 문서를 적절한 크기로 분할합니다.
벡터화: 청크들을 임베딩 모델을 통해 벡터로 변환합니다.
저장: 벡터와 메타데이터를 벡터 데이터베이스에 저장합니다.
쿼리 처리: 사용자 질문을 분석하고 전처리합니다.
쿼리 벡터화: 질문을 동일한 임베딩 모델로 벡터화합니다.
유사도 검색: 벡터 데이터베이스에서 가장 관련성 높은 청크들을 검색합니다.
후처리: 검색 결과를 필터링, 재순위, 중복 제거합니다.
컨텍스트 구성: 검색된 청크들을 LLM이 이해할 수 있는 형태로 구성합니다.
프롬프트 엔지니어링: 검색된 컨텍스트와 사용자 질문을 효과적으로 결합합니다.
LLM 호출: 구성된 프롬프트를 LLM에 전달하여 답변을 생성합니다.
후처리: 생성된 답변을 검증하고 형식을 맞춥니다.
응답 제공: 최종 답변을 사용자에게 제공합니다.
하이브리드 검색: 벡터 검색과 키워드 검색을 결합하여 검색 정확도를 높입니다.
쿼리 확장: 사용자 질문을 유사한 표현들로 확장하여 검색 범위를 넓힙니다.
다단계 검색: 초기 검색 후 결과를 바탕으로 추가 검색을 수행합니다.
컨텍스트 순위 매기기: 검색된 청크들의 관련성을 재평가하여 순서를 조정합니다.
답변 검증: 생성된 답변이 제공된 컨텍스트와 일치하는지 확인합니다.
인용 추가: 답변의 근거가 되는 문서나 청크를 명시합니다.
캐싱: 자주 검색되는 쿼리나 결과를 캐시하여 응답 속도를 높입니다.
배치 처리: 여러 쿼리를 배치로 처리하여 처리량을 향상시킵니다.
모니터링: 시스템 성능과 품질 지표를 지속적으로 모니터링합니다.
검색 정확도: 관련성 있는 문서가 상위에 검색되는지 측정합니다.
답변 품질: 생성된 답변의 정확성, 완전성, 유용성을 평가합니다.
시스템 성능: 응답 시간, 처리량, 자원 사용량을 측정합니다.
피드백 수집: 사용자 피드백을 수집하여 시스템을 개선합니다.
A/B 테스트: 다른 설정이나 모델을 비교 테스트합니다.
모델 업데이트: 새로운 임베딩 모델이나 LLM으로 업그레이드합니다.
벡터 DB RAG 시스템은 이러한 다양한 구성 요소들이 유기적으로 결합되어 작동하는 복합 시스템입니다. 각 단계의 최적화가 전체 시스템의 성능에 중요한 영향을 미치므로, 전체적인 관점에서 균형잡힌 접근이 필요합니다.