AI 답변의 신뢰성은 모델 성능보다 데이터 상태에서 갈렸다. 뉴스가 오래됐든 임베딩이 빠졌든 서비스가 막혔든 답변은 자연스럽게 나오니까, 답변 이전에 데이터 상태를 먼저 보여주는 쪽으로 설계했다.

| 문제 | 운영 리스크 |
|---|---|
| 오래된 뉴스 | 지난 근거로 현재 판단을 만든다 |
| 임베딩 누락 | 검색 품질이 떨어져도 알 수 없다 |
| 대체 문서 | 임시 문서가 RAG 근거에 섞인다 |
| 서비스 호출 제한 | 호출 실패가 분석 누락이 된다 |
| 뉴스 소스 상태 불명확 | 어떤 소스가 죽었는지 모른다 |
AI 답변보다 RAG 품질을 먼저 드러낸다. 원문 메타데이터와 검색용 청크는 따로 저장하고, 검색은 kNN 벡터와 BM25 키워드를 함께 쓴다. 서비스 라우터가 Gemini와 OpenAI 후보의 차단 상태를 계산해 한 서비스 장애가 전체를 멈추지 않게 하고, 오래된 데이터와 임베딩 누락, 서비스 실패는 화면과 API에 경고로 띄운다.
2026.07에는 목적별 제한 시간이 붙었다. 분석·매수 사전 점검·채팅·리포트·임베딩·번역마다 제한 시간을 두고 SDK 자체 재시도는 억제했다. 분석이 제한 시간을 넘기면 현재 주기를 HOLD로 저장하고, 매수 사전 점검이 넘기면 주문 0회로 끝낸다.
for candidate in candidates:
try:
value = await operation(candidate)
except AIProviderRateLimitError as exc:
await self.mark_rate_limited(candidate.provider, exc)
continue
except Exception as exc:
if is_provider_rate_limit_error(candidate.provider, exc):
await self.mark_rate_limited(candidate.provider, exc)
else:
await self.mark_error(candidate.provider, exc)
continue
await self.mark_success(candidate.provider)
return AIProviderExecutionResult(
value=value,
provider=candidate.provider,
model=candidate.model,
)
한 서비스가 할당량이나 호출 제한으로 막혀도 AI 기능 전체가 멈추지 않는다. 차단된 서비스는 후보에서 빠지고 대체 서비스가 실제로 쓰이는지를 테스트로 고정했다.
if real_documents <= 0:
warnings.append(_rag_warning("no_real_documents", "critical", {...}))
if fallback_documents > 0:
warnings.append(_rag_warning("fallback_documents_present", "warning", {...}))
if embedding_total > 0:
missing_ratio = missing_embedding_documents / embedding_total
if missing_ratio >= 0.5:
warnings.append(_rag_warning("missing_embedding_high", "warning", {...}))
실제 문서 부재, 대체 문서, 임베딩 누락을 등급이 있는 경고로 올린다. 대체 뉴스가 긍정 신호로 과대평가되지 않는지도 검증했다.