기본 전략

기본 전략 (Basic Strategies)

RAG 워크플로의 성능을 빠르게 끌어올리고 싶을 때 시도할 수 있는 쉬운 방법들을 소개해요. 프롬프트 엔지니어링, 임베딩 선택, 청크 크기 조정, 하이브리드 검색 등을 살펴봅시다.

출처: 문서

본문

RAG 워크플로에서 빠르게 추가 성능을 짜내 최적화해야 할 때 시도할 수 있는 쉬운 방법이 많습니다.

프롬프트 엔지니어링

환각(hallucination)이나 형식이 잘못된 출력 같은 LLM 관련 실패를 만난다면, 가장 먼저 시도해 볼 것 중 하나가 이것입니다.

간단한 것부터 고급까지의 몇 가지 작업은 아래와 같습니다.

  1. RAG 워크플로에서 사용되는 프롬프트(예: 질문-답변 프롬프트)를 검사하고 커스터마이징해 보세요.
  1. **프롬프트 함수(prompt functions)**를 추가해 few-shot 예제를 동적으로 주입하거나 주입된 입력을 처리해 보세요.

임베딩

올바른 임베딩 모델을 선택하는 것은 전체 성능에서 큰 역할을 합니다.

  • OpenAI의 text-embedding-ada-002보다 더 강력하거나 최신 모델을 원할 수 있습니다(여전히 하위 호환성을 위해 OpenAIEmbedding 기본값입니다)?
  • 호스팅 API를 호출하는 대신 로컬에서 모델을 실행하고 싶을 수 있습니다?
  • 특정 언어에 잘 동작하는 임베딩 모델이 필요할 수 있습니다?

OpenAI 외에도 임베딩 API, 로컬에서 임베딩 모델 실행, 자체 서버 호스팅 등 다양한 옵션이 존재합니다.

MTEB 리더보드는 수많은 데이터셋과 태스크에서 현재 모델들을 비교하기에 가장 좋은 곳입니다. 작성 시점에 인기 있는 오픈소스 선택지는 다음과 같습니다.

  • 빠르고 작은 기준 모델(~22-33M params): sentence-transformers/all-MiniLM-L6-v2 또는 BAAI/bge-small-en-v1.5. 아주 작고 빠르며 많은 워크로드에서 여전히 견고합니다.
  • 중간 크기, 최신 아키텍처(~150M params): lightonai/DenseOn, 2026년 4월 출시. 작은 기준 모델과 Qwen3 계열 사이의 크기로, 0.6B+ 모델로 갈 필요 없이 최신 SOTA 검색을 시도해 보고 싶다면 고려할 만합니다.
  • 강력한 올라운더형 다국어(~0.6-4B params): Qwen/Qwen3-Embedding-0.6B (더 높은 정확도에는 -4B). MTEB에서 경쟁력 있고 단일 GPU에서 서빙할 만큼 작습니다.
  • 마찰 없는 호스팅 API: OpenAIEmbedding(model="text-embedding-3-small").

위의 로컬/오픈소스 옵션은 모두 HuggingFaceEmbedding으로 사용할 수 있고 CPU에서 ONNX/OpenVINO 가속의 이점을 얻습니다. 자세한 내용은 embeddings 가이드를 참고하세요.

참고: 언제든 바꿀 수 있는 LLM과 달리, 임베딩 모델을 바꾸면 데이터를 다시 인덱싱해야 합니다. 또한 인덱싱과 쿼리 모두 같은 임베딩 모델을 사용해야 합니다.

지원되는 모든 임베딩 모델 통합 목록이 있습니다.

청크 크기 (Chunk Sizes)

인덱싱하는 데이터 유형이나 검색 결과에 따라 청크 크기 또는 청크 오버랩을 커스터마이징하고 싶을 수 있습니다.

문서가 인덱스에 수집(ingest)될 때 일정량의 오버랩을 두고 청크로 분할됩니다. 기본 청크 크기는 1024이고 기본 청크 오버랩은 20입니다.

이 두 파라미터를 바꾸면 계산되는 임베딩이 달라집니다. 청크 크기가 작을수록 임베딩이 더 정밀해지며, 청크 크기가 클수록 임베딩이 더 일반적일 수 있지만 미세한 세부 사항을 놓칠 수 있습니다.

