Router와 Orchestration
쿼리를 적절한 데이터 소스로 라우팅하기
Query Routing이란?
정보를 어디서 찾을 것인가
Query Routing은 사용자의 질문을 분석하여 가장 적절한 데이터 소스나 처리 파이프라인으로 연결하는 과정입니다. Agentic RAG에서 Router는 "어디서 정보를 찾을 것인가"를 결정하는 핵심 컴포넌트입니다.
Router 유형
4가지 라우팅 방식
LLM Router
LLM이 쿼리를 분석하고 적절한 데이터 소스를 선택합니다. Function Calling을 활용하여 구조화된 라우팅 결정을 내립니다.
장점: 복잡한 쿼리 이해, 유연한 분류
단점: 지연시간, 비용, 일관성
Semantic Router
쿼리를 임베딩하여 미리 정의된 라우트 임베딩과 유사도를 비교합니다. 빠르고 비용 효율적입니다.
장점: 빠른 속도, 저비용, 일관성
단점: 미리 라우트 정의 필요
Keyword Router
키워드 매칭이나 규칙 기반으로 라우팅합니다. 가장 단순하고 예측 가능한 방식입니다.
장점: 최고 속도, 예측 가능
단점: 유연성 부족, 유지보수
Hybrid Router
키워드 - Semantic - LLM 순으로 단계적으로 적용합니다. 속도와 정확도의 균형을 맞춥니다.
장점: 균형잡힌 성능
단점: 구현 복잡도
라우터 유형별 비교
| Router 유형 | 속도 | 비용 | 정확도 | 유연성 | 적합한 경우 |
|---|---|---|---|---|---|
| LLM Router | 느림 | 높음 | 최고 | 최고 | 복잡한 쿼리, 동적 라우팅 |
| Semantic Router | 빠름 | 낮음 | 높음 | 중간 | 정의된 카테고리, 고성능 필요 |
| Keyword Router | 최고 | 최저 | 제한적 | 낮음 | 단순 분류, 명확한 규칙 |
| Hybrid | 좋음 | 적정 | 높음 | 높음 | 프로덕션 환경, 다양한 쿼리 |
Router 구현 예시
Python 코드로 살펴보기
LLM Router (OpenAI Function Calling)
from openai import OpenAI import json client = OpenAI() # 라우팅 함수 정의 routing_tools = [{ "type": "function", "function": { "name": "route_query", "description": "쿼리를 적절한 데이터 소스로 라우팅", "parameters": { "type": "object", "properties": { "datasource": { "type": "string", "enum": ["vector_db", "web_search", "sql_db", "calculator"], "description": "선택할 데이터 소스" }, "reasoning": { "type": "string", "description": "선택 이유" } }, "required": ["datasource", "reasoning"] } } }] def route_query(query: str) -> dict: response = client.chat.completions.create( model="gpt-4", messages=[ {"role": "system", "content": """당신은 쿼리 라우터입니다. - vector_db: 기술 문서, 제품 정보 등 내부 지식 - web_search: 최신 뉴스, 실시간 정보 - sql_db: 구조화된 데이터, 통계, 리포트 - calculator: 수학 계산, 단위 변환"""}, {"role": "user", "content": query} ], tools=routing_tools, tool_choice={"type": "function", "function": {"name": "route_query"}} ) tool_call = response.choices[0].message.tool_calls[0] return json.loads(tool_call.function.arguments)
Semantic Router
from semantic_router import Route, RouteLayer from semantic_router.encoders import OpenAIEncoder # 라우트 정의 tech_docs = Route( name="technical_docs", utterances=[ "API 사용법 알려줘", "설치 방법이 뭐야?", "에러 코드 E001의 의미는?", "configuration 설정 방법", ] ) latest_news = Route( name="web_search", utterances=[ "오늘 주가 어때?", "최근 AI 트렌드", "어제 발표된 뉴스", "실시간 날씨", ] ) data_query = Route( name="sql_database", utterances=[ "지난달 매출 합계", "고객 수 통계", "분기별 성장률", "상위 10개 제품", ] ) # RouteLayer 생성 encoder = OpenAIEncoder() route_layer = RouteLayer(encoder=encoder, routes=[tech_docs, latest_news, data_query]) # 라우팅 실행 result = route_layer("API 인증 방법 알려줘") print(result.name) # "technical_docs"
Orchestration 패턴
컴포넌트 조율 방식
Orchestration은 여러 컴포넌트(Router, Retriever, Generator)를 조율하여 전체 RAG 파이프라인을 관리합니다.
Sequential Orchestration
단계별로 순차 실행. 가장 단순하고 디버깅이 쉬움.
적합한 경우: 단일 데이터 소스, 예측 가능한 워크플로우
Parallel Orchestration
여러 소스에서 동시에 검색 후 결과 병합.
적합한 경우: 다중 소스 통합, 응답 시간 최적화
Adaptive Orchestration
검색 결과를 평가하고 필요시 재검색. Self-RAG 패턴.
| 부족
Query Rewrite - Re-retrieve
적합한 경우: 높은 정확도 요구, 복잡한 질문
Hierarchical Orchestration
상위 Agent가 하위 Agent들을 관리하는 계층 구조.
|
[Research Agent] [Data Agent] [Code Agent]
|
Supervisor - Synthesize - Response
적합한 경우: 멀티 에이전트 시스템, 복잡한 태스크
Best Practices
실전 적용 팁
모든 라우팅 결정을 로깅하세요. 어떤 쿼리가 어떤 소스로 라우팅되었는지 추적하면 시스템 개선에 필수적인 인사이트를 얻을 수 있습니다.
라우팅 실패나 검색 결과가 없는 경우를 대비한 fallback 전략을 준비하세요. 기본 소스로 돌아가거나, 사용자에게 명확히 알리는 것이 좋습니다.
Adaptive 패턴에서 재검색 횟수를 제한하세요. 최대 반복 횟수(예: 3회)를 설정하여 무한 루프와 비용 폭주를 방지합니다.
다양한 라우팅 전략을 A/B 테스트하세요. LLM Router vs Semantic Router의 정확도와 비용을 실제 트래픽으로 비교해보세요.
참고 자료
더 깊이 학습하기
핵심 요약
- Query Routing은 질문을 적절한 데이터 소스로 연결하는 핵심 컴포넌트
- LLM, Semantic, Keyword, Hybrid 4가지 Router 유형 존재
- 속도-비용-정확도 트레이드오프에 따라 적절한 Router 선택
- Orchestration 패턴: Sequential, Parallel, Adaptive, Hierarchical
- 로깅, Fallback, 루프 제한 등 Best Practices 적용 필수