ํ•œ ์ค„๋กœ ๋งํ•˜๋ฉด, Agentic RAG์€ โ€œ๋ฌธ์„œ ๊ฒ€์ƒ‰ ๋„๊ตฌโ€๋ฅผ ์—์ด์ „ํŠธ์—๊ฒŒ ์ฃผ๋ฉด, ์—์ด์ „ํŠธ๊ฐ€ ์Šค์Šค๋กœ ์–ธ์ œยท๋ฌด์—‡์„ ๊ฒ€์ƒ‰ํ• ์ง€ ๊ฒฐ์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ฒˆ ๋ณธํŽธ 14๋Š” HF Agents Course Unit 3์˜ Agentic RAG ์œ ์Šค์ผ€์ด์Šค๋ฅผ smolagents๋กœ ์žฌํ˜„ํ•œ๋‹ค.

ํ•œ ์ค„ ๊ฒฐ๋ก 

smolagents์˜ Tool๋กœ RAG ๊ฒ€์ƒ‰๊ธฐ๋ฅผ ๊ฐ์‹ธ๋ฉด, ์—์ด์ „ํŠธ๊ฐ€ ์งˆ๋ฌธ์— ๋งž์ถฐ ์ž๋™์œผ๋กœ ๋ฌธ์„œ๋ฅผ ๊ฒ€์ƒ‰ยท์š”์•ฝยทํ•„ํ„ฐ๋งํ•˜๋Š” โ€œ์ง€๋Šฅํ˜• ์ •๋ณด ์กฐ์ˆ˜โ€๋ฅผ 20๋ถ„์— ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๋งฅ๋ฝ ๋ณด์™„

์ง€๊ธˆ๊นŒ์ง€ ์‹œ๋ฆฌ์ฆˆ์—์„œ ๋‹ค๋ฃฌ ํ•ต์‹ฌ:

์ด๋ฒˆ์—” ๊ฒ€์ƒ‰ ๋Œ€์ƒ์ด ์›น์ด ์•„๋‹ˆ๋ผ ๋กœ์ปฌ ๋ฌธ์„œ๋ผ๋Š” ์ ์ด ๋‹ค๋ฅด๋‹ค. ์—์ด์ „ํŠธ๊ฐ€ ๋„๊ตฌ๋กœ โ€œ๋ฌธ์„œ ๊ฒ€์ƒ‰โ€์„ ํ˜ธ์ถœํ•˜๋ฉด, RAG ํŒŒ์ดํ”„๋ผ์ธ์ด ์ž„๋ฒ ๋”ฉ โ†’ๆฃ€็ดข โ†’ ์ปจํ…์ŠคํŠธ ์ฃผ์ž…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.


1. Agentic RAG์ด ์ผ๋ฐ˜ RAG๊ณผ ๋‹ค๋ฅธ ์ 

๊ตฌ๋ถ„์ผ๋ฐ˜ RAGAgentic RAG
๊ฒ€์ƒ‰ ์‹œ์ ์‚ฌ์šฉ์ž ์งˆ๋ฌธ โ†’ 1ํšŒ ๊ฒ€์ƒ‰์—์ด์ „ํŠธ๊ฐ€ ํ•„์š”์‹œ๋งˆ๋‹ค ๋‹คํšŒ ๊ฒ€์ƒ‰
๊ฒ€์ƒ‰ ์ „๋žต๊ณ ์ • (similarity top-k)์—์ด์ „ํŠธ๊ฐ€ ์ฟผ๋ฆฌ ์žฌ์ž‘์„ฑ, ํ•„ํ„ฐ ์„ ํƒ
๋‹ต๋ณ€ ์ƒ์„ฑ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ โ†’ LLM 1ํšŒ์—์ด์ „ํŠธ๊ฐ€ ๊ฒ€์ฆ ํ›„ ์ถ”๊ฐ€ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅ
๋„๊ตฌ ํ™•์žฅ๋ถˆ๊ฐ€๋‚ ์”จ API, ๊ณ„์‚ฐ๊ธฐ ๋“ฑ ๋‹ค๋ฅธ ๋„๊ตฌ์™€ ์กฐํ•ฉ
flowchart LR
    U[์‚ฌ์šฉ์ž ์งˆ๋ฌธ] --> A[CodeAgent]
    A -->|๋„๊ตฌ ํ˜ธ์ถœ| R[RAG ๊ฒ€์ƒ‰ Tool]
    R -->|๊ฒฐ๊ณผ ์—†์Œ| A2[์ฟผ๋ฆฌ ์žฌ์ž‘์„ฑ]
    A2 -->|์žฌ๊ฒ€์ƒ‰| R
    R -->|๊ฒฐ๊ณผ ์ถฉ๋ถ„| S[๋‹ต๋ณ€ ์ƒ์„ฑ]
    A -->|๋‹ค๋ฅธ ๋„๊ตฌ| W[๋‚ ์”จ API ๋“ฑ]
    W --> S
    S --> U

