macOS에서 Ollama+SQLite 기반 로컬 RAG 구축 방법

오늘날 챗봇과 AI 도구에서 정보를 정확하고 신뢰성 있게 얻는 방법으로 RAG 구축을 통해 하기도 하는데요. 검색 확장 생성(Retrieval-Augmented Generation, RAG)는 대형 언어 모델(LLM)이 기존 훈련 데이터에 없는 최신 정보나 도메인 지식을 참조하도록 도와 답변의 정확도와 신뢰성을 높여줍니다.
특히, 로컬 환경에서 RAG를 구축하면 프라이버시 보호와 오프라인 활용이 가능해져, AI 도구 개발자들에게 큰 관심을 받고 있습니다. 이 글에서는 macOS 기반에서 SQLite(FTS5/BM25)와 Ollama를 사용해 로컬 RAG를 단계별로 구현하는 실용적인 방법을 다룹니다.
RAG란 무엇인가, 로컬 RAG의 특징
RAG는 사용자의 질의에 대해 LLM이 답을 생성하기 전에 관련 문서나 자료를 검색해 참고 자료로 활용하는 기법입니다. 예를 들어 법정 판사가 사건 판결에 앞서 관련 판례를 찾아보듯, LLM에게 필요한 최신 정보나 전문 자료를 제공하는 역할을 합니다.
NVIDIA 블로그에 따르면, RAG는 “특정하고 관련성 높은 데이터 소스에서 정보를 가져와 생성 AI 모델의 정확도와 신뢰성을 향상”시키는 기법입니다. RAG은 모델이 인수로 학습된 일반적인 언어 패턴 외에 최신 정보나 도메인별 지식을 반영할 수 있어, 잘못된 답변(환각)을 줄이고 사용자의 신뢰를 높이는 장점이 있습니다.
로컬 RAG는 이 과정을 클라우드 서비스 대신 로컬 환경에서 수행한다는 점이 특징입니다. 즉, 온라인 API(예: OpenAI, Azure)를 사용하지 않고도 맥북 등 개인 기기에서 모든 데이터를 처리합니다. 장점은 데이터 유출 위험 감소와 API 사용 비용 절감, 인터넷 연결 불필요 등입니다. 반면 단점으로는 모델 성능(예: GPT-4보다 상대적으로 낮은 품질)이나 컴퓨팅 자원(CPU/GPU 요구량)이 있습니다.
또한, Hosted LLM은 무제한 확장성과 강력한 성능을 제공하는 반면 API 비용과 네트워크 레이턴시, 개인정보 이슈가 발생할 수 있습니다. 반면 로컬 LLM은 데이터 관리 통제와 낮은 레이턴시 장점이 있지만, 규모 확장과 리소스 제약이 있습니다. 사용자 환경이나 필요에 따라 양자의 선택과 절충이 필요합니다.
로컬 RAG의 간단한 작동 모델

