서론
요즘 RAG 시스템은 챗봇이나 검색 기반 AI 서비스를 만들 때 꼭 필요한 기술이에요. 저 또한 회사에서 AI 관련 기능을 준비하고 있고, 트렌드이기 때문에 학습에 도전해보았어요!
먼저 RAG 시스템이 무엇일까요? 검색 증강 생성 기술로 LLM이 답변을 생성하기 전에 신뢰할 수 있는 외부 지식 베이스를 참조함으로써 정확성 높이고, 잘못된 정보 생성 (할루시네이션)을 줄이기 위해 개발된 컨텍스트 증강 기술이에요.
라마인덱스(LlamaIndex)는 RAG 시스템을 쉽고 체계적으로 구축할 수 있도록 도와주는 프레임워크!
RAG를 구축하는 과정은 보통 다음과 같은 단계로 이루어져요:
데이터 로딩 → 텍스트 분할 → 인덱싱 및 저장 → 쿼리 검색
이 과정을 예시로, “영화 리뷰 데이터”를 다루는 케이스를 기반으로 하나씩 정리했어요!
1. 데이터 로딩 (Data Loading)
데이터를 불러오는 단계예요.
라마인덱스에서는 다양한 형태의 데이터를 읽을 수 있도록 데이터 커넥터와 데이터 리더를 제공해요.
- 데이터 커넥터: 웹, 데이터베이스, 구글 드라이브 등 여러 소스에서 데이터를 가져오는 역할 (예: Llama Hub 커넥터)
- 데이터 리더: 가져온 데이터를 어떻게 처리할지를 결정
대표적으로
SimpleDirectoryReader는 폴더 안의 문서(txt, pdf 등)를 자동으로 읽어옵니다.
💡 예시:
JSON 형태의 데이터를 불러와요.
“조이의 블로그는 개발자에게 도움을 줘요. 다양한 개발 문서가 있어요.” 라는 데이터가 존재하면, 이 데이터는 하나의 문서 객체(Document) 로 변환되어요.
2. 텍스트 분할 (Text Splitting)
불러온 문서를 더 작은 단위로 나누는 단계입니다.
RAG 시스템은 긴 문서 전체보다, 작은 단위로 쪼개진 정보(노드) 를 다루는 게 훨씬 효율적이에요.
- 문서(Document): 원본 데이터를 처리 가능한 형태로 바꾼 기본 단위
- 노드(Node): 문서를 더 세분화한 단위 일반적으로 문장, 문단, 혹은 의미 단위로 나뉩니다!
텍스트 분할 방식 비교
| 방식 | 장점 | 단점 |
|---|---|---|
| 토큰 단위 | 단순, 빠름 | 문맥 끊김 |
| 문장 단위 | 읽기 쉬움 | 의미가 중간에 잘릴 수 있음 |
| 의미 단위 | 문맥 유지 | 처리 시간 길어짐 |
💡 예시:
“조이의 블로그는 개발자에게 도움을 줘요. 다양한 개발 문서가 있어요.”
→ 이 문서는 두 개의 노드로 분할돼요.
Node1: 조이의 블로그는 개발자에게 도움을 줘요.
Node2: 다양한 개발 문서가 있어요.분할 과정에서는 토크나이저(tokenizer) 가 사용되어요. 기본적으로 OpenAI의 cl100k_base 토크나이저가 적용되며, 라마인덱스의 기본 청킹 크기는 1024 토큰이에요.
이 청킹 사이즈는 데이터의 특성이나 목적에 맞게 적절히 조정하는 게 좋아요. 검색 속도나 정확도에 영향을 주는 요소에요.
3. 인덱싱 및 저장 (Indexing & Storage)
이제 분할된 노드들을 벡터화(embedding) 해서 저장해요. 이 과정을 통해 “의미가 비슷한 문장끼리” 서로 가깝게 묶이도록 만들어요.
라마인덱스는 내부적으로 벡터 스토어(Vector Store) 라는 데이터베이스를 사용해요. 가장 많이 쓰이는 오픈소스 벡터 DB는 Chroma 라고 합니다!
그 외에도 LlamaHub 에 접근하면, 라마인덱스와 함께 사용할 수 있는 DB 등을 검색해볼 수 있어요.
- 인덱싱(Indexing): 문서의 의미를 숫자 벡터로 바꿔 저장
- 저장(Storage): 생성된 벡터를 데이터베이스에 영구 보관
이렇게 하면 나중에 비슷한 의미의 문장을 빠르게 검색할 수 있게 됩니다!
4. 쿼리 검색 (Querying)
두둥- 이제 입력에 대한 답변을 받아야겠죠? 마지막 단계는 사용자의 질문에 맞는 정보를 검색하고 답변을 생성하는 과정이에요.
라마인덱스에서는 이를 쿼리엔진(Query Engine) 이 담당하고 있어요.
쿼리엔진은 다음 단계를 거쳐 응답을 만들어요:
- 검색(Search) – 인덱스에서 쿼리와 관련된 상위 K개의 문서를 찾음 (TOP-K 검색)
- 후처리(Post-processing) – 유사도 점수나 조건(ex. 유사도 0.7 이상, 혹은 데이터 타입) 에 따라 필터링
- 응답 합성(Response synthesis) – 필터링된 문서 내용을 기반으로 LLM이 자연스러운 문장을 만들어 응답
💡 예시:
사용자 질문: “조이의 블로그는 개발자에게 도움이 될까요?”
→ 벡터 DB에서 ‘개발자’와 관련된 노드를 찾아요.
→ “조이의 블로그는 개발자에게 도움을 줘요.” 문장이 검색돼요.
→ LLM이 “네, 조이의 블로그는 개발자에게 도움을 준다고 합니다.” 라고 응답을 생성해요.
🎁 정리
| 단계 | 주요 역할 | 예시 |
|---|---|---|
| 데이터 로딩 | 데이터를 불러와 문서 객체로 변환 | JSON 불러오기 |
| 텍스트 분할 | 문서를 문장 단위로 쪼개기 | Node1, Node2 생성 |
| 인덱싱 및 저장 | 문장을 벡터로 변환 후 저장 | 의미 기반 검색 준비 |
| 쿼리 검색 | 질문에 맞는 문장 검색 및 답변 생성 | “블로그가 도움이 되나요?” → “네 도움이 돼요.” |