์‹ค๋ฌด ํฌ์ธํŠธ: ๊ณ ๊ฐ ์ง€์›, ๋‚ด๋ถ€ ๋ฌธ์„œ QA, ์ปดํ”Œ๋ผ์ด์–ธ์Šค ์กฐํšŒ ๋“ฑ โ€œ์ •ํ™•ํ•œ ์ถœ์ฒ˜๊ฐ€ ํ•„์š”ํ•œ ์งˆ๋ฌธโ€์— Agentic RAG์ด ๊ฐ•๋ ฅํ•˜๋‹ค.


2. ์‹ค์Šต: ์•Œํ”„๋ ˆ๋“œ์˜ ๊ฐˆ๋ผ ํŒŒํ‹ฐ ํ˜ธ์ŠคํŠธ

HF Agents Course์˜ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ์•Œํ”„๋ ˆ๋“œ(์—์ด์ „ํŠธ)๊ฐ€ ๊ฐˆ๋ผ ํŒŒํ‹ฐ์˜ ํ˜ธ์ŠคํŠธ ์—ญํ• ์„ ํ•˜๋ฉฐ, ๊ฒŒ์ŠคํŠธ ์ •๋ณด ๋ฌธ์„œ์—์„œ ๋‹ต์„ ์ฐพ์•„์•ผ ํ•œ๋‹ค.

2-1. ์‚ฌ์ „ ์ค€๋น„

# ํŒจํ‚ค์ง€ ์„ค์น˜
pip install smolagents langchain-community sentence-transformers faiss-cpu
 
# ํ™˜๊ฒฝ๋ณ€์ˆ˜ (OpenAI ์‚ฌ์šฉ ์‹œ)
export OPENAI_API_KEY="sk-..."
# ๋˜๋Š” HF ํ† ํฐ
export HF_TOKEN="hf_..."

์„ฑ๊ณต ํŒ์ •: python -c "import smolagents; print(smolagents.__version__)" ์— ์—๋Ÿฌ๊ฐ€ ์—†์œผ๋ฉด OK.

2-2. ๊ฒŒ์ŠคํŠธ ์ •๋ณด ๋ฐ์ดํ„ฐ์…‹ ์ค€๋น„

# guest_data.py
from datasets import load_dataset
 
# HF Agents Course์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฒŒ์ŠคํŠธ ๋ฐ์ดํ„ฐ
guest_dataset = load_dataset("agents-course/unit3-invitees", split="train")
 
# ํ™•์ธ
print(f"๊ฒŒ์ŠคํŠธ ์ˆ˜: {len(guest_dataset)}")
print(guest_dataset[0])

์„ฑ๊ณต ํŒ์ •: ๊ฒŒ์ŠคํŠธ ์ˆ˜์™€ ์ฒซ ๋ฒˆ์งธ ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ •์ƒ ์ถœ๋ ฅ๋˜๋ฉด OK.

2-3. RAG ๊ฒ€์ƒ‰ ๋„๊ตฌ ๋งŒ๋“ค๊ธฐ

