사용자 질문이 들어와서 응답이 나가는 런타임 호출 시퀀스.
💡 핵심 개념: 데이터 흐름(3번)이 "데이터 어디로 가나"라면, 이 도식은 "누가 언제 누구를 부르나". API 서버·Retriever·LLM은 각각 다른 프로세스/스레드일 수 있어 호출 순서·latency 파악이 중요.
sequenceDiagram
actor User as 👤 사용자
participant API as 🖥️ API
participant R as 🔍 Retriever
participant VDB as 🗄️ Vector DB
participant L as 🧠 LLM
User->>API: 질문 입력
activate API
API->>R: 검색 요청 (질의)
activate R
R->>R: 질의 임베딩
R->>VDB: top-k 검색
activate VDB
VDB-->>R: 관련 chunk들
deactivate VDB
R-->>API: 리랭킹된 chunk들
deactivate R
API->>L: 컨텍스트 + 질문
activate L
L-->>API: 응답 생성
deactivate L
API-->>User: 최종 응답
deactivate API
🔧 단계별 latency (typical)
- 질의 임베딩 — 50~200ms (OpenAI API)
- Vector DB 검색 — 5~50ms (Pinecone p95)
- Rerank — 100~300ms (Cohere rerank)
- LLM 응답 — 500~3000ms (GPT-4 streaming 기준 첫 토큰까지)
- 총합 — streaming 안 쓰면 1~4초. UX 임계점: 1초 이내면 "빠르다", 3초 넘으면 "느리다".
📋 구체적 예시 (토스 FAQ 챗봇):
- 사용자 "적금 해지 어떻게 해?" 입력
- API 서버(FastAPI)가 인증·rate-limit 체크 → Retriever 호출
- Retriever가 질의 임베딩 + Qdrant 검색 (top-10)
- Cohere rerank로 top-3 압축
- Prompt 조립:
"고객 상담사처럼 답해. 매뉴얼: {top3}. 질문: {q}"
- GPT-4o 응답 (streaming, 첫 토큰 800ms 후)
- SSE로 사용자에게 토큰 단위 전송
⚠️ 흔한 함정:
- 전체 흐름 동기 호출 — LLM 응답 기다리는 동안 thread 점유. 해결: streaming + 백프레셔
- 에러 시 부분 실패 처리 — 검색 실패해도 LLM만 호출? 또는 전체 fail? 정책 필요
- 타임아웃 미설정 — LLM 30초 걸리면 사용자 떠남. 10초 타임아웃 + graceful 메시지
- rate limit 무시 — 임베딩/LLM API는 분당 호출 제한. 큐잉 필수
🛠️ 도식화 도구: sequenceDiagram(mermaid)이 이 패턴의 표준. PlantUML도 가능. 코드 추적은 OpenTelemetry(분산 trace).