로컬 RAG의 기본 아이디어는 간단합니다.
(1) 먼저 문서들을 로컬 저장소(예: 마크다운 파일, PDF 등)로 준비한 뒤,
(2) SQLite FTS5(전문 검색) 테이블을 만들어 문서 텍스트를 색인합니다.
(3) 사용자가 질문을 입력하면, 이 질문을 키워드로 SQLite FTS5에서 관련 구문(단락)을 BM25 알고리즘으로 랭킹하여 검색합니다.
(4) 검색된 상위 구문들을 모아서 원문의 프롬프트 앞이나 뒤에 추가하고, 이 확장된 프롬프트를 Ollama의 로컬 LLM에 전달해 답변을 생성합니다.
예를 들어 “가장 최근에 나온 인디아나 존스 영화는?”이라는 질문을 받으면, 로컬 지식 베이스에서 “Dial of Destiny (2023)”가 포함된 문단을 찾아내어 프롬프트에 삽입합니다. 그런 다음 LLM이 이 문단을 참고하도록 하여 “2023년에 인디아나 존스와 운명의 다이얼이 개봉했다”는 정확한 답변을 얻을 수 있습니다.
이처럼 RAG는 검색(R)과 생성(G) 두 단계로 나뉘어 작동합니다. 먼저 사용자 질의를 바탕으로 관련 정보를 검색(retrieval)하고, 이어서 LLM에게 검색 결과를 포함한 프롬프트를 제시해 답변을 생성합니다.
SQLite FTS5는 키워드와 구문 기반의 검색을 빠르게 수행하도록 설계된 모듈입니다. 전통적인 벡터 검색에 비해 정확도와 도메인 특수어 보존에서 강점이 있습니다. FTS5는 특정 용어나 숫자 정보를 온전히 유지해 검색할 수 있으며, 복잡한 문서에서도 정밀한 검색 결과를 제공합니다.
실제로 FTS는 금융 보고서나 법률 문서처럼 전문 용어와 숫자가 중요한 문서에 유리하고, 일반 벡터 검색보다 높은 정밀도를 보여줍니다. SQLite3는 기본적으로 FTS5 모듈을 지원하므로, 별도 설치 없이 간단한 SQL 명령으로 가상 테이블을 생성하여 사용할 수 있습니다. 예를 들어, Python에서 SQLite3를 사용하면 아래처럼 FTS5 가상 테이블을 생성할 수 있습니다.
import sqlite3
conn = sqlite3.connect('docs.db')
conn.execute("CREATE VIRTUAL TABLE IF NOT EXISTS docs USING fts5(content)")이렇게 생성된 docs 테이블에 문서 텍스트를 삽입하면, docs MATCH ? 질의로 BM25 순위에 따른 검색이 가능합니다.
개발 환경 설정: Ollama, SQLite, Python
macOS에서 로컬 RAG를 구축하려면 몇 가지 필수 도구를 설치해야 합니다. Ollama는 맥, 윈도우, 리눅스에서 로컬 LLM을 실행할 수 있도록 해주는 오픈소스 도구입니다. Ollama를 설치하려면 Homebrew를 이용하는 것이 편리합니다. 터미널에서 다음 명령을 실행합니다.
brew install ollama
brew services start ollama이렇게 하면 Ollama가 설치되고 백그라운드 서비스로 실행됩니다. 실행 후 웹 브라우저로 http://localhost:11434에 접속하면 “Ollama is running” 페이지가 표시됩니다. 원하는 LLM을 다운받아 사용할 수 있는데, 예를 들어 LLaMA나 Mistral 등의 모델을 Ollama 마켓에서 내려받을 수 있습니다. (예: ollama pull llama2:13b-chat와 같이 모델 이름을 지정)
SQLite는 macOS에 기본 내장되어 있지만, 최신 버전으로 업데이트하거나 FTS5가 활성화된 버전을 쓰려면 Brew로 다시 설치해도 됩니다. 일반적으로 brew install sqlite 명령만으로도 FTS5가 활성화된 SQLite를 사용할 수 있습니다. Python 환경에서는 내장 sqlite3 모듈을 이용하거나, 필요시 pip install sqlite3(별도 패키는 필요 없음)로 사용할 수 있습니다.

Python 도구는 데이터 전처리와 데이터베이스 조작, API 호출 등을 위해 필요합니다. 예를 들어, PDF를 텍스트로 변환하려면 pip install pypdf (또는 PyMuPDF, pdfplumber 등)로 라이브러리를 설치하고, Ollama의 HTTP API를 사용하려면 pip install requests 또는 pip install ollama(공식 Python 라이브러리)도 설치할 수 있습니다. 터미널에서 Python 가상환경(venv)을 만들어 두고 필요한 패키지를 설치해두면 관리가 편리합니다.
단계별 RAG 구현 가이드