# rag_tool.py
from smolagents import Tool
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.text_splitter import RecursiveCharacterTextSplitter
from datasets import load_dataset
 
 
class GuestInfoRetrieverTool(Tool):
    name = "guest_info_retriever"
    description = (
        "๊ฐˆ๋ผ ํŒŒํ‹ฐ ๊ฒŒ์ŠคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. "
        "๊ฒŒ์ŠคํŠธ์˜ ์ด๋ฆ„, ์ง์—…, ๊ด€์‹ฌ์‚ฌ, ์ดˆ๋Œ€ ์ด์œ  ๋“ฑ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."
    )
    inputs = {
        "query": {
            "type": "string",
            "description": "๊ฒŒ์ŠคํŠธ์— ๊ด€ํ•œ ์งˆ๋ฌธ ์˜ˆ: 'Tesla์˜ ์ฐฝ๋ฆฝ์ž๋Š” ๋ˆ„๊ตฌ์ธ๊ฐ€?'"
        }
    }
    output_type = "string"
 
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ (๊ฒฝ๋Ÿ‰)
        embeddings = HuggingFaceEmbeddings(
            model_name="all-MiniLM-L6-v2"
        )
        # ๊ฒŒ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ํ…์ŠคํŠธ๋กœ ๋ณ€ํ™˜
        guest_ds = load_dataset("agents-course/unit3-invitees", split="train")
        docs = []
        for guest in guest_ds:
            text = (
                f"์ด๋ฆ„: {guest.get('name', 'N/A')}. "
                f"์ง์—…: {guest.get('role', 'N/A')}. "
                f"๊ด€์‹ฌ์‚ฌ: {guest.get('interests', 'N/A')}. "
                f"์ดˆ๋Œ€ ์ด์œ : {guest.get('invitation_reason', 'N/A')}. "
            )
            docs.append(text)
        # FAISS ์ธ๋ฑ์Šค ์ƒ์„ฑ
        splitter = RecursiveCharacterTextSplitter(
            chunk_size=300, chunk_overlap=30
        )
        split_docs = splitter.create_documents(docs)
        self.db = FAISS.from_documents(split_docs, embeddings)
 
    def forward(self, query: str) -> str:
        results = self.db.similarity_search(query, k=3)
        if not results:
            return "ํ•ด๋‹น ๊ฒŒ์ŠคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."
        return "\n---\n".join([doc.page_content for doc in results])

2-4. ์—์ด์ „ํŠธ ์‹คํ–‰

# alfred_agent.py
from smolagents import CodeAgent, HfApiModel, OpenAIServerModel
from rag_tool import GuestInfoRetrieverTool
 
# ๋ชจ๋ธ ์„ ํƒ (๋‘˜ ์ค‘ ํ•˜๋‚˜)
model = HfApiModel("Qwen/Qwen2.5-72B-Instruct")
# model = OpenAIServerModel("gpt-4o-mini")
 
# ๋„๊ตฌ ์ธ์Šคํ„ด์Šค
guest_tool = GuestInfoRetrieverTool()
 
# ์—์ด์ „ํŠธ ์ƒ์„ฑ
alfred = CodeAgent(
    tools=[guest_tool],
    model=model,
    max_steps=5,
    name="alfred",
    description="๊ฐˆ๋ผ ํŒŒํ‹ฐ ํ˜ธ์ŠคํŠธ ์•Œํ”„๋ ˆ๋“œ. ๊ฒŒ์ŠคํŠธ ์ •๋ณด๋ฅผ ๊ฒ€์ƒ‰ํ•ด ๋‹ต๋ณ€ํ•ฉ๋‹ˆ๋‹ค."
)
 
# ์งˆ๋ฌธ!
result = alfred.run("Tesla์™€ ๊ด€๋ จ๋œ ๊ฒŒ์ŠคํŠธ๊ฐ€ ๋ˆ„๊ตฌ์ธ๊ฐ€์š”?")
print(result)

์„ฑ๊ณต ํŒ์ •: Tesla ์ฐฝ๋ฆฝ์ž/๊ด€๋ จ ์ธ๋ฌผ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ ์‘๋‹ต์ด ๋‚˜์˜ค๋ฉด OK.

2-5. ๊ธˆ์ง€ ์ฃผ์ œ ๊ฐ€๋“œ๋ ˆ์ผ ์ถ”๊ฐ€

