RAG는 모델이 학습하지 않은 정보를 외부 저장소에서 검색한 뒤, 그 결과를 context로 프롬프트에 추가해 LLM이 답변을 생성하도록 하는 기술
학습되지 않은 정보를 모르거나 hallucination(거짓 답변)을 일으키는 LLM의 한계를 해결하기 위해 등장했다
상황
문제
RAG 해결
사내 문서 질의
LLM이 모름
DB에서 검색해서 참고
최신 정보
학습 cutoff 이후 데이터 모름
외부 저장소에서 가져옴
재학습 비용
Fine-tuning은 비싸고 느림
DB만 업데이트하면 즉시 반영
2) 구성 요소
구성 요소
역할
Document
검색 대상이 되는 원본 텍스트. 메타데이터와 함께 Vector DB에 저장됨
Retriever
사용자 질문을 벡터로 변환 후 Vector DB에서 유사한 Document를 찾아오는 검색기
Query Engine
검색된 Document를 context로 삽입해 LLM에 전달하고 최종 답변을 생성하는 엔진
2. 동작 흐름
1) 사전 준비 - 문서 저장
문서 텍스트
→ 임베딩 모델(text-embedding-3-small)
→ 1536차원 벡터
→ Vector DB에 저장
2) 질문 시 RAG 흐름
1. 사용자 질문 → 임베딩 모델 → 벡터 변환
↓
2. Vector DB에서 코사인 유사도로 유사한 문서 탐색
↓
3. 임계치(threshold) 이상 문서만 선별
↓
4. 선별된 문서를 프롬프트 context로 삽입
┌────────────────────┐
│ [CONTEXT] │
│ 검색된 관련 문서 내용 │
│ │
│ [USER QUESTION] │
│ 사용자 질문 │
└────────────────────┘
↓
5. LLM이 context를 참고해서 답변 생성
AI가 문서를 재학습하는 게 아니라 매 요청마다 관련 문서를 프롬프트에 동적으로 삽입하는 방식이기 때문에 DB 내용이 바뀌어도 재학습 없이 즉시 반영된다
단, 검색된 문서가 프롬프트에 포함되기 때문에 문서 길이만큼 토큰이 추가로 소비된다. OpenAI 같은 서드파티 API 사용 시 context가 길어질수록 비용이 증가하므로 문서 크기와 개수(topK) 설정에 주의해야 한다
DB 내용이 바뀌어도 재학습 없이 즉시 반영된다
3. Fine-tuning vs RAG
구분
Fine-tuning
RAG
방식
모델 자체를 추가 학습
외부 문서를 프롬프트에 삽입
비용
높음
낮음
최신 정보 반영
재학습 필요
DB 업데이트만으로 즉시 반영
적합한 상황
특정 도메인 말투/형식 학습
최신 정보, 사내 문서 질의
4. 주의사항
1) 검색 품질이 답변 품질을 결정한다
RAG는 검색된 문서를 그대로 context로 넘기기 때문에 검색 결과가 부정확하면 답변도 틀린다
임계치(threshold) 설정이 중요하다. 너무 낮으면 관련 없는 문서가 포함되고, 너무 높으면 아무 문서도 검색되지 않는다
2) Prompt Caching과 궁합이 안 맞는다
OpenAI Prompt Caching은 프롬프트 앞부분이 완전히 동일할 때 캐싱된다
RAG는 질문마다 다른 문서가 context에 삽입되어 프롬프트가 매번 달라지기 때문에 캐싱 효과가 거의 없다
Caching은 고정된 긴 system prompt에 적용할 때 효과적이다
3) 문서 분할(Chunking)이 중요하다
문서가 너무 길면 임베딩 품질이 떨어지고 context가 길어져 LLM 처리 비용이 증가한다