원문: RAG is dead, long live agentic retrieval

Sourabh Desai

May 29, 2025

RAG는 단순한 청크 검색의 시대를 지나 많은 발전을 이루었고, 이제 에이전트 기반 전략이 기본이 되었습니다.

요즘 AI 엔지니어는 하이브리드 검색, CRAG, Self-RAG, HyDE, 심층 연구, 재순위화, 다중 모드 임베딩, RAPTOR 등 에이전트 시스템의 데이터 검색 측면을 포괄하는 수많은 기술과 용어를 알고 있어야 합니다.

LlamaCloud에서 검색 서비스를 구축하면서 저희는 이러한 기술 중 일부를 API로 추상화하고, 이러한 알고리즘을 제어하기 위한 몇 가지 최상위 하이퍼파라미터만 노출하기로 결정했습니다. 이 블로그 게시물에서는 이러한 다양한 기술을 소개하고 사용 방법과 시기를 설명합니다. 이러한 기술을 하나씩 기반으로 구축하여 여러 지식 베이스를 한 번에 지능적으로 쿼리할 수 있는 완전한 에이전트 기반 검색 시스템으로 마무리할 것입니다.

기본부터 시작하기

RAG를 이야기하려면 “단순 상위 k개 검색”을 빼놓을 수 없습니다. 이 기본 방식에서는 문서 청크가 벡터 데이터베이스에 저장되고, 쿼리 임베딩이 가장 유사한 k개의 청크 임베딩과 매칭됩니다.

다음은 간단한 PDF 폴더를 인덱싱하는 기본 코드 스니펫입니다.

import os
from llama_index.indices.managed.llama_cloud import LlamaCloudIndex
# ^ pip install llama-index-indices-managed-llama-cloud
 
financial_index = LlamaCloudIndex.from_documents(
    documents=[],  # 원시 파일을 업로드할 것이므로 문서는 비워 둡니다.
    name="Financial Reports",
    project_name=project_name,
)
 
financial_reports_directory = "./data/financial_reports"
for file_name in os.listdir(financial_reports_directory):
    file_path = os.path.join(financial_reports_directory, file_name)
    # 각 파일을 슬라이드 인덱스에 추가합니다.
    financial_index.upload_file(file_path, wait_for_ingestion=False)
 
financial_index.wait_for_completion()

이 인덱싱이 완료되면 한 줄만 더 추가하여 이러한 청크를 검색할 수 있습니다.

query = "마이크로소프트 본사는 어디에 있나요?"
nodes = financial_index.as_retriever().retrieve(query)
 
# 또는 Settings 객체를 설정했다면 여기에서 전체 응답을 생성합니다.
response = financial_index.as_query_engine().query(query)

이 단순한 chunk 검색 모드를 약간 넘어서, 관련 파일의 전체 내용을 검색하려는 경우 두 가지 모드가 더 있습니다.

  • files_via_metadata - 특정 파일 이름이나 경로 이름이 언급된 쿼리를 처리하려는 경우 이 모드를 사용합니다. 예: “2024_MSFT_10K.pdf 파일은 MSFT의 재무 전망에 대해 무엇이라고 말하나요?“.
  • files_via_content - 특정 파일 집합이 아닌 주제에 대한 일반적인 질문을 하는 쿼리를 처리하려는 경우 이 모드를 사용합니다. 예: “MSFT의 재무 전망은 어떻습니까?“.

chunk 검색이 기본 모드이지만 retrieval_mode kwarg를 통해 다른 검색 모드 중 하나를 사용할 수 있습니다.

files_via_metadata_nodes = financial_index.as_retriever(retrieval_mode="files_via_metadata").retrieve(query)
 
files_via_content_nodes = financial_index.as_retriever(retrieval_mode="files_via_content").retrieve(query)

레벨 업: 자동 모드

이제 각 검색 모드를 사용하는 방법과 시기를 이해했으므로 지식 베이스에 대한 모든 유형의 질문에 답할 수 있는 능력을 갖추게 되었습니다!

그러나 많은 애플리케이션은 어떤 유형의 질문이 미리 제기될지 알지 못합니다. 대부분의 경우 이러한 질문은 최종 사용자가 합니다. 주어진 쿼리에 어떤 검색 모드가 가장 적합한지 알 수 있는 방법이 필요합니다.