로컬 RAG 시스템을 실제로 구현하는 단계는 다음과 같습니다.
- 데이터 준비 – 마크다운이나 텍스트 파일, PDF 등 필요한 문서를 수집합니다. 마크다운은 그대로 텍스트로 사용할 수 있고, PDF는 텍스트 추출을 해야 합니다. 예를 들어
pypdf라이브러리를 사용하면 아래와 같이 PDF 페이지별로 텍스트를 추출할 수 있습니다:from pypdf import PdfReaderreader = PdfReader("document.pdf")text = "" for page in reader.pages: text += page.extract_text() + "\n"
추출한 텍스트를 문단별로 나누거나 적절한 크기로 청크(chunk)로 분할해 두면 추후 검색 품질을 높이는 데 도움이 됩니다. - FTS5 인덱싱 – SQLite 데이터베이스에 FTS5 가상 테이블을 만들어 텍스트를 저장합니다. 예를 들어
docs라는 테이블을 만들었다면, 추출한 텍스트(또는 문단 청크)를 아래와 같이 삽입합니다.conn = sqlite3.connect('rag.db')conn.execute("CREATE VIRTUAL TABLE IF NOT EXISTS docs USING fts5(content)")for paragraph in paragraphs:
conn.execute("INSERT INTO docs (content) VALUES (?)", (paragraph,))conn.commit()
이렇게 하면docs테이블이 완성되고, 각 행(row)마다content칼럼에 문서 내용이 들어갑니다. SQLite FTS5는 기본적으로 BM25 알고리즘으로 결과를 점수화하므로, 검색 시 BM25 순으로 랭킹됩니다. - Ollama 실행 – Ollama를 설치한 후 원하는 LLM 모델을 로컬에 내려받습니다. 예를 들어 LLaMA 2 13B 채팅 모델을 사용할 경우,
ollama pull llama2:13b-chatollama run llama2:13b-chat
이렇게 하면 Ollama 데몬이 해당 모델을 로드하고 로컬에서 사용할 준비가 됩니다. Python 코드를 통해 사용하려면 Ollama의 OpenAI 호환 API를 이용할 수 있습니다. 예를 들어 다음처럼openai클라이언트를 사용하면 다음과 같이 채팅 요청을 보낼 수 있습니다.from openai import OpenAIclient = OpenAI(base_url='http://localhost:11434/v1/', api_key='ollama')response = client.chat.completions.create( model='llama2:13b-chat', messages=[{'role': 'user', 'content': '안녕하세요?'}] )print(response.choices[0].message.content)
또는requests라이브러리로 HTTP POST를 직접 호출해도 됩니다. - 검색 및 프롬프트 구성 – 사용자의 질문이 들어오면 SQLite에 질의어를 전달해 상위 N개의 관련 문단을 가져옵니다.
예를 들어query = "인디아나 존스 최신 영화"cursor = conn.execute( "SELECT content FROM docs WHERE docs MATCH ? ORDER BY bm25(docs) LIMIT 3", (query,) )results = [row[0] forrow in cursor.fetchall()]
이렇게 하면 BM25 점수가 높은 상위 3개 문단이results에 리스트로 저장됩니다. 그다음 이 결과를 원래 질문과 함께 LLM의 입력 프롬프트로 조합합니다.
예를 들어문서 참고 자료: [결과1 텍스트] [결과2 텍스트] [결과3 텍스트]질문: 인디아나 존스 최신 영화는 무엇인가요?
이런 식으로 컨텍스트를 덧붙여chat.completions.create에 전달하면, 모델이 해당 정보를 참고하여 응답을 생성합니다. - LLM으로 답변 생성 – 완성된 프롬프트를 Ollama LLM에 보내면 최종 답변이 나옵니다. 예시 코드는 다음과 같습니다.
prompt = "다음 내용을 참고하여 질문에 답해주세요:\n" + "\n".join(results) + f"\n\n질문: {query}"payload = { "model": "llama2:13b-chat", "messages": [{"role": "user", "content": prompt}] }res = requests.post("http://localhost:11434/v1/chat/completions", json=payload)answer = res.json()['choices'][0]['message']['content']print(answer)
여기서v1/chat/completions엔드포인트는 Ollama가 OpenAI API 호환 모드를 지원하며, 응답 JSON에서 실제 답변 텍스트를 얻을 수 있습니다.

