Provider Drift: 기본 라우팅이 LLM 비용을 부풀리는 방식
목차
프롬프트 캐싱을 켰고, 적중 카운터가 가끔 올라가는데도 청구서는 거의 움직이지 않습니다. 프롬프트 구조를 탓하기 전에, 대시보드가 숨기고 있는 한 가지를 살펴보세요. 바로 각 요청을 실제로 처리한 업스트림이 무엇이었는지입니다.
멀티 프로바이더 게이트웨이는 단일 모델을 여러 업스트림 프로바이더에 분산시키고 요청마다 하나를 고릅니다. 프롬프트 캐시는 프로바이더별로(흔히 프로바이더 내부 노드별로) 존재합니다. 그래서 두 번째로 보낸 동일한 요청이 첫 번째와 다른 업스트림에 도착하면, 프롬프트가 단 1바이트도 바뀌지 않았는데도 캐시 미스가 됩니다. 이것이 provider drift이며, 토큰당 과금 모델에서는 조용히 비용을 배가시킵니다.
이를 유발하는 두 가지 조건
이것은 당신이 직접 선택한 잘못된 설정이 아닙니다. 박스에서 꺼낸 그대로의 기본값입니다:
- 기본 자동 라우팅. 요청이 업스트림을 고정하지 않은 채 모델로 전송되어, 게이트웨이가 호출마다 하나를 고릅니다.
- 기본 프로바이더 정렬 = “default (balanced)”. 게이트웨이가 하나의 업스트림에 고정하지 않고 적격 업스트림들 사이에서 부하를 분산합니다.
둘 다 공장 기본값입니다. drift를 얻기 위해서는 아무것도 건드릴 필요가 없습니다. drift를 피하려면 설정을 건드려야 합니다.
동일한 요청 20개는 어떻게 보이는가
위 기본값으로 인기 있는 한 멀티 프로바이더 게이트웨이에 동일한 약 8K 토큰 프리픽스를 연속으로 20번 보내면서, 매번 업스트림이 자체 보고하는 프로바이더 및 캐시 필드를 요청했습니다. DeepSeek 계열의 디스크 캐시 모델에 대해:
- 9개의 서로 다른 업스트림이 20번의 호출을 처리했습니다:
N***a,S***w,M***h,D***a,A***L,P***l,S***e,V***e,A***d. - 캐시 적중률: 4/20 (20%). 이미 당신의 프리픽스를 캐시해 둔 업스트림에 우연히 도착한 호출에서만 적중했습니다.
동일한 20번의 호출을 단일 백엔드 게이트웨이(모델 하나, 업스트림 하나, 부하 분산 없음)에 보내면 동일한 워크로드에서 적중률은 19/20 (95%) 입니다. 같은 모델, 같은 프롬프트, 같은 호출 수. 유일한 변수는 라우팅이 drift하는지 여부입니다.
대조를 위해, 동일한 멀티 프로바이더 게이트웨이에서 GPT 계열 모델은 20번의 호출 모두 하나의 업스트림(A***e)으로 라우팅되었고 19/20 적중했습니다. drift는 균일하지 않습니다. 게이트웨이가 우연히 분산하는 모델을 무는데, 이번 실행에서는 그게 DeepSeek 계열 모델이었습니다.
결론 A: 기대했던 비용 vs 실제 지불한 비용
drift가 일어난 모델의 호출당 비용은 캐시 결과에 따라 깔끔하게 나뉘었습니다:
| 호출 유형 | 호출당 중앙값 비용 |
|---|---|
| 캐시 적중 | ~$0.00015 |
| 캐시 미스 | ~$0.00062 |
이 모델에서 미스는 적중의 약 4배 비용입니다(원시 입력 토큰 기준으로는 공시된 격차가 더 커서 대략 50배입니다). 이제 20번의 호출 전체로 합산하면:
| 시나리오 | 적중률 | 동일한 20번 호출 비용 |
|---|---|---|
| 기대값 (캐시 도달 가능) | 95% | $0.0026 |
| 실제값 (기본 drift) | 20% | $0.0102 |
같은 모델, 같은 프롬프트, 같은 20개 요청. provider drift가 실행 비용을 약 3.9배 더 들게 만들었습니다. 캐싱은 내내 “켜져” 있었지만, 라우팅 계층이 토큰 대부분을 미스 요율로 청구했을 뿐입니다. 이를 하루 종일 크고 안정적인 프리픽스를 재생하는 프로덕션 엔드포인트로 확장하면, 그 격차가 입력 지출의 대부분을 차지합니다.
결론 B: 캐시가 없으면 지연 시간 이득도 없다
캐싱은 비용 레버일 뿐만이 아닙니다. 따뜻한 프리필은 첫 토큰을 더 빨리 반환합니다. drift가 캐시를 막으면 그 속도 향상도 잃게 됩니다. 반복되는 동일한 호출에 대해 첫 토큰까지의 시간(TTFT)을 측정했습니다:
GPT 계열 모델 (일관된 하나의 업스트림으로 라우팅, 캐시 도달 가능):
| 호출 | TTFT |
|---|---|
| 1번째 (콜드, 미스) | ~1760 ms |
| 이후 (웜, 적중) | ~1130 ms |
캐싱은 첫 토큰을 약 36% 더 빠르게 해주며, 안정적입니다. 모든 웜 호출이 좁은 범위 안에 들어옵니다.
DeepSeek 계열 모델 (기본 drift, 캐시 도달 드묾):
- 10번 반복 호출에 걸친 캐시 적중: 0.
- TTFT는 호출마다 약 1000 ms에서 4500 ms 사이를 오갔고, 가끔 빈 응답도 있었습니다.
거의 모든 요청이 새 업스트림이기 때문에 콜드 프리필 지연 시간에 머무르고, 응답한 프로바이더가 무엇이든 그 변동성을 그대로 물려받습니다. GPT 모델은 도달 가능한 캐시로 TTFT 36% 개선을 얻었지만, drift하는 모델은 아무것도 얻지 못한 데다 가장 빠른 호출과 가장 느린 호출 사이에 4.5배 격차까지 떠안았습니다.
5분 만에 당신의 설정을 감사하기
이 수치들을, 혹은 누구의 수치든 믿지 마세요. 같은 긴 프리픽스를 여러 번 보내고 두 필드를 지켜보세요. 하드코딩된 도메인은 없습니다. 환경 변수로 당신의 게이트웨이를 가리키세요.
import os, uuid
from openai import OpenAI
client = OpenAI(api_key=os.environ["GW_KEY"], base_url=os.environ["GW_BASE"])
SYS = f"[probe {uuid.uuid4().hex}]\n\n" + ("You are a support assistant. " * 300)
seen, hits = {}, 0
for i in range(20):
r = client.chat.completions.create(
model=os.environ["GW_MODEL"], max_tokens=16,
messages=[{"role": "system", "content": SYS},
{"role": "user", "content": f"q{i}"}],
extra_body={"usage": {"include": True}})
d = r.model_dump()
det = r.usage.prompt_tokens_details
cached = (getattr(det, "cached_tokens", 0) or 0) if det else 0
seen[d.get("provider")] = seen.get(d.get("provider"), 0) + 1 # populated when exposed
hits += 1 if cached else 0
print(f"hit rate {hits}/20; upstreams seen: {len(seen)}")
같은 모델에 대해 업스트림이 둘 이상이면 drift입니다. 프롬프트 안정성에 비해 적중률이 한참 낮다면, 그것이 당신에게 세금을 매기고 있는 것입니다. 더 완전한 방법은 Does Your LLM Gateway Lie About Cache?에 있습니다.
무엇을 찾아야 하는가
drift의 치료법은 구조적입니다. 주어진 모델을 일관된 백엔드로 라우팅해서, 다음 요청에서 따뜻한 캐시가 실제로 도달 가능하도록 하는 것입니다. 호출마다 당신의 프리픽스를 한 번도 본 적 없는 새 업스트림으로 부하 분산하는 대신에요. 게이트웨이를 평가할 때는 같은 프리픽스를 20번 보내고 업스트림 수를 세어 보세요. 하나가 당신이 원하는 것입니다. 아홉은 세금입니다.
공정한 단서 하나: 프롬프트 캐싱은 어디에서나 최선 노력(best-effort)이며, 디스크 캐시 모델에서는 단일 백엔드라 하더라도 오랜 유휴 간격 후에는 적중률이 여전히 무뎌집니다. drift를 없앤다고 무한 캐시가 주어지는 것은 아닙니다. 다만 가장 크고 가장 낭비적인 미스의 원천, 즉 당신이 동의한 적도 없고 볼 수도 없는 그 원천을 제거해 줍니다.
맺음말
“프롬프트 캐싱 지원”과 “당신의 캐시가 도달 가능함”은 서로 다른 주장입니다. 한 모델을 돌아가며 바뀌는 여러 업스트림에 흩뿌리는 게이트웨이는 캐시 지원을 진실하게 보고하면서도 20% 적중률, 약 4배의 청구서, 그리고 4.5배로 출렁이는 첫 토큰 지연 시간을 안겨줄 수 있습니다. 지켜봐야 할 수치는 캐싱이 광고되는지 여부가 아닙니다. 당신이 측정한 적중률, 그리고 동일한 요청이 몇 개의 업스트림에 닿는지입니다. 프로브를 돌려서 데이터가 결론을 내리게 하세요.
더 폭넓은 감사 방법은 Does Your LLM Gateway Lie About Cache?를 참고하세요. 캐시가 애초에 왜