네 번째 검색 모드인 auto_routed 모드를 시작하세요! 이름에서 알 수 있듯이 이 모드는 경량 에이전트를 사용하여 주어진 쿼리에 대해 다른 3가지 검색 모드 중 어떤 것을 사용할지 결정합니다.

이 모드를 사용하는 것은 다른 모드를 사용하는 것만큼 간단합니다.

nodes = financial_index.as_retriever(retrieval_mode="auto_routed").retrieve("마이크로소프트 본사는 어디에 있나요?")
# retrieval_mode 메타데이터 값을 통해 쿼리가 어떤 모드로 라우팅되었는지 확인할 수 있습니다.
 
# 입력 쿼리가 특정 정보에 대해 묻고 있으므로 "chunks"를 인쇄합니다.
print(nodes[0].metadata["retrieval_mode"])

단일 지식 베이스를 넘어서 확장하기

auto_routed 모드를 사용하면 다양한 질문에 유능하게 답변할 수 있는 경량 에이전트 시스템을 갖게 됩니다. 그러나 이 시스템은 검색 공간 측면에서 다소 제한적입니다. 단일 인덱스에 수집된 데이터만 검색할 수 있습니다.

모든 문서가 동일한 형식(예: 모두 SEC 10K 제출 서류)인 경우 모든 문서를 단일 인덱스를 통해 수집하는 것이 실제로 적절할 수 있습니다. 해당 단일 인덱스의 구문 분석 및 청크 구성은 이 동종 문서 집합의 서식에 맞게 고도로 최적화될 수 있습니다. 그러나 전체 지식 베이스에는 SEC 제출 서류, 회의록, 고객 서비스 요청 등 다양한 파일 형식이 포함될 것입니다. 이러한 다른 형식에는 구문 분석 및 청크 설정이 각 문서 하위 집합에 최적화된 별도의 인덱스를 설정해야 합니다.

이전 코드 스니펫의 financial_index에 SEC 제출 서류가 있고, 추가로 슬라이드 쇼 폴더에서 .ppt PowerPoint 파일을 수집한 slides_index를 만들었다고 가정해 보겠습니다.

import os
from llama_index.indices.managed.llama_cloud import LlamaCloudIndex
# ^ pip install llama-index-indices-managed-llama-cloud
 
slides_index = LlamaCloudIndex.from_documents(
    documents=[],  # 원시 파일을 업로드할 것이므로 문서는 비워 둡니다.
    name="Slides",
    project_name=project_name,
)
 
# 슬라이드 파일을 인덱스에 추가합니다.
slides_directory = "./data/slides"
 
for file_name in os.listdir(slides_directory):
    file_path = os.path.join(slides_directory, file_name)
    # 각 파일을 슬라이드 인덱스에 추가합니다.
    slides_index.upload_file(file_path, wait_for_ingestion=False)

이제 애플리케이션에서 사용자가 financial_index에 수집한 SEC 제출 서류 및 slides_index에 수집한 회의 슬라이드 쇼에 대해 질문할 수 있습니다.

이것이 바로 Composite Retrieval API가 빛을 발하는 부분입니다! 단일 인덱스가 아닌 여러 인덱스에서 관련 콘텐츠를 검색할 수 있는 단일 검색 API를 제공합니다. Composite Retrieval API는 클라이언트에 경량 에이전트 계층을 노출하여 각 하위 인덱스에 대한 이름 및 설명을 지정할 수 있도록 합니다. 이러한 매개변수는 에이전트가 복합 리트리버에 추가한 다양한 인덱스 간에 질문을 라우팅하는 방법을 제어하는 데 도움이 될 수 있습니다.

from llama_cloud import CompositeRetrievalMode
from llama_index.indices.managed.llama_cloud import LlamaCloudCompositeRetriever
 
composite_retriever = LlamaCloudCompositeRetriever(
    name="My App Retriever",
    project_name=project_name,
    # "My App Retriever"라는 이름의 리트리버가 아직 없으면 생성됩니다.
    create_if_not_exists=True,
    # CompositeRetrievalMode.ROUTED는 쿼리를 인덱스 하위 집합으로 라우팅합니다.
    mode=CompositeRetrievalMode.ROUTED,
    # 쿼리된 모든 인덱스에서 상위 5개 결과를 반환합니다.
    rerank_top_n=5,
)
 