실용적인 팁
텍스트 청크 전략
문서를 너무 짧게 자르면 의미 단위가 분리될 수 있고, 너무 길면 검색에서 노이즈가 생기기 쉽습니다. 적절히 문단이나 500–1000 토큰 내외로 청크를 나누고, 헤더를 제거하는 등의 전처리로 검색 품질을 높여보세요.
메모리 사용 관리
SQLite FTS5 테이블은 기본적으로 메모리 맵형태로 동작합니다. 문서 수가 많으면 메모리 사용량이 커질 수 있으므로, 필요에 따라 PRAGMA cache_size 조정이나 디스크 기반 DB 사용(파일 경로 지정) 방법을 고려하세요. 또한, Ollama에서 대형 모델(7B 이상)을 실행할 때는 CPU 대신 Apple Silicon M1/M2 등의 GPU/Neural 엔진 활용이나 4/8비트 퀀타이제이션을 이용해 메모리 부담을 줄일 수 있습니다.
키워드 선택과 쿼리
SQLite FTS5는 특수 기호나 구문 검색 기능이 제한적일 수 있습니다. 여러 키워드가 있을 때는 OR/NEAR 구문(예: docs MATCH '키워드1 OR 키워드2')을 활용하거나, 중요 단어를 그대로 매칭시켜 보세요. 필요하다면 OpenAI나 다른 LLM에 입력어를 확장(paraphrase)시켜 키워드 추출 후 사용해도 좋습니다.
리랭킹 사용 고려
단순 BM25 검색 외에, 벡터 임베딩을 이용한 재정렬(re-ranking)을 추가하면 정확도를 높일 수 있습니다. 예를 들어, sqlite-vec 확장으로 상위 결과를 임베딩 유사도로 필터링하거나, 랭크 점수를 가중치 합으로 결합하면 더 정밀한 결과를 얻을 수 있습니다. 기본적인 구축 단계에서는 필수는 아니지만, 더 높은 정확도를 원할 땐 단계적으로 도입해보세요.
Ollama 활용법
Ollama는 LLM 실행 외에도 임베딩 생성 기능을 제공합니다. ollama run embeddinggemma "문장" 명령어로 간단히 문장 임베딩을 얻거나, Python ollama.embed() 함수를 사용할 수 있습니다. 이렇게 추출한 임베딩은 벡터 검색이나 유사도 기반 정렬에도 활용할 수 있습니다.
RAG 파인튜닝 차이
RAG와 파인튜닝은 LLM을 특정 작업에 최적화하는 대표적인 두 접근법으로, 근본적인 작동 방식에서 차이가 큽니다. RAG는 모델 자체를 건드리지 않고 외부 데이터베이스(예: SQLite FTS5나 벡터 DB)에서 질의와 관련된 문서를 실시간 검색해 프롬프트에 컨텍스트로 추가하는 방식입니다. 따라서 최신 정보나 자주 업데이트되는 도메인 데이터에 강하며, 구현 비용이 낮고 검색 품질에 따라 정확도가 결정되지만 환각(hallucination)을 줄이는 데 효과적입니다. 반면 파인튜닝은 기존 LLM의 가중치를 추가 학습 데이터로 재조정해 새로운 지식이나 특정 스타일·톤을 모델 내부로 내재화시키는 과정으로, 고비용·고자원 소모적입니다.
파인튜닝은 전문 도메인(예: 의료·법률)에서 일관된 응답 스타일이나 복잡한 추론 패턴을 요구할 때 적합하며, 한 번 학습 후 빠른 추론 속도를 제공하지만 데이터 업데이트 시 재학습이 필요합니다. RAG는 로컬 RAG처럼 SQLite BM25 검색으로 간단히 구현 가능하며 유지보수가 쉬워 개인 프로젝트나 프로토타입에 이상적입니다. 최적의 결과는 하이브리드 접근으로, 파인튜닝으로 기본 성능을 강화한 뒤 RAG로 실시간 정보를 보완하는 방식입니다.
커뮤니티 반응 요약
일반적인 사용자 의견을 살펴보면, 로컬 RAG에 대한 반응은 다음과 같습니다.
- 장점: 많은 개발자들이 프라이버시와 오프라인 동작을 큰 강점으로 꼽습니다. 민감한 문서나 자체 자료를 클라우드에 보내지 않고 자유롭게 검색할 수 있다는 점에서 호응이 높습니다. 또한 비용 부담 없이 로컬에서 자유롭게 튜닝하며 실험할 수 있어, 빠른 프로토타입 제작에 유리하다고 평가합니다.
- 단점: 반면, 현 시점에서 로컬 LLM은 클라우드 GPT 모델에 비해 언어 이해력이나 답변 품질이 낮은 편입니다. 따라서 결과의 정확도에 있어 검증과 사용자 개입이 필요할 수 있습니다. 또, 특히 큰 모델(10B 이상)을 돌리려면 충분한 연산 자원(GPU/메모리)이 필요하며, 초기 설정과 디버깅에 많은 시간이 소요된다는 의견도 많습니다.
- SQLite FTS에 대한 평: 간단한 구축과 빠른 텍스트 검색에 대해 긍정적으로 평가합니다. 복잡한 도큐먼트 검색에는 충분하지만, 매우 큰 데이터셋이나 의미 기반 검색에는 한계가 있다는 점은 감안해야 합니다.
- Ollama 활용: 설치와 실행이 비교적 간단하다는 점이 장점으로 꼽힙니다. 커뮤니티에서는 Ollama가 아직 개발 중이므로 지속적으로 업데이트를 확인해야 한다는 조언과, 적절한 모델 선택(파라미터 크기 등)이 중요하다는 의견이 많습니다.
위와 같은 커뮤니티 전반의 의견을 참고하여, 로컬 RAG를 도입할 때는 성능과 편의성, 리소스 제약 사이의 균형을 잘 맞추는 것이 중요합니다.
주의사항 및 위험 요소
로컬 RAG 시스템을 구축할 때는 다음과 같은 리스크와 주의사항을 고려해야 합니다:
- 모델 크기와 전력 소모: LLM은 크기에 비례해 연산량과 전력 소모가 큽니다. 예를 들어 LLaMA 13B를 CPU에서 실행하면 응답 속도가 느릴 수 있으며, 70B 모델은 GPU나 매치된 하드웨어 없이 사실상 구동이 어렵습니다. 필요 시 모델 퀀타이즈(4/8bit)나 Distil 모델을 고려하세요.
- 파일 권한 및 접근: SQLite 데이터베이스 파일의 위치와 권한 설정을 주의해야 합니다. 잘못된 디렉토리 권한 설정은 보안 이슈를 일으킬 수 있습니다. 또한, PDF나 마크다운 원본 파일의 저작권이나 개인정보를 다룰 땐 해당 내용을 주의 깊게 처리해야 합니다.
- 정확도 트레이드오프: 로컬 LLM은 GPT-4 등 상용 모델보다 학습 데이터가 적거나 알파벳 특화일 수 있습니다. 따라서 생성된 답변이 꼭 정확하지 않을 수 있습니다. RAG로도 모델 자체의 한계는 극복하기 어려우므로, 항상 출력 결과를 검증하고 신뢰성을 높이는 노력이 필요합니다.
- 토큰/토크나이저 불일치: 텍스트를 일정 길이로 나눌 때, 모델의 토크나이저(tokenizer) 특성을 고려해야 합니다. 예를 들어, 한글이나 특정 기호가 분절될 때 개수 제한에 걸릴 수 있습니다. 자르는 위치가 문장 중간이 되지 않도록 조심하고,
MAX_TOKENS제한에 유의해 프롬프트를 구성하세요. - PDF 변환/임베딩 오류: PDF 파일에서 텍스트를 추출할 때 글꼴 임베딩 오류나 OCR 문제로 내용 일부가 누락될 수 있습니다. 특히 이미지로 스캔된 PDF는 Tesseract OCR 같은 추가 도구가 필요할 수 있습니다. 텍스트 변환 결과를 사람이 검토하여 누락이나 깨진 부분이 없는지 확인하세요.
- 출력 검증: LLM이 생성한 답변은 그 자체로 완전한 사실이 아닐 수 있으므로, 반드시 제공한 문서나 근거와 일치하는지 검토해야 합니다. RAG는 모델이 참고할 자료를 제공하므로 답변 출처 검증이 상대적으로 용이하지만, 최종 판단과 검증은 사람이 수행해야 합니다.
위 위험 요소를 미리 고려하고 조심하여 로컬 RAG를 안전하게 활용하세요. 예를 들어 “모델이 허위 정보를 제시할 경우 그 원천을 찾아보고, 중요한 결정에는 자체 검증을 거친다”는 식의 운영 방침을 마련하는 것이 좋습니다.
자주 묻는 질문
Q1: RAG 파인튜닝 차이점은 무엇인가요?
A: RAG는 외부 문서를 통해 실시간으로 정보를 검색해 모델에 제공하는 방식이고, 파인튜닝은 도메인 데이터를 이용해 모델의 가중치를 직접 재훈련하는 방식입니다. RAG는 새로운 자료를 반영하기 쉽고 인프라 비용이 적다는 장점이 있지만, 지식이 모델 내부에 영구적으로 내재되지 않습니다. 반면 파인튜닝은 모델 자체에 지식을 저장할 수 있지만 훈련 비용이 크고 업데이트 주기가 깁니다.
Q2: SQLite FTS5 기반 RAG와 벡터 데이터베이스를 쓰는 RAG의 차이는?
A: SQLite FTS5는 키워드 기반 검색에 특화된 반면, 벡터 DB(예: FAISS, Milvus)는 텍스트 임베딩 간의 의미적 유사도 검색에 강점이 있습니다. 일반적인 정보 검색이나 숫자/전문 용어 정확성이 중요하면 FTS5가 유리할 수 있고, 어휘가 유연하고 의미적으로 연관된 결과를 원하면 벡터 DB를 사용합니다. SQLite FTS5는 별도 서버 없이 간단히 구현할 수 있지만, 벡터 검색은 임베딩 생성과 계산 비용이 추가됩니다.
Q3: 리랭킹(Ranking Re-Ranker)은 꼭 필요한가요?
A: 필수는 아니지만, 정확도가 중요한 경우 사용을 고려할 만합니다. 기본적으로 SQLite FTS5에서 상위 결과를 뽑고, 이후에 추가 알고리즘(예: 벡터 임베딩 유사도, 역위치 순위 융합 등)으로 순위를 재조정하면 더 일관성 있는 답변을 얻을 수 있습니다. 특히 문서가 많거나 다의어가 많을 때 리랭킹을 통해 불필요한 답변을 걸러내는 데 도움이 됩니다.
Q4: RAG 시스템 구축에 추천하는 LLM과 임베딩 모델은?
A: Ollama에서는 LLaMA, Mistral, Qwen, Gemma 등 여러 오픈 모델을 지원합니다. 일반적으로 채팅과 텍스트 생성을 위해 LLaMA 2 7B/13B, Mistral 7B 등이 있고, 임베딩용으로는 gemma나 all-MiniLM 같은 경량 모델이 많이 사용됩니다. 모델 선택 시 파라미터 크기(예: 7B/13B)와 양자화 지원 여부를 고려하세요. 예를 들어 CPU만 사용한다면 7B 정도를, M1/M2를 활용하면 13B 이상도 가능할 수 있습니다.
Q5: SQLite 대신 Lucene이나 Elasticsearch 같은 검색엔진을 써도 되나요?
A: 가능합니다. Lucene/Solr, Elasticsearch 등은 더 복잡한 텍스트 분석과 분산 검색 기능을 제공하지만, 구축 난이도와 환경 구성이 추가됩니다. 단일 머신에서 가볍게 시작하고 싶다면 SQLite FTS5가 편리하며, 큰 규모나 고급 검색 기능이 필요하다면 Lucene 계열 검색엔진을 고려할 수 있습니다.
Q6: 로컬 RAG 구축 예제로는 어떤 것이 있나요?
A: 예를 들어 논문 PDF를 로컬에 저장하고, 이들을 텍스트로 변환하여 SQLite에 색인한 뒤 질의할 수 있습니다. Turso 블로그나 개발자 커뮤니티에도 유사한 사례가 많이 공유되어 있습니다. 필요한 예제에 맞춰 파이썬 스크립트를 작성하고, Ollama로 모델을 연결하면 됩니다.
정리하기
이 글에서는 macOS 환경에서 Ollama와 SQLite FTS5를 활용해 로컬 RAG 시스템을 구축하는 방법을 살펴보았습니다. 먼저 RAG의 개념과 로컬 RAG의 장단점을 설명했고, 마크다운/PDF 텍스트 준비와 SQLite 인덱싱, Ollama 실행 방법을 단계별로 안내했습니다. 텍스트를 적절히 청크화하고 BM25 검색을 통해 상위 관련 문단을 뽑아 프롬프트에 주입하는 과정을 코딩 예시와 함께 설명했습니다. 또한 실용적인 팁과 커뮤니티 의견, 위험요소를 정리하여 실제 구축 시 도움이 되도록 했습니다.
다음 글에서는 BM25와 벡터 검색을 결합한 하이브리드 RAG나 결과 재순위화(re-ranking) 같은 고급 기술을 다룰 예정입니다. 예를 들어, SQLite FTS5와 함께 임베딩 벡터를 사용하여 검색 정확도를 높이는 방법 등을 실습할 것입니다. 여러분의 로컬 RAG 프로젝트에 도움이 되길 바랍니다!
RAG 학습에 대한 이슈를 이야기 하시는 분이 있어서 별도로 정리해 보았습니다.
RAG 자체는 전통적인 "학습(training)" 과정이 없습니다. 대신 검색(retrieval) 단계에서 BM25나 벡터 임베딩을 통해 관련 문서를 찾고, 이를 프롬프트 컨텍스트로 LLM에 전달하는 방식이기 때문입니다. 다만 검색 품질을 높이기 위해 "RAG 학습"이라 불리는 최적화 과정이 존재하는데, 이는 청크 분할 전략(chunking), 검색 임계값, 상위 K개 문서 수 등을 실험하고 튜닝하는 것을 의미합니다. 또한 벡터 RAG에서는 문서 임베딩 모델을 도메인 데이터로 파인튜닝하거나, 쿼리 확장(Query Expansion) 기법을 통해 더 정확한 검색어를 자동 생성하는 방법도 포함됩니다.
고급 RAG 학습으로는 검색 후 생성(Retrieval-Augmented Generation) 평가 지표를 활용한 반복 개선이 있습니다. 예를 들어 RAGAS나 DeepEval 같은 프레임워크로 검색된 컨텍스트의 관련성(Context Relevance), 답변의 사실성(Groundedness), 응답 완전성을 측정하고, 낮은 점수의 경우 청크 크기나 검색 알고리즘을 조정합니다. 이렇게 검색 품질을 체계적으로 최적화하면 LLM의 환각을 30-50% 줄이고, 답변 정확도를 크게 향상시킬 수 있습니다. 로컬 RAG에서는 SQLite FTS5의 `rank` 함수 파라미터나 토큰 오버랩 설정을 실험하는 것부터 시작하는 것이 효과적입니다.