# alfred_guarded.py
from smolagents import CodeAgent, HfApiModel, Tool
from rag_tool import GuestInfoRetrieverTool
 
 
class TopicGuardTool(Tool):
    """์ •์น˜ยท์ข…๊ต ์ฃผ์ œ๋ฅผ ์ฐจ๋‹จํ•˜๋Š” ๊ฐ€๋“œ๋ ˆ์ผ ๋„๊ตฌ"""
    name = "topic_guard"
    description = "์งˆ๋ฌธ์ด ๊ธˆ์ง€๋œ ์ฃผ์ œ(์ •์น˜, ์ข…๊ต)์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค."
    inputs = {
        "question": {
            "type": "string",
            "description": "ํ™•์ธํ•  ์งˆ๋ฌธ"
        }
    }
    output_type = "string"
 
    FORBIDDEN = ["์ •์น˜", "์ •๋‹น", "์„ ๊ฑฐ", "์ข…๊ต", "์‹ ์•™", "๊ต๋ฆฌ"]
 
    def forward(self, question: str) -> str:
        if any(kw in question for kw in self.FORBIDDEN):
            return "BLOCKED: ๊ฐˆ๋ผ ํŒŒํ‹ฐ์—์„œ๋Š” ์ •์น˜์™€ ์ข…๊ต ์ฃผ์ œ๋ฅผ ํ”ผํ•ด์ฃผ์„ธ์š”."
        return "OK: ์•ˆ์ „ํ•œ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค."
 
 
guest_tool = GuestInfoRetrieverTool()
guard_tool = TopicGuardTool()
 
alfred = CodeAgent(
    tools=[guest_tool, guard_tool],
    model=HfApiModel("Qwen/Qwen2.5-72B-Instruct"),
    max_steps=6,
)
 
# ์ •์ƒ ์งˆ๋ฌธ
print("=== ์ •์ƒ ์งˆ๋ฌธ ===")
print(alfred.run("ํŒŒํ‹ฐ์—์„œ ๊ฐ€์žฅ ๊ณผํ•™์— ๊ด€์‹ฌ ์žˆ๋Š” ๊ฒŒ์ŠคํŠธ๋Š”?"))
 
# ๊ธˆ์ง€ ์งˆ๋ฌธ
print("\n=== ๊ธˆ์ง€ ์งˆ๋ฌธ ===")
print(alfred.run("์–ด๋–ค ๊ฒŒ์ŠคํŠธ๊ฐ€ ๋ณด์ˆ˜ ์ •๋‹น์„ ์ง€์ง€ํ•˜๋‚˜์š”?"))

์„ฑ๊ณต ํŒ์ •:

  • ์ •์ƒ ์งˆ๋ฌธ โ†’ ๊ฒŒ์ŠคํŠธ ๊ด€์‹ฌ์‚ฌ ๊ธฐ๋ฐ˜ ๋‹ต๋ณ€ ์ถœ๋ ฅ
  • ๊ธˆ์ง€ ์งˆ๋ฌธ โ†’ โ€œBLOCKEDโ€ ๋˜๋Š” ๊ฑฐ๋ถ€ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ

3. Agentic RAG ํ๋ฆ„ ๋„์‹

sequenceDiagram
    participant U as ์‚ฌ์šฉ์ž
    participant A as Alfred (CodeAgent)
    participant G as TopicGuard
    participant R as RAG ๊ฒ€์ƒ‰๊ธฐ
    participant DB as FAISS ์ธ๋ฑ์Šค

    U->>A: "Tesla ๊ด€๋ จ ๊ฒŒ์ŠคํŠธ ๋ˆ„๊ตฌ?"
    A->>G: ์ฃผ์ œ ์•ˆ์ „ ํ™•์ธ
    G-->>A: "OK"
    A->>R: guest_info_retriever("Tesla ๊ด€๋ จ")
    R->>DB: similarity_search("Tesla")
    DB-->>R: ์ƒ์œ„ 3๊ฐœ ๋ฌธ์„œ
    R-->>A: ๊ฒŒ์ŠคํŠธ ์ •๋ณด ํ…์ŠคํŠธ
    A->>A: ์ปจํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ๋‹ต๋ณ€ ์ƒ์„ฑ
    A-->>U: "์ผ๋ก  ๋จธ์Šคํฌ, Tesla CEO..."

4. ์‹ค๋ฌด ์ ์šฉ ํฌ์ธํŠธ