# 위의 인덱스를 복합 리트리버에 추가합니다.
# CompositeRetrievalMode.ROUTING이 사용될 때 쿼리를 연결된 하위 인덱스로 내부적으로 라우팅하는 데 사용되므로 설명을 신중하게 작성하십시오.
composite_retriever.add_index(
    slides_index,
    description="팀 회의 중에 발표된 슬라이드 쇼 정보 소스",
)
 
composite_retriever.add_index(
    financial_index,
    description="회사 재무 보고서 정보 소스",
)
 
# 이 두 인덱스 모두에서 한 번에 쿼리 시작
nodes = retriever.retrieve("2024년 4분기 최고 수익 제품의 주요 특징은 무엇이었나요?")

지식 에이전트 구성하기

이제 개별 및 다중 인덱스 수준 모두에서 에이전트를 사용하는 방법을 알았으므로 검색의 모든 단계에서 에이전트 기반 검색을 수행하는 단일 시스템을 구성할 수 있습니다! 그렇게 하면 LLM을 사용하여 검색 경로의 모든 계층을 최적화할 수 있습니다.

시스템은 다음과 같이 작동합니다.

  1. 최상위 계층에서 복합 리트리버는 LLM 기반 분류를 사용하여 지정된 쿼리에 대해 어떤 하위 인덱스(또는 인덱스)가 관련이 있는지 결정합니다.
  2. 하위 인덱스 수준에서 auto_routed 검색 모드는 쿼리에 가장 적합한 검색 방법(예: chunk, files_via_metadata 또는 files_via_content)을 결정합니다.

다음은 코드 구현입니다.

from llama_cloud import CompositeRetrievalMode
from llama_index.indices.managed.llama_cloud import LlamaCloudCompositeRetriever
 
# 복합 리트리버 생성
composite_retriever = LlamaCloudCompositeRetriever(
    name="Knowledge Agent",
    project_name=project_name,
    create_if_not_exists=True,
    mode=CompositeRetrievalMode.ROUTED,  # 지능적인 인덱스 선택을 위해 라우팅 모드 사용
    rerank_top_n=5,  # 상위 5개 결과 재순위화 및 반환
)
 
# 자세한 설명과 함께 하위 인덱스 추가
composite_retriever.add_index(
    financial_index,
    description="SEC 제출 및 수익 분석을 포함한 상세 재무 보고서",
)
 
composite_retriever.add_index(
    slides_index,
    description="제품 업데이트 및 프로젝트 통찰력을 다루는 팀 회의의 슬라이드 쇼",
)
 
# 복합 리트리버 쿼리
query = "2024년 4분기 재무 보고서는 수익 성장에 대해 무엇이라고 말하나요?"
nodes = composite_retriever.retrieve(query)
 
# 쿼리에 사용된 검색 모드 및 결과 인쇄
for node in nodes:
    print(f"Retrieved from: {node.metadata['retrieval_mode']} - {node.text}")

이 설정은 검색 결정이 각 계층에서 지능적으로 라우팅되도록 보장하며, LLM 기반 분류를 사용하여 여러 인덱스 및 검색 모드에서 복잡한 쿼리를 처리합니다. 그 결과 다양한 사용자 쿼리에 동적으로 적응할 수 있는 완전한 에이전트 기반 검색 시스템이 탄생했습니다.

단순 RAG의 시대는 가고, 에이전트 기반 검색의 시대가 온다

에이전트는 최신 애플리케이션의 필수적인 부분이 되었습니다. 이러한 에이전트가 효과적이고 자율적으로 작동하려면 정확하고 관련성 있는 컨텍스트가 손끝에 있어야 합니다. 이것이 바로 정교한 데이터 검색이 모든 에이전트 기반 시스템에 중요한 이유입니다. LlamaCloud는 이러한 지능형 시스템의 중추 역할을 하여 에이전트가 가장 필요할 때와 장소에서 신뢰할 수 있고 정확한 컨텍스트를 제공합니다.