LangChain에서의 Agentic RAG
요약
고정된 흐름의 2단계 RAG와 달리, LLM이 질문의 의도를 판단하여 검색 도구 사용 여부를 스스로 결정하는 Agentic RAG의 개념과 구현 방법을 설명합니다. LangChain을 사용하여 검색 기능을 도구(Tool)로 래핑하고 에이전트를 구축하는 과정을 다룹니다.
핵심 포인트
- Agentic RAG는 LLM이 검색 필요성을 직접 판단하여 효율성을 높임
- 검색 기능을 @tool 데코레이터로 래핑하여 에이전트에게 전달
- 에이전트의 도구 활용 능력을 높이기 위해 명확한 Docstring 작성 필수
- 질문의 성격에 따라 검색을 수행하거나 건너뛰는 유연한 워크플로우 구현
이전 포스트에서는 질문이 무엇이든 관계없이 항상 검색(retrieval)이 발생하는 2단계 RAG 시스템을 구축했습니다. 질문을 하면, 검색하고, 답변합니다. 단순하고 예측 가능합니다.
하지만 이것을 생각해 보세요. 누군가 단순히 _"안녕하세요! 어떻게 지내세요?"_라고 말한다면 — 그것을 위해 정말 벡터 데이터베이스(vector database)를 검색해야 할까요? 당연히 아닙니다. 그것이 바로 Agentic RAG가 해결하는 문제입니다.
Agentic RAG란 무엇인가?
2단계 RAG에서는 **사용자(you)**가 검색이 언제 일어날지를 제어합니다. 흐름은 고정되어 있습니다:
질문(Query) → 검색(retrieve) → 답변(answer)
Agentic RAG에서는 LLM이 검색이 언제 일어날지를 결정합니다:
질문(Query) → 에이전트(agent)가 생각함 → "검색이 필요한가?" → 검색할 수도 있음 → 답변(answer)
에이전트는 질문이 실제로 무엇을 필요로 하는지에 따라 검색을 집어 들거나 내려놓을 수 있는 하나의 도구(tool)로 취급합니다. 때로는 한 번 검색하고, 때로는 여러 번 검색하며, 때로는 전혀 검색하지 않기도 합니다.
2단계 RAG vs Agentic RAG
| 2단계 RAG | Agentic RAG | |
|---|---|---|
| 검색을 누가 제어하는가? | 사용자 (개발자) | LLM (에이전트) |
| ... |
우리가 구축할 것
이전과 동일한 지식 베이스(knowledge base) — LangChain 개념에 관한 5개의 문서입니다. 하지만 이번에는 항상 검색하는 대신, LLM에게 검색 도구(search tool)를 주고 언제 사용할지 결정하게 합니다.
우리는 3가지 쿼리(query)를 실행할 것입니다:
- 검색이 필요한 사실적 질문
- 검색이 필요하지 않은 일상적인 인사
- 검색이 필요한 또 다른 사실적 질문
코드를 살펴보겠습니다.
1단계: 동일한 지식 베이스, 동일한 벡터 스토어(Vector Store)
from langchain_core.documents import Document
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
...
여기서 새로운 것은 없습니다. 이전과 마찬가지로 문서를 임베딩(embed)하고 FAISS에 저장합니다.
2단계: 검색을 도구(Tool)로 래핑(Wrapping)하기
이 부분이 Agentic RAG가 2단계 RAG와 다른 점입니다. 코드에서 검색을 직접 호출하는 대신, @tool 데코레이터로 래핑하여 에이전트에게 전달합니다.
from langchain.tools import tool
@tool
...
여기서 주목해야 할 몇 가지 사항이 있습니다:
Docstring (독스트링)이 매우 중요합니다. 에이전트는 도구가 무엇을 하는지, 언제 사용해야 하는지를 이해하기 위해 이를 읽습니다. 단순히 개발자를 위한 주석이라고 생각하지 말고, LLM (Large Language Model)에게 전달하는 지침(instruction)처럼 명확하게 작성하세요.
**similarity_search(query, k=2)**는 이전 포스트의 retriever.invoke()와 동일한 작업을 수행합니다. 즉, 가장 유사한 문서 2개를 찾습니다. 단지 도구 함수 내부에서 이를 호출하는 더 직접적인 방법일 뿐입니다.
이것은 일반 문자열(plain string)을 반환합니다. 에이전트가 결과를 읽어야 하므로, 우리는 문서들을 하나의 읽기 쉬운 문자열로 결합합니다.
Step 3: 에이전트 생성하기
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
...
에이전트는 다음을 전달받습니다:
- LLM — 추론을 위한 두뇌
- 도구(tools) 리스트 — 사용이 허용된 도구들
- 시스템 프롬프트 (system prompt) — 에이전트의 성격과 지침
여기서 시스템 프롬프트가 중요합니다: "답을 모른다면, search_docs 도구를 사용하세요." 이는 에이전트에게 먼저 자신의 지식에 의존하고, 정말로 필요할 때만 검색하도록 지시합니다.
Step 4: 에이전트 실행하기
queries = [
"What is RAG and how does it work?",
"Hello! How are you?",
...
각 쿼리에 대해 실제로 일어나는 일
Q: "What is RAG and how does it work?"
↓
Agent thinks: "I should look this up"
...
중간에 있는 쿼리가 2단계 RAG (2-step RAG)와의 핵심적인 차이점입니다. 불필요한 검색도, 낭비되는 토큰(token)도 없습니다.
전체 코드
import os
from dotenv import load_dotenv
...
핵심 통찰 (The Key Insight)
@tool 데코레이터와 docstring이 결합되어 이 기능이 작동하게 만듭니다. 에이전트는 "항상 검색하라" 또는 "절대 검색하지 마라"와 같은 하드코딩된 규칙을 가지고 있지 않습니다. 에이전트는 도구의 설명을 읽고, 질문을 읽은 뒤, 마치 사람처럼 판단을 내립니다.
이것이 search_docs의 docstring이 매우 중요한 이유입니다:
"""지식 베이스에서 관련 정보를 검색합니다.
LangChain, RAG, 에이전트 또는 관련 주제에 대한 사실을 찾아봐야 할 때 이 도구를 사용하세요."""
해당 설명은 말 그대로 이 도구를 언제 사용해야 하는지에 대한 에이전트(agent)의 지침서(instruction manual)입니다. 설명을 모호하게 작성하면 에이전트가 잘못된 시점에 도구를 사용할 것이고, 명확하게 작성하면 에이전트가 정확히 필요한 시점에 도구를 사용할 것입니다.
주의해야 할 사항
더 큰 권한에는 더 큰 책임이 따릅니다. 에이전트가 검색 시점을 직접 결정하기 때문에, 잘못 작성된 시스템 프롬프트(system prompt)나 도구 설명은 에이전트가 검색하지 말아야 할 때 검색을 하거나, 검색해야 할 때 검색을 건너뛰게 만들 수 있습니다. 여러분의 쿼리(query)를 테스트해 보세요.
때로는 쿼리당 비용이 더 많이 발생합니다. 에이전트가 검색을 수행할 때, 검색을 할지 말지 결정하기 위해 추가적인 LLM 호출(LLM call)을 한 번 더 수행합니다. 고정된 데이터셋에 대해 단순하고 대량의 Q&A를 처리해야 한다면, 2단계 RAG (2-step RAG)가 실제로 더 현명한 선택일 수 있습니다.
여러 개의 도구를 제공할 수 있습니다. 웹 검색이나 계산기 같은 두 번째 도구를 추가하는 것을 막는 규칙은 없습니다. 에이전트는 질문에 가장 적합한 도구를 선택할 것입니다. 바로 이 지점에서 에이전트형 RAG (Agentic RAG)가 진정으로 빛을 발하기 시작합니다.
어떤 것을 사용할 것인가
- 모든 쿼리에 검색이 필요하고 단순하며 예측 가능한 동작을 원한다면 **2단계 RAG (2-step RAG)**를 사용하세요.
- 질문이 혼합되어 있어 어떤 것은 검색이 필요하고, 어떤 것은 필요 없으며, 어떤 것은 여러 번의 검색이 필요할 수 있다면 **에이전트형 RAG (Agentic RAG)**를 사용하세요.
2단계 RAG로 시작하세요. 그 한계에 부딪혔을 때 에이전트형으로 넘어가세요. 그것이 실무적인 경로입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기