[AI] 08_외부_도구_통합 - 100-hours-a-week/9-team-Devths-WIKI GitHub Wiki
단계 6: 외부 도구 통합 및 상용 API 활용
표준화된 도구 통합 및 외부 API 활용 설계
Why: 우리 서비스에 왜 필요한가?
Devths AI 서비스는 자체 GPU 인프라 없이 상용 API를 활용합니다.
외부 도구/API 연동이 필요한 이유:
- LLM/VLM: Gemini API 사용 (GPU 인프라 비용 절감)
- 캘린더: Backend Calendar API와 연동
- OCR: 로컬 PaddleOCR + Gemini Vision Fallback
표준화가 필요한 이유:
- 다양한 외부 시스템을 일관된 방식으로 호출
- API 비용, 응답 지연, 장애 대응 일원화
- 새로운 도구 추가 시 확장 용이
도구/서비스 통합 다이어그램
┌─────────────────────────────────────────────────────────────────┐
│ AI Server (FastAPI) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Tool Manager │ │
│ │ ────────────────────────────────────────────────────────│ │
│ │ • Tool 등록/관리 │ │
│ │ • 호출 라우팅 │ │
│ │ • 에러 핸들링/재시도 │ │
│ └─────────────┬───────────────────────────────┬────────────┘ │
│ │ │ │
│ ┌────────────▼────────────┐ ┌────────────▼────────────┐ │
│ │ External APIs │ │ Internal Tools │ │
│ ├─────────────────────────┤ ├─────────────────────────┤ │
│ │ • Gemini LLM/VLM │ │ • PaddleOCR (로컬) │ │
│ │ • Gemini Embedding │ │ • ChromaDB (로컬) │ │
│ │ • Backend Calendar API │ │ • Redis (로컬/원격) │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
자체 모델 vs 상용 API 비교
| 기준 | 자체 모델 | 상용 API (Gemini) |
|---|---|---|
| 초기 비용 | 높음 (GPU 인프라) | 낮음 (사용량 기반) |
| 운영 비용 | 고정 비용 | 변동 비용 |
| 확장성 | 수동 스케일링 | 자동 스케일링 |
| 유지보수 | 높은 운영 부담 | 낮은 운영 부담 |
| 최신 모델 | 수동 업데이트 | 자동 업데이트 |
결정: 상용 API (Gemini) 사용
- 스타트업 단계에서 인프라 비용 최소화
- 빠른 개발 및 배포 가능
사용 API 목록
| API | 제공사 | 용도 | 가격 | Rate Limit |
|---|---|---|---|---|
| Gemini 1.5 Flash | LLM/VLM | $0.075-$0.30/1M tokens | 1500 RPM | |
| Gemini 1.5 Pro | 고품질 분석 | $1.25-$5.00/1M tokens | 360 RPM | |
| text-embedding-004 | 임베딩 | $0.00001/1K chars | 1500 RPM | |
| PaddleOCR | 로컬 | OCR | 무료 | 무제한 |
Fallback 전략
class APIManager:
async def call_with_fallback(
self,
primary_fn,
fallback_fn,
**kwargs
):
try:
return await primary_fn(**kwargs)
except RateLimitError:
await asyncio.sleep(self.calculate_backoff())
return await primary_fn(**kwargs)
except APIError:
return await fallback_fn(**kwargs)
async def generate(self, prompt: str):
return await self.call_with_fallback(
primary_fn=self.gemini_flash, # 메인: 저렴한 모델
fallback_fn=self.gemini_pro, # Fallback: 고품질
prompt=prompt
)
Fallback 정책
| 상황 | 메인 | Fallback | 동작 |
|---|---|---|---|
| LLM 오류 | Gemini Flash | Gemini Pro | 상위 모델 재시도 |
| OCR 오류 | PaddleOCR | Gemini Vision | VLM으로 대체 |
| Rate Limit | - | Exponential Backoff | 대기 후 재시도 |
| Timeout | - | 캐시 응답 | 가능 시 캐시 반환 |
Agent Tool Calling 설계
사용 가능한 Tools
tools = [
{
"name": "get_schedules",
"description": "지정된 기간의 일정을 조회합니다",
"parameters": {
"start_date": "string (YYYY-MM-DD)",
"end_date": "string (YYYY-MM-DD)"
}
},
{
"name": "add_schedule",
"description": "캘린더에 일정을 추가합니다",
"parameters": {
"title": "string",
"datetime": "string (ISO 8601)"
}
},
{
"name": "update_schedule",
"description": "기존 일정을 수정합니다",
"parameters": {"schedule_id": "string", ...}
},
{
"name": "delete_schedule",
"description": "일정을 삭제합니다",
"parameters": {"schedule_id": "string"}
}
]
Tool 실행 흐름
사용자: "내일 오후 2시에 카카오 면접 추가해줘"
│
▼
[LLM] Intent 파싱 → add_schedule 선택
│
▼
[Tool Executor] POST /api/calendar 호출
│
▼
[Response] "내일 오후 2시에 카카오 면접 일정을 추가했습니다."
비용 분석
월간 예상 비용 (10,000 요청 기준)
| 항목 | 계산 | 비용 |
|---|---|---|
| LLM (Flash) | 10,000 × 3,000 tokens × $0.075/1M | ~$22.5 |
| LLM (Pro, 10%) | 1,000 × 5,000 tokens × $1.25/1M | ~$6.25 |
| Embedding | 10,000 × 2,000 chars × $0.00001/1K | ~$2.0 |
| 총계 | ~$31/월 |
비용 최적화 전략
- 캐싱: 동일 요청 캐싱으로 API 호출 40% 감소
- Flash 우선: 복잡한 분석만 Pro 사용
- 토큰 최적화: 프롬프트 압축으로 30% 절감
확장성 계획
향후 도구 추가 고려
| 도구 | 용도 | 우선순위 |
|---|---|---|
| Slack/Discord 연동 | 알림 전송 | 중 |
| Google Calendar API | 외부 캘린더 동기화 | 중 |
| 이메일 발송 | 리포트 전송 | 하 |
확장 전략
- Tool Interface 표준화: 모든 Tool은 동일한 인터페이스 구현
- Plugin 방식: 새 Tool 추가 시 코드 변경 최소화
- Config 기반 등록: YAML/JSON으로 Tool 정의
결론
외부 도구 통합 설계를 통해:
- 비용 효율: 상용 API로 GPU 인프라 비용 제거
- 안정성: Fallback 전략으로 장애 대응
- 확장성: 표준화된 인터페이스로 새 도구 추가 용이
- 자연스러운 연동: Tool Calling으로 캘린더 CRUD 구현