청크 크기에 대한 [자체 초기 평가]((https://blog.llamaindex.ai/evaluating-the-ideal-chunk-size-for-a-rag-system-using-llamaindex-6207e5d3fec5)를 진행했습니다.

또한 벡터 인덱스의 청크 크기를 바꿀 때는 각 쿼리에 대해 검색할 데이터 양을 더 잘 나타내도록 similarity_top_k 파라미터도 함께 늘리는 것이 좋습니다.

전체 예제는 다음과 같습니다.

from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
from llama_index.core import Settings


documents = SimpleDirectoryReader("./data").load_data()


Settings.chunk_size = 512
Settings.chunk_overlap = 50


index = VectorStoreIndex.from_documents(
    documents,
)


query_engine = index.as_query_engine(similarity_top_k=4)

기본 청크 크기를 절반으로 줄였으므로, 이 예제는 similarity_top_k도 기본값 2에서 4로 두 배로 늘립니다.

하이브리드 검색은 시맨틱 검색(즉 임베딩 유사도)과 키워드 검색의 결과를 결합하는 검색을 일컫는 흔한 용어입니다.

임베딩은 완벽하지 않으며 검색 단계에서 키워드가 일치하는 텍스트 청크를 반환하지 못할 수 있습니다.

이 문제의 해결책은 흔히 하이브리드 검색입니다. LlamaIndex에서 이를 달성하는 두 가지 주요 방법이 있습니다.

  1. 하이브리드 검색 기능이 있는 벡터 데이터베이스 사용(지원되는 벡터 저장소 전체 목록).
  2. BM25로 로컬 하이브리드 검색 메커니즘 설정.

두 접근법에 대한 관련 가이드는 아래에서 찾을 수 있습니다.

리랭킹 (Reranking)

리랭킹은 RAG 품질에서 가장 영향력이 큰 지렛대 중 하나입니다. 리트리버가 더 넓은 후보 집합(similarity_top_k=10 이상)을 반환하고, 리랭커(더 강력하지만 느린 모델)가 이를 재정렬해 최고의 노드가 LLM에 도달하도록 합니다. 종종 "검색이 대략 맞는 것 같다"와 "검색이 실제로 질문에 답한다"의 차이를 만듭니다.

마찰 없는 레시피는 로컬 cross-encoder를 SentenceTransformerRerank로 사용하는 것입니다. API 키 없이 어디서든 실행됩니다.

from llama_index.core.postprocessor import SentenceTransformerRerank


reranker = SentenceTransformerRerank(
    model="cross-encoder/ms-marco-MiniLM-L6-v2", top_n=3
)


query_engine = index.as_query_engine(
    similarity_top_k=10,
    node_postprocessors=[reranker],
)

다국어 콘텐츠에 더 강한 품질이 필요하면 모델을 Qwen/Qwen3-Reranker-0.6B로 바꾸세요. 최소 설정의 호스팅 API 옵션에는 CohereRerank, JinaRerank, VoyageAIRerank를 사용하세요. 지연 시간이 중요하지 않을 때 최고 품질을 원한다면 LLM 기반 리랭커(LLMRerank, RankGPTRerank)가 추가 LLM 호출 비용으로 cross-encoder를 능가할 수 있습니다.

전체 목록은 node postprocessors 가이드와 의사결정 트리는 rerankers 개요를 참고하세요.

메타데이터 필터 (Metadata Filters)

문서를 벡터 인덱스에 넣기 전에 문서에 메타데이터를 붙이는 것이 유용할 수 있습니다. 이 메타데이터는 나중에 response 객체에서 답변의 출처를 추적하는 데 사용할 수 있을 뿐 아니라, 쿼리 시점에 top-k 유사도 검색을 수행하기 전에 데이터를 필터링하는 데도 사용할 수 있습니다.

메타데이터 필터를 수동으로 설정해 일치하는 메타데이터를 가진 노드만 반환되게 할 수 있습니다.

from llama_index.core import VectorStoreIndex, Document
from llama_index.core.vector_stores import MetadataFilters, ExactMatchFilter


documents = [
    Document(text="text", metadata={"author": "LlamaIndex"}),
    Document(text="text", metadata={"author": "John Doe"}),
]


filters = MetadataFilters(
    filters=[ExactMatchFilter(key="author", value="John Doe")]
)


index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine(filters=filters)

GPT-4 같은 고급 LLM을 사용하고 벡터 데이터베이스가 필터링을 지원한다면, AutoVectorRetriever를 사용해 쿼리 시점에 LLM이 필터를 자동으로 작성하게 할 수 있습니다.

문서/노드 사용

Documents/Nodes 사용법에 대한 자세한 내용은 심층 가이드를 참고하세요.

멀티 테넌시 RAG (Multi-Tenancy RAG)

RAG 시스템의 멀티 테넌시는 데이터 보안을 보장하는 데 중요합니다. 사용자가 자신의 인덱싱된 문서에만 접근할 수 있게 하여 무단 공유를 방지하고 데이터 프라이버시를 보호합니다. 검색 연산은 사용자 자신의 데이터로 제한되어 민감한 정보를 보호합니다. VectorStoreIndex와 VectorDB 제공자를 메타데이터 필터를 통해 구현할 수 있습니다.

자세한 내용은 아래 가이드를 참고하세요.

LlamaIndex와 Qdrant로 멀티 테넌시 RAG를 구현하는 자세한 지침은 Qdrant가 발행한 블로그 포스트를 참고하세요.

더 알아보기 (Learn more)