AILlamaIndexRAGLLM

LlamaIndex

·7 min read

늘 하루하루가 새로운 AI 생태계

RAG 관련해서 LangChain 말고도 뭐가 있나 들여다보니 라마 인덱스라는 놈이 있어서 가져와봤다.

LlamaIndex란?

데이터 프레임워크다.

다양한 소스(로컬 파일, SaaS 앱, 데이터베이스)랑 다양한 모델/백엔드에 걸쳐서

데이터에서 수집, 변환, 인덱싱, 검색 및 합성 하는데 쓰인다.

문서(원시 파일, 페이지, DB 행) => 노드(청크 테스트 + 메타데이터) => 인덱스(벡터 인덱스 등) => Retriever(관련 노드 찾기) => 쿼리 엔진(인용으로 최종 답변 합성)

과정에서 관여한다.

LangChain이 다중 에이전트 오케스트레이션 느낌이라면 애는 딱 문서 검색에 최적화 되어있다.

빠른 RAG 구현용으로 한번 써볼만 하다는 것이다.

함 써보자

코드로 애가 어떻게 도는지 확인하는게 더 직관적일 것이다.

"코어 + OpenAI LLM + OpenAI embeddings" pip install llama-index llama-index-llms-openai llama-index-embeddings-openai

"선택항목: 로컬 모델, vector stores, loaders, 등등"

pip install llama-index-llms-ollama llama-index-embeddings-huggingface

pip install llama-index-vector-stores-chroma chromadb

pip install llama-index-readers-notion

Oepn AI 기능 쓰니 환경 변수에 OPENAI_API_KEY로 키를 설정해주자

RAG를 만든다면 다음의 순서를 따를 것이다

파일 로드 => 벡터 인덱스 구축 => 출처와 함께 질문에 답변

그러니 /data 폴더 하나 만들고 md, txt, pdf 등의 파일을 넣어두자

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings from llama_index.llms.openai import OpenAI from llama_index.embeddings.openai import OpenAIEmbedding

모델이랑 임베딩 설정 Settings.llm = OpenAI(model="gpt-4o-mini") 싼거로 하자

Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")

폴더 명만 지정하면 알아서 데이터를 가져온다. docs = SimpleDirectoryReader("data").load_data()

인덱스를 구축하고 index = VectorStoreIndex.from_documents(docs)

쿼리 엔진을 만든다. qe = index.as_query_engine(response_mode="compact") # compact 모드 = 질문과 출처

질문을 던져보자 q = "문서 요약좀, 출처는 명시하고." ans = qe.query(q) print(ans)

품질을 업그레이드 해보자

라마인덱스는 데이터 프레임워크다.

즉 데이터가 제일 중요하다는 뜻이다.

청크 전략

기본 청크 크기를 512~1024로 두고 시작하자

제목, 섹션 같은걸로 분할되어있는 좀 구조를 가진 문서는 semantic 청커 즉, 의미를 기반으로 분해하는 청커를 가져다 쓰자

중간중간 개념이 잘리지 않도록 20~50 토큰 정도는 오버랩 해서 겹침을 유지하자

메타데이터 및 필터

문서에 소스, 섹션, 페이지, 언제 만들었냐 등으로 라벨링(태그)를 해두면 좋다.

태그나 라벨링이 되어있으면 쿼리시 메타데이터 필터를 사용해서 "2025-10-18 이후만" 지정할 수 있다.

Retrieval 업그레이드

순수 벡터 검색하면 의미기반으로 짤라냈으니 의미 유사도에는 강하지만, 정확한 키워드/용어에는 약하다.

Hybrid Retrieval (BM25 + Vector) 방식으로 키워드랑 벡터를 결합하자.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader from llama_index.core.retrievers import QueryFusionRetriever from llama_index.core.query_engine import RetrieverQueryEngine from llama_index.retrievers.bm25 import BM25Retriever "요놈이 키워드"

"벡터 인덱스" docs = SimpleDirectoryReader("data").load_data() vec_index = VectorStoreIndex.from_documents(docs) vec_retriever = vec_index.as_retriever(similarity_top_k=5)

"키워드(BM25) 리트리버" bm25 = BM25Retriever.from_documents(docs, top_k=5)

"여기서 합쳐서 구성 + 점수 정규화/결합" hybrid = QueryFusionRetriever(retrievers=[bm25, vec_retriever], mode="relative_score") qe = RetrieverQueryEngine.from_args(hybrid) print(qe.query("카레 레시피중에 관심 표시 된 레시피?"))

1차 검색에서는 상위 k개 중에는 근사치가 좀 섞여서 가벼운 리랭커 등으로 재정렬하면 정답에 가까운 청크가 더 위로 올라온다.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader from llama_index.postprocessor.cohere_rerank import CohereRerank "또는 SentenceTransformer 기반 리랭커" " 1차 검색" docs = SimpleDirectoryReader("data").load_data() index = VectorStoreIndex.from_documents(docs) retriever = index.as_retriever(similarity_top_k=10)

" 리랭커 후처리" reranker = CohereRerank(top_n=5) "상위 5개만 남기기" qe = index.as_query_engine(retriever=retriever, node_postprocessors=[reranker]) print(qe.query("엑스콤 정예 요원의 명중률은?")) "감나빗!"

복합 질문 보다는 하위 질의로 좀 쪼개서 개별 검색 후 합성하는 방안을 추천한다.

애는 좀 복잡해서 관심있다면 직접 한번 알아보자.

PDF를 잘 처리해보자.

PDF에 대해서는 별도의 처리 기능을 제공하는데

표, 각주, 지저분한 레이아웃에 대한 정제 기능이 존재한다.

LlamaParse라는 직관적인 이름으로 청크가 제목, 목록, 테이블과 같은 구조를 유지하도록 구문 분석을 업그레이드 해서 검색 품질을 개선한다.

from llama_index.core import VectorStoreIndex, Settings from llama_index.core.readers import LlamaParseReader from llama_index.llms.openai import OpenAI from llama_index.embeddings.openai import OpenAIEmbedding

Settings.llm = OpenAI(model="gpt-4o-mini") Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")

"PDF를 마크 다운 형식으로" parser = LlamaParseReader(result_type="markdown") docs = parser.load_data(["./data/annual_report.pdf"])

index = VectorStoreIndex.from_documents(docs) qe = index.as_query_engine() print(qe.query("첫번째 표에 주석에 뭐라고 적혀있어."))

물론 있다는 거지 더 좋은 Parser가 없다는 뜻은 아니니 관심있다면 직접 찾아보자.

KT도 놀라고 구름 EXP도 경악한 Llama의 데이터 분할 능력!

너나한테왜이러는데코드치고자료조사하러다른탭좀다녀오니깐왜내용을니맘대로청크분할을시켜버리는데.아

file_AetPFz8HQvzh0KDISj

← Previous
10년 이상의 경력을 가진 개발자가 초보 개발자들에게 주는 교훈
Next →
AI 시대 생존 방법 by 노정석 대표, 카이스트 김대식 교수