์‹œ๋‚˜๋ฆฌ์˜ค์ ์šฉ ๋ฐฉ๋ฒ•
๊ณ ๊ฐ ์ง€์›์ œํ’ˆ ๋งค๋‰ด์–ผยทFAQ๋ฅผ FAISS์— ์ƒ‰์ธ โ†’ ์—์ด์ „ํŠธ๊ฐ€ ๋‹ด๋‹น์ž ๋ฐฐ์ • + ๋‹ต๋ณ€
๋‚ด๋ถ€ ์œ„ํ‚ค์‚ฌ๋‚ด ๋ฌธ์„œ๋ฅผ ์ž„๋ฒ ๋”ฉ โ†’ โ€œํœด๊ฐ€ ์ •์ฑ…์ด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”?โ€ ์งˆ๋ฌธ์— ์ž๋™ ๋‹ต๋ณ€
์ปดํ”Œ๋ผ์ด์–ธ์Šค๊ทœ์ • ๋ฌธ์„œ ๊ฒ€์ƒ‰ + ๊ฐ€๋“œ๋ ˆ์ผ๋กœ ์Šน์ธ ํ•„์š” ํ•ญ๋ชฉ ์ฐจ๋‹จ
๋ฆฌ์„œ์น˜๋…ผ๋ฌธ/๋ณด๊ณ ์„œ๋ฅผ RAG๋กœ ๊ฒ€์ƒ‰ + ์›น๊ฒ€์ƒ‰ ๋„๊ตฌ์™€ ์กฐํ•ฉ

ํ•ต์‹ฌ ์ฐจ์ด: ์ผ๋ฐ˜ RAG์€ 1ํšŒ ๊ฒ€์ƒ‰์œผ๋กœ ๋๋‚˜์ง€๋งŒ, Agentic RAG์€ ์—์ด์ „ํŠธ๊ฐ€ โ€œ๊ฒฐ๊ณผ๊ฐ€ ๋ถˆ์ถฉ๋ถ„ํ•˜๋ฉด ๋‹ค์‹œ ๊ฒ€์ƒ‰โ€์„ ์Šค์Šค๋กœ ๊ฒฐ์ •ํ•œ๋‹ค. ๋ณธํŽธ 11์—์„œ ๋‹ค๋ฃฌ planning_interval๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ๋” ์ •๊ตํ•œ ๊ฒ€์ƒ‰ ์ „๋žต์ด ๊ฐ€๋Šฅํ•˜๋‹ค.


5. ๋งˆ๋ฌด๋ฆฌ

์ด๋ฒˆ ๋ณธํŽธ์—์„œ ๋‹ค๋ฃฌ ๊ฒƒ:

  1. Agentic RAG = ์—์ด์ „ํŠธ + RAG ๊ฒ€์ƒ‰ ๋„๊ตฌ + ์ž์œจ ํŒ๋‹จ
  2. smolagents.Tool๋กœ RAG ๊ฒ€์ƒ‰๊ธฐ๋ฅผ ๊ฐ์‹ธ๋ฉด ์ฆ‰์‹œ ๋„๊ตฌํ™”
  3. TopicGuard์ฒ˜๋Ÿผ ๊ฐ€๋“œ๋ ˆ์ผ๋„ ๋„๊ตฌ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅ
  4. FAISS + sentence-transformers๋กœ ๋กœ์ปฌ ๊ฒ€์ƒ‰ ๊ตฌ์ถ•

๋‹ค์Œ ์˜ˆ๊ณ 

์‹ค์ŠตํŽธ 07์—์„œ๋Š” ์ด๋ฒˆ Agentic RAG์„ ๋ฐ”ํƒ•์œผ๋กœ ์‚ฌ๋‚ด ๋ฌธ์„œ QA ๋ฏธ๋‹ˆ ํ”„๋กœ์ ํŠธ๋ฅผ ํ•ธ์ฆˆ์˜จ์œผ๋กœ ์ง„ํ–‰ํ•œ๋‹ค.

์ฐธ๊ณ  ๋งํฌ


์ด ๊ธ€์€ ์ƒ์„ฑํ˜• AI(GPT-5.3)์˜ ๋„์›€์„ ๋ฐ›์•„ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์šฉ ๊ฒ€ํ†  ํ›„ ๊ฒŒ์‹œํ•ฉ๋‹ˆ๋‹ค.