Ollama를 활용한 로컬 RAG: 프라이빗 AI 검색 시스템 구축 튜토리얼
요약
Ollama를 사용하여 데이터 유출 걱정 없는 로컬 RAG(검색 증강 생성) 시스템을 구축하는 방법을 안내합니다. 데이터 주권 확보, 비용 절감, 낮은 지연 시간을 목적으로 하며, 하드웨어 요구 사항부터 단계별 설치 명령어까지 상세히 다룹니다.
핵심 포인트
- 데이터 주권 및 보안을 위해 로컬 환경에서 RAG 구축 가능
- API 비용 없이 온디바이스 추론을 통한 비용 예측 가능성 확보
- Mistral-7B 모델과 Ollama를 활용한 실전 설치 가이드 제공
- 원활한 실행을 위한 최소 CPU, RAM, SSD 사양 가이드
에피소드 47 – Ollama를 활용한 로컬 RAG: 프라이빗 AI 검색 시스템 구축
안녕하세요, _Build Log_의 Nick입니다. 지난 에피소드의 마지막 15분 동안 저는 클라우드 키도, API 비용도, 데이터 유출도 전혀 없는, 노트북에서 완전히 실행되는 검색 증강 생성 (RAG, Retrieval-Augmented Generation) 파이프라인을 구축하는 방법을 안내해 드렸습니다. 아래는 모든 "빠른 팁"을 터미널에 바로 복사하여 붙여넣을 수 있는 완전하고 실행 가능한 가이드로 확장한 동반 블로그 포스트입니다.
왜 로컬인가? 현실적인 동기
- 데이터 주권 (Data sovereignty). 계약서, HIPAA, GDPR – "데이터가 절대 현장을 떠나지 않는다"라고 명시된 세부 조항들.
- 비용 예측 가능성. API 비용이 0달러라는 것은 하드웨어 예산을 한 번만 세우면 그 이후로는 신경 쓸 필요가 없음을 의미합니다.
- 지연 시간 (Latency). 온디바이스 추론 (On-device inference)은 평범한 MacBook Air에서도 1초 미만으로 수행되며, 이는 네트워크 왕복 호출보다 훨씬 뛰어납니다.
- 제어권. 어떤 모델 버전을 실행할지, 어떻게 양자화 (Quantized)할지, 그리고 이를 인터넷에 노출할지 여부를 직접 결정합니다.
이러한 이유들은 제가 쇼에서 설명했던 시나리오와 잘 맞아떨어집니다: 13개의 고객 사이트, 독점적인 PDF 파일들, 그리고 여전히 제트 엔진 같은 소리가 나는 팬을 가진 3년 된 노트북. 그곳에서 작동한다면, 당신에게도 작동할 것입니다.
하드웨어 현실 점검 – 실제로 필요한 것
"어떤 GPU든 상관없다"는 과장된 광고에 속지 마세요. 노트북에서 프로덕션급 RAG 스택을 구축하려면 다음이 필요합니다:
- CPU: 8GB 이상의 RAM, 최소 쿼드 코어 Intel i5 또는 Apple M1/M2. 제가 사용하는 모델 (Mistral-7B-instruct-v0.1)은 4비트로 양자화했을 때 6GB의 VRAM에 여유롭게 들어갑니다.
- 디스크: 모델 가중치 (Model weights)와 ollama 런타임을 위해 20GB의 여유 공간. SSD는 필수입니다; HDD는 임베딩 (Embedding) 단계를 고통스러울 정도로 느리게 만듭니다.
- OS: macOS 12 이상, Ubuntu 20.04 이상, 또는 Windows 10 (WSL2) – Docker 또는 네이티브 바이너리를 실행할 수 있는 환경이라면 무엇이든 가능합니다.
만약 이 사양을 충족하지 못하는 기기를 사용 중이라면, 저렴한 외장 GPU (예: eGPU 인클로저에 장착된 NVIDIA RTX 3060)나 무거운 작업을 위한 소규모 클라우드 버스트 VM (Cloud-burst VM)을 고려해 보세요.
단계별 가이드: 15분 완성 스택
다음은 제가 2020년형 MacBook Air (8GB RAM, Apple Silicon)에서 실행한 정확한 명령어 순서입니다. 경로는 필요에 따라 조정하세요.
1️⃣ Ollama 설치 (LLM을 로컬에서 서빙하는 런타임)
curl -L https://ollama.com/install.sh | sh
2️⃣ 7B 인스트럭션 튜닝 모델 다운로드 (Mistral-7B-instruct)
ollama pull mistral:7b-instruct-q4_0
3️⃣ 모델 부팅 확인
ollama run mistral:7b-instruct-q4_0 "What is RAG?"
처음 두 명령어는 10Gbps 연결 환경에서 약 8~10분 정도 소요됩니다. 세 번째 명령어는 2초 이내에 간결한 답변을 반환해야 하며, 이것이 정상 작동 여부를 확인하는 검증(sanity check) 단계입니다.
3️⃣ 벡터 스토어 (Vector Store) 설정
저는 ChromaDB를 사용하고 있습니다. 순수 Python 기반이며, 오프라인에서 작동하고, Ollama와 호환성이 좋기 때문입니다. 가상 환경(virtual environment)에 설치하세요:
venv 생성
python3 -m venv rag-env
source rag-env/bin/activate
의존성 설치
pip install chromadb sentence-transformers tqdm
이제 임베딩 모델 (embedding model)이 필요합니다. Sentence-Transformers의 all-mpnet-base-v2 인코더는 속도와 품질 사이의 최적의 균형점을 제공합니다.
python -
4️⃣ 문서 인제스트 (Ingest)
데모를 위해 저는 PDF와 Markdown 파일이 담긴 폴더를 사용했습니다. 아래 스크립트는 폴더를 순회하며, 평문 텍스트를 추출하고 (PDF의 경우 pdfminer.six 사용), 이를 500 토큰 단위의 청크 (chunk)로 나누며, 각 청크를 임베딩하여 Chroma에 저장합니다.
pip install pdfminer.six tiktoken
python -
제 노트북에서 200페이지 분량의 PDF를 처리하는 데 약 3분이 소요되었습니다. 핵심 요점은 임베딩은 일회성으로만 수행하면 된다는 것이며, 나머지 파이프라인은 오프라인 상태를 유지합니다.
5️⃣ 검색(Retrieval) + 생성(Generation) 루프 연결
벡터 스토어가 준비되었으므로, 마지막 단계는 사용자 질의를 받아 상위 k개의 관련 청크를 추출하고 이를 로컬 LLM에 전달하는 가벼운 Flask API를 만드는 것입니다.
pip install flask
python -
python app.py로 서비스를 시작한 후 다음 명령어로 호출하세요:
curl -X POST http://localhost:8080/rag -H "Content-Type: application/json" -d '{"question":"What is the retention policy for client data?"}'
AI의 답변과 사용된 정확한 청크(chunks)를 포함하는 JSON 페이로드를 확인할 수 있습니다. 이는 감사 가능성(auditability) 측면에서 매우 완벽합니다.
노트북 규모의 성능을 위한 Ollama 모델 튜닝
기본 설정 상태에서 mistral:7b-instruct-q4_0 모델은 8GB MacBook Air에서 초당 약 1.2 토큰(tokens/second)의 속도로 실행됩니다. 짧은 답변에는 괜찮지만, 긴 형식의 답변에는 적합하지 않습니다. 재학습 없이 조정할 수 있는 세 가지 설정값(knobs)은 다음과 같습니다:
- 양자화 수준 (Quantization level). Ollama는 4비트(q4_0) 및 8비트(q8_0) 변형 모델을 제공합니다. RAM 여유가 조금 더 있다면, q8_0로 전환하여 약 30%의 속도 향상을 꾀할 수 있습니다.
- 컨텍스트 윈도우 (Context window). 서버를 시작할 때
--max-context 2048을 전달하여 프롬프트 길이를 제한하고 OOM(Out Of Memory) 오류를 방지하세요. - 온도(Temperature) 및 top-p. 온도를 0.2로, top-p를 0.9로 낮추면 검색(retrieval) 중심 작업에서 환각(hallucination) 현상을 줄일 수 있습니다.
세 가지 조정을 모두 적용한 실행 명령 예시:
ollama serve mistral:7b-instruct-q8_0 --max-context 2048 --temperature 0.2 --top-p 0.9
테스트 및 문제 해결 – 미니 체크리스트
- 임베딩 불일치 (Embedding mismatch). Chroma에서 "결과 없음"이 나온다면, 청킹(chunking)에 사용된 토크나이저(tokenizer)가 인덱스를 구축할 때 사용한 것과 일치하는지 다시 확인하세요. 스크립트의 tiktoken 인코더는 쿼리 시점에 사용하는 버전과 동일해야 합니다.
- Ollama 멈춤 현상 (Ollama hangs). macOS의 경우, 새로 실행한 후 첫 번째 추론(inference) 단계에서 샌드박스 권한 문제로 인해 지연될 수 있습니다.
chmod +x $(which ollama)를 실행하고 바이너리를 재시작하세요. - GPU 폴백 (GPU fallback). 외장 GPU를 사용 중이라면, 서버를 실행하기 전에 환경 변수
OLLAMA_GPU=1을 설정하세요. Ollama가 자동으로 행렬 연산(matrix math)을 오프로드(offload)합니다. - 메모리 급증 (Memory spikes).
ps -o %mem,rss,command -p $(pgrep -f ollama)를 사용하여 RAM을 모니터링하세요. 사용량이 80%를 초과하면 4비트 모델로 전환하거나max-context를 줄이세요.
프로덕션 적용 – 에이전시에서의 작업 방식
Flask API가 안정화되면, 전체 스택을 버전 관리하고 어떤 노트북에서도 몇 초 만에 배포할 수 있도록 Docker를 사용하여 컨테이너화합니다.
Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python", "app.py"]
빌드 및 실행:
docker build -t local‑rag .
docker run -d -p 8080:8080 --restart unless-stopped local‑rag
실제 운영 환경(Production)에서는 엔드포인트를 비공개로 유지하기 위해 HTTP 기본 인증 (HTTP basic auth) 기능이 포함된 아주 작은 리버스 프록시 (Reverse-proxy, Caddy 또는 Nginx)를 추가합니다. 또한, /knowledge_base 폴더에 새로 들어오는 모든 PDF에 대해 인제스션 (Ingestion) 스크립트를 다시 실행하도록 매일 밤 크론 잡 (Cron job)을 예약하여, 수동 작업 없이 운영합니다.
핵심 요약 (Key Takeaways)
- RAG 파이프라인 (Pipeline)을 로컬에서 실행하는 것은 더 이상 연구용 활동에만 국한되지 않습니다. 최신 8GB 노트북에서도 벡터 스토어 (Vector store)와 함께 7B 인스트럭션 튜닝 (Instruction-tuned) 모델을 호스팅할 수 있습니다.
- 모든 무거운 작업 (모델 다운로드, 임베딩 (Embedding), 벡터 인덱싱 (Vector indexing))은 일회성 비용이며, 일상적인 쿼리 (Query)는 1초 미만으로 수행됩니다.
- Ollama는 GPU/CPU의 세부 사항을 추상화하여, 사용자가 프롬프트 엔지니어링 (Prompt engineering)과 데이터 위생 (Data hygiene)에 집중할 수 있게 해줍니다.
- 감사 가능성 (Auditability)이 자동으로 제공됩니다. API는 답변과 함께 정확히 검색된 청크 (Chunks)를 반환합니다.
- Flask 서비스를 컨테이너화하면 10대 이상의 노트북을 사용하는 팀 전체로 확장하는 것이 매우 간단해집니다.
Signal Notes의 에피소드를 각색했습니다. 즐겨 사용하는 팟캐스트 앱에서 들어보세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기