10분 만에 내 OpenAI 앱에 LLM 폴백을 추가한 방법
Source: Dev.to
당신은 OpenAI에서 프로덕션 앱을 운영하고 있습니다. 어느 화요일 아침에 서비스가 중단됩니다. 앱이 500 오류를 반환하고, status.openai.com을 새로 고치느라 한 시간을 보냅니다.
더 나은 설정이 있습니다. 코드를 다시 작성하지 않고도 모든 OpenAI‑SDK 앱에 제공자 폴백을 추가하는 방법은 다음과 같습니다.
단일 공급자 설정의 문제점
OpenAI를 직접 호출하면 하나의 실패 지점이 있습니다:
from openai import OpenAI
client = OpenAI(api_key="sk-...")
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Summarise this text..."}],
)
OpenAI가 500 또는 429 오류를 반환하면 사용자는 오류를 보게 됩니다. 대체 수단이 없고, 무엇이 실패했는지에 대한 가시성도 없으며, GPT‑4 품질이 필요하지 않을 때 더 저렴한 공급자로 전환할 쉬운 방법도 없습니다.
해결책: 두 줄과 게이트웨이
InferBridge는 OpenAI와 호환되는 API 게이트웨이입니다. OpenAI SDK를 직접 OpenAI 대신 이 게이트웨이로 지정하면 됩니다. 라우팅, 폴백, 요청별 가시성을 처리해 주며 애플리케이션 로직을 건드리지 않습니다.
단계 1: InferBridge 키 받기 (한 번만 실행)
# 계정을 생성하면 InferBridge 키가 한 번만 반환됩니다. 저장해 두세요.
curl -X POST https://api.inferbridge.dev/v1/users \
-H 'Content-Type: application/json' \
-d '{"email":"you@example.com"}'
# {"api_key": "ib_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", ...}
단계 2: 기존 OpenAI 키 등록
curl -X POST https://api.inferbridge.dev/v1/keys \
-H 'Authorization: Bearer ib_xxx...' \
-H 'Content-Type: application/json' \
-d '{"provider":"openai","api_key":"sk-..."}'
키는 저장 시 Fernet으로 암호화됩니다. InferBridge는 요청 내용을 기록하지 않으며 추론 결과에 마크업을 하지 않습니다 — 키는 직접 공급자에게 전달됩니다.
단계 3: 앱에서 두 줄만 수정
from openai import OpenAI
client = OpenAI(
api_key="ib_xxx...", # ← 이전은 sk-...
base_url="https://api.inferbridge.dev/v1", # ← 새 주소
)
resp = client.chat.completions.create(
model="ib/balanced", # ← 이전은 "gpt-4o-mini"
messages=[{"role": "user", "content": "Summarise this text..."}],
)
이것으로 끝입니다. 이제 앱에 폴백 기능이 추가되었습니다.
라우팅 티어가 실제로 하는 일
InferBridge는 마법 같은 자동 분류 대신 명시적인 라우팅 티어를 사용합니다:
| 티어 | 체인 | 사용 시 |
|---|---|---|
ib/cheap | Groq → DeepSeek → Together → Sarvam → OpenAI | 대량, 비용 민감, 품질 유연 |
ib/balanced | OpenAI → Sarvam → Anthropic | 대부분의 프로덕션 앱 기본값 |
ib/premium | Anthropic → OpenAI | 복잡한 추론, 품질 중요 |
라우터는 등록한 제공자 키와 티어를 교차합니다. 따라서 OpenAI 키만 있으면 ib/cheap은 OpenAI로 라우팅됩니다. Groq 키를 등록하면(무료 티어 제공) 동일한 요청 코드가 먼저 Groq에 도달합니다 — 코드 변경이 필요 없습니다.
실제로 폴백이 어떻게 보이는지
OpenAI에서 ib/balanced에 대해 500 오류가 발생해도 애플리케이션에서는 보이지 않습니다. 정상적인 OpenAI 형식의 응답과 함께 깔끔한 200 응답을 받게 됩니다. 유일한 신호는 응답 본문에 추가된 inferbridge 블록에 있습니다:
{
"id": "chatcmpl-...",
"choices": [...],
"usage": {...},
"inferbridge": {
"provider": "anthropic",
"model": "claude-3-5-haiku-20241022",
"mode": "ib/balanced",
"cache_hit": false,
"latency_ms": 834,
"cost_usd": "0.000041",
"residency_actual": "global",
"request_id": "abc123"
}
}
provider: "anthropic"은 OpenAI가 실패하고 Anthropic이 요청을 처리했음을 알려줍니다. 애플리케이션 코드는 변경되지 않았으며, 사용자는 아무것도 보지 못했습니다.
체인에 있는 모든 후보가 실패하면 깔끔한 오류가 반환됩니다:
- 모든 429 오류 →
429 rate_limit_error와Retry-After헤더 - 5xx 오류와 타임아웃이 혼합된 경우 →
502 provider_error또는504 gateway_timeout
무료로 제공되는 가시성
모든 요청이 기록됩니다. 대시보드 없이도 가시성을 제공하는 두 개의 엔드포인트가 있습니다:
# Aggregated stats
GET /v1/stats
# → totals, cache_hit_rate, breakdown by provider/mode/status
# Paginated request log
GET /v1/logs
# → per‑request: provider, model, cost_usd, latency_ms, status, request_id
status는 success, fallback_success, cache_hit, 또는 error가 될 수 있습니다. fallback_success를 필터링하면 기본 제공자가 언제, 얼마나 자주 실패하는지 정확히 확인할 수 있습니다.
옵션: 반복 프롬프트에 대한 캐싱 추가
결정론적 프롬프트(분류, 추출, 템플릿 기반 질의)의 경우, 하나의 헤더를 사용하여 정확히 일치하는 캐싱을 선택할 수 있습니다:
resp = client.chat.completions.create(
model="ib/balanced",
messages=[...],
extra_headers={
"X-InferBridge-Cache": "true",
"X-InferBridge-Cache-TTL": "3600", # seconds
}
)
캐시 키는 provider + model + messages + determinism 파라미터에 대한 SHA‑256 해시입니다. 캐시 히트가 발생하면 inferbridge 블록에 cache_hit: true가 반환되며 토큰 비용이 발생하지 않습니다.
아직 구축되지 않은 것 (스스로 솔직히 말해보세요)
- 대시보드 UI 없음 — 관측은 JSON 엔드포인트만 제공
- 스트리밍 요청이 캐시를 우회함
- 임베딩 엔드포인트 없음
- 비전 입력 없음
- 스트리밍 도구 사용/함수 호출 없음
만약 이러한 항목들이 사용 사례에 장애가 된다면, 기다리거나 우회 방법을 구축해야 할 수도 있습니다. 그렇지 않다면 InferBridge를 시도해보고 최소한의 코드 변경으로 탄력적인 LLM 라우팅을 즐겨보세요.
이 경우 아직 적합하지 않습니다.
시도해 보기
- 무료 티어는 무제한 BYOK입니다. 신용카드가 필요 없습니다.
문서: inferbridge.dev/docs
마이그레이션 가이드: inferbridge.dev/docs/migration-from-openai
문제가 있거나 혼란스러운 부분이 있으면, hello@inferbridge.dev 로 이메일을 보내 주세요 – 실제 받은 편지함으로 전달됩니다.
