3

Why: RAG만으로는 부족한 이유, Agent가 중심인 이유

RAG + Agent 파이프라인 통합

학습 목표
  • RAG-only vs Agent-orchestrated의 차이를 이해한다
  • Agent 중심 아키텍처의 장점을 설명할 수 있다
  • Tool 설계의 핵심 원칙을 안다

RAG만으로는 왜 부족한가?

시나리오: "CNC-001 알람 E-042, 관련 부품 재고 있어?"

[RAG-only 시스템]
  질문 -> 벡터 검색 -> 매뉴얼 문서 반환 -> LLM 답변
  결과: "E-042는 스핀들 과열입니다. 냉각수를 확인하세요."

  문제: "관련 부품 재고" 에 대한 답이 없다!
  왜? -> RAG는 문서만 검색하지, DB를 조회하지 않으니까.

[Agent 시스템]
  질문 -> Agent 분석 -> "3가지 작업이 필요하군"
    1) RAG: 매뉴얼에서 E-042 정보 검색
    2) KG: CNC-001 관련 부품 목록 조회
    3) 종합: 부품 정보 + 매뉴얼 정보를 합쳐 답변

  결과: "E-042는 스핀들 과열입니다.
         CNC-001의 냉각수펌프(CP-007) 점검이 필요합니다.
         CP-007은 CL-003 냉각시스템에 연결되어 있습니다."

Agent 중심 아키텍처의 핵심

                    ┌──────────────┐
                    │   Agent      │
                    │  (두뇌)      │
                    │              │
                    │  "이 질문은  │
                    │   RAG+KG가  │
                    │   필요하군"  │
                    └──────┬───────┘
                           │
              ┌────────────┼────────────┐
              │            │            │
        ┌─────▼────┐ ┌────▼─────┐ ┌────▼──────┐
        │ RAG Tool │ │ KG Tool  │ │ Calc Tool │
        │ (팔)     │ │ (팔)     │ │ (팔)      │
        └──────────┘ └──────────┘ └───────────┘

Agent = 두뇌 (어떤 도구를 쓸지 결정) Tools = (실제 작업 수행)

핵심: Agent는 도구를 직접 구현하지 않는다. 도구를 선택하고 조합한다.


좋은 Tool 설계의 3원칙

1. 하나의 도구 = 하나의 책임

# [나쁜 예] 하나에 다 넣기
@tool
def do_everything(query: str) -> str:
    # RAG도 하고 KG도 하고 계산도 하고...
    ...

# [좋은 예] 책임 분리
@tool
def search_documents(query: str) -> str:
    """매뉴얼에서 관련 문서를 검색합니다"""
    ...

@tool
def query_knowledge_graph(entity_id: str) -> str:
    """설비의 관련 노드를 Knowledge Graph에서 탐색합니다"""
    ...

2. 명확한 설명 = Agent의 판단력

# [나쁜 예] 설명이 부실
@tool
def search(q: str) -> str:
    """검색합니다"""  # Agent: "뭘 검색하라는 거지?"

# [좋은 예] Agent가 판단할 수 있는 설명
@tool
def search_documents(query: str) -> str:
    """설비 매뉴얼, 안전 규정, 작업 절차서에서
    관련 내용을 검색합니다.
    설비 고장, 알람 대응, 안전 수칙 질문에 사용하세요."""

3. 구조화된 입출력

# [나쁜 예] 자유 형식
@tool
def kg_query(text: str) -> str:
    ...

# [좋은 예] 구조화
@tool
def query_knowledge_graph(
    entity_id: str,
    relation_type: str = "all",
    depth: int = 2
) -> str:
    """Knowledge Graph에서 엔티티의 관련 노드를 탐색합니다.

    Args:
        entity_id: 설비 ID (예: 'CNC-001')
        relation_type: 관계 유형 ('PART_OF', 'HAS_SENSOR', 'all')
        depth: 탐색 깊이 (기본 2)
    """
    ...

오늘 만들 도구 3개

도구역할사용 시점
search_documents매뉴얼/규정 검색절차, 규정, 방법 질문
query_knowledge_graph설비 관계 탐색관계, 영향, 연결 질문
calculate수치 계산계산, 변환 질문

설비 상태 조회를 따로 두고 싶어지겠지만, 시드에 있는 설비 속성은 관계 탐색 결과에 이미 실린다. 도구를 늘리면 LLM 이 고를 후보가 늘어 잘못 고를 여지도 함께 는다. MVP 에서는 셋이면 충분하고, 필요해지면 그때 넷째를 만든다.


서비스 객체를 도구 안으로 들여보내기

여기서 한 번 걸린다. @tool 이 붙은 함수의 인자는 LLM 이 채운다. 그러니 search_documents(query, rag_service) 처럼 서비스를 인자로 둘 수 없다. LLM 이 RAGService 인스턴스를 만들어 줄 리가 없다.

바깥 함수가 서비스를 받고, 그 안에서 도구를 정의해 클로저로 잡는다.

def create_rag_tool(rag_service):        # <- 여기서 서비스를 받는다
    @tool
    def search_documents(query: str) -> str:   # <- LLM 에게는 query 만 보인다
        """설비 매뉴얼에서 관련 내용을 검색합니다. ..."""
        return rag_service.search_as_text(query)   # <- 클로저로 잡은 것을 쓴다
    return search_documents

tools = [create_rag_tool(rag), create_kg_tool(kg), calculate]

한 가지 더. 도구의 반환값은 문자열이어야 한다. 도구 결과는 ToolMessage 의 본문이 되어 다음 LLM 호출의 컨텍스트로 들어가기 때문이다. SearchResult 객체 리스트를 그대로 돌려주면 안 되고, search_as_text 처럼 사람이 읽을 수 있는 형태로 직렬화해서 넘긴다. 출처와 절 번호를 이 문자열에 함께 실어야 답변에도 출처가 남는다.

AI로 학습하기 — 꿀팁
RAG-only 한계 주장 검증AI 학습 팁

RAG만으로 충분한 경우도 있는데, AI가 Agent 필요성을 과도하게 주장하지는 않는지 반론 관점에서 검증하세요.

'제조 현장 AI에서 RAG만으로는 부족하고 Agent가 필수다'라는 주장을 비판적으로 평가해줘. RAG-only로도 충분히 해결 가능한 제조 Q&A 시나리오는 어떤 것이고, 반드시 Agent가 필요한 시나리오는 어떤 것인지 구체적인 제조 사례로 구분해줘.
이 팁이 도움이 됐나요?
용어