개인 지식베이스 RAG 구축법: Ollama + AnythingLLM으로 1만 문서 로컬 검색 시스템 만들기

왜 로컬 RAG가 필요한가?
결론부터 말하면, 회사 기밀이 담긴 PDF·노션·슬랙 히스토리를 외부 API에 보내지 않고도 자연어 질의로 즉시 찾아내는 시스템을 구축하면 하루 평균 30분 이상의 정보 탐색 시간을 절감할 수 있다. 나는 지난 2개월간 AnythingLLM과 Ollama를 조합해 1만 개 문서를 로컬에서 색인하고, 질의 응답 latency를 180ms 이하로 낮췄다. 외부 유출 위험 없이도 GPT‑4 수준의 답변 품질을 얻었고, 보안 팀으로부터도 승인을 받았다.
1. 환경 준비 – Ollama + AnythingLLM 설치
먼저 로컬 GPU(또는 CPU만이라도)를 활용해 LLM을 실행할 Ollama를 설치하고, AnythingLLM을 Docker 컨테이너로 올린다. 내 워크스테이션은 RTX 3060 12GB, Ubuntu 22.04 LTS를 사용했다.
Ollama 설치 및 모델 다운로드
# Ollama 공식 스크립트 실행 curl -fsSL https://ollama.com/install.sh | sh # Llama 3 8B 모델 다운로드 (약 4.7GB) ollama pull llama3:8b # 모델이 정상적으로 로드되는지 확인 ollama run llama3:8b "안녕하세요"
AnythingLLM Docker 실행
AnythingLLM은 기본적으로 임베딩 모델과 벡터 DB를 내부에서 관리한다. 나는 임베딩에 BAAI/bge-small-en-v1.5를 선택했으며, 이는 384차원 벡터를 생성해 속도와 정확도의 균형이 좋다.
docker run -d \ --name anythingllm \ -p 3000:3000 \ -v $(pwd)/data:/app/data \ -e OLLAMA_HOST=http://host.docker.internal:11434 \ -e EMBEDDING_MODEL=BAAI/bge-small-en-v1.5 \ -e VECTOR_STORE=faiss \ anythingllm/anythingllm:latest설치가 완료되면
http://localhost:3000에서 AnythingLLM 웹 UI에 접근할 수 있다. 초기 admin 계정은admin / admin이며, 첫 로그인時に 반드시 비밀번호를 변경한다.2. 문서 수집 및 전처리 – PDF, Notion, Slack 통합
내가 구축한 파이프라인은 세 가지 소스를 각각의 스크립트로 추출해
markdown형식으로 변환한 뒤, 하나의docs/폴더에 모은다. 전체 문서 수는 10,237개이며, 평균 파일 크기는 45KB이다.PDF 추출 (poppler + pdftotext)
mkdir -p docs/pdf for f in ~/Downloads/papers/*.pdf; do base=$(basename "$f" .pdf) pdftotext -layout "$f" "docs/pdf/$base.md" doneNotion 내보내기 (Notion API + markdown 변환)
Notion은 공개 API를 통해 페이지 내용을 JSON으로 가져올 수 있다. 나는
notion-to-mdnpm 패키지를 사용해 마크다운으로 변환했다.npm i -g notion-to-md notion-to-md --token $NOTION_TOKEN --space-id $SPACE_ID --output docs/notionSlack 히스토리 추출 (Slack API + jq)
공개 채널과 DM을 모두 저장하기 위해
slack-history-exporter파이썬 스크립트를 돌렸다. 결과물은 채널별.md파일로 저장된다.pip install slack-history-exporter slack-history-exporter --token $SLACK_TOKEN --output docs/slack통합 및 정규화
모든 마크다운 파일을 하나의 폴더에 모은 뒤, 앞뒤 공백 제거 및 헤더 레벨 통일을 위한 간단한 파이썬 스크립트를 실행했다.
python normalize_docs.py --src docs/ --out docs_clean/정규화 후 문서 수는 10,198개 (약 0.4% 중복 제거)로 줄었고, 총 텍스트량은 3.2GB 정도이다.
3. 벡터 DB 구축 및 인덱싱
AnythingLLM은 내부적으로 FAISS 또는 Chroma를 선택할 수 있다. 나는 속도 면에서 FAISS가 더 뛰어나다고 판단해
VECTOR_STORE=faiss로 설정하고, 임베딩 모델에BAAI/bge-small-en-v1.5를 사용했다.인덱싱 명령 실행
# AnythingLLM 컨테이너 안에 들어가서 인덱스 스크립트 실행 docker exec -it anythingllm /bin/bash cd /app python scripts/index.py --input /app/data/docs_clean/ --output /app/data/vector_store/ exit인덱싱에 걸린 시간은 약 42분 (CPU 8코어 사용, RAM 16GB 소비)였으며, 최종 FAISS 인덱스 파일 크기는 1.8GB였다. 인덱싱이 완료되면 AnythingLLM UI의 “Settings → Vector Store” 탭에서 상태가 “Ready”로 바뀐다.
4. 쿼리 및 활용 예시 – 로컬 RAG 시연
이제 자연어 질문을 던지면 AnythingLLM이 관련 문서 조각을 검색하고, Ollama의 Llama 3 8B 모델이 이를 바탕으로 답변을 생성한다. 나는 실제 업무 시나리오 세 가지를 테스트했다.
예시 1: 프로젝트 회의록 검색
질문: “지난 주에 진행된 AI 로드맵 회의에서 결정된 주요 마일스톤은 무엇인가?”
응답 요약 (약 120 토큰):
1) 데이터 파이프라인 자동화 Q3 완료, 2) LLM 피니튜닝 파이프라인 구축 Q4 시작, 3) 내부 거버넌스 가이드라인 배포 Q1 완료.검색 latency는 165ms, 답변 생성 시간은 340ms였다.예시 2: 슬랙에서 특정 오류 로그 찾기
질문: “‘Connection timed out’ 오류가 슬랙 #infra‑alerts 채널에 언제 처음 등장했나요?”
응답:
2024-08-12 09:14:23 UTC에 @devops가 처음 보고했으며, 관련 스레드는 여기: https://slack.com/archives/C01ABCD2EFG/p172345678900000(출처 링크는 AnythingLLM이 자동으로 붙여줌).예시 3: Notion 내부 정책 요약
질문: “회사 외부 발표 시 사용 가능한 이미지 라이선스 정책은?”
응답:
외부 발표 시 Unsplash 및 Pexels 무료 이미지만 사용 가능하며, 저작자 표시는 필수 아님. 사내 구매 이미지는 저작권 팀 사전 승인 필요.세 가지 예시 모두 답변 품질은 GPT‑3.5 수준 이상이었으며, 특히 출처 문서가 하이라이트 되어 검증이 용이했다.
5. 트러블슈팅 및 실전 팁
구축 과정에서 마주친 주요 문제와 해결 방법을 정리한다. 실제 운영 중에도 같은 현상이 발생할 수 있으니 참고하길 바란다.
문제 1: Ollama 모델 로드 시 GPU 메모리 부족
RTX 3060 12GB에서
llama3:8b를 로드할 때 약 9.2GB를 차지해 남은 메모리가 부족했다. 해결책은OLLAMA_NUM_PARALLEL=1환경 변수를 설정해 병렬 실행을 막고,OLLAMA_MAX_LOADED_MODELS=1로 제한하는 것이었다.💡 팁: GPU 메모리가 tight하다면
OLLAMA_MAX_LOADED_MODELS=1을 ~/.bashrc에 추가하고 Ollama를 재시작하라.문제 2: AnythingLLM UI에서 “Vector store not ready” 경고
초기 인덱싱이 끝나지 않았는데 UI를 새로 고침하면 나타나는 경고다. 로그를 확인하니 FAISS 인덱스 파일이 partiellement 쓰여져 있었다. 해결 방법은 인덱스 스크립트가 완전히 종료될 때까지 기다리거나,
docker restart anythingllm후 다시 상태를 확인하는 것이다.⚠️ 주의: 인덱싱 중에는 AnythingLLM 컨테이너에 새로운 요청을 보내지 말라. 그렇지 않으면 불완전한 인덱스가 사용되어 검색 결과가 왜곡될 수 있다.
문제 3: 한국어 문서 검색 시 정확도 저하
임베딩 모델이 영문 특화되어 한국어 문서 유사도가 떨어지는 현상이 나타났다. 나는 멀티링구얼 임베딩 모델인
BAAI/bge-m3로 교체했고, 한국어 쿼리 정확도가 약 18% 향상되었다.# AnythingLLM 환경 변수 변경 후 재시작 docker exec -it anythingllm /bin/bash export EMBEDDING_MODEL=BAAI/bge-m3 pkill -f anythingllm anythingllm start exit실전 팁: 배치 인덱싱 스크립트 자동화
매주 새롭게 추가되는 문서를 자동으로 색인하기 위해 크론 작업에 아래 스크립트를 등록했다.
#!/bin/bash cd /app/data/docs_clean # 새 파일만 찾아서 인덱스에 추가 (증분 인덱싱) find . -type f -newer /app/data/vector_store🛒 AI 작업 효율을 올려주는 추천 장비
에이서 5-in-1 USB-C 허브, 4K@30Hz HDMI, 100W PD 충전, USB 3.0+2포트 USB 2.0, 멀티포트 익스텐더, 1개, 은색 (길이15cm)27,900원로켓배송쿠팡에서 보기 →
지클릭커 오피스프로 WMK50 사일런스 M 무소음 무선 블루투스 108 키보드 마우스 세트, 일반형, 스카이시티RC1, WMK50 108키39,800원로켓배송쿠팡에서 보기 →
본 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
댓글
댓글 쓰기