Smart Routing
스마트 라우팅
모든 요청이 프론티어 모델을 쓸 필요는 없습니다. Celon은 프롬프트 난이도를 수 밀리초 만에 점수화해서, 품질을 지키는 선에서 가장 저렴한 티어로 요청을 보냅니다.
celon/auto — 난이도 기반 자동 라우팅
model: "celon/auto"로 요청하면 규칙 기반 분류기(LLM 호출 없음, CPU <5ms)가 난이도 점수를 0–1 범위로 산출합니다. 점수는 아래 특징의 가중합입니다.
| 특징 | 가중치 | 설명 |
|---|---|---|
promptSize | +0.20 | 프롬프트 토큰 수 (1k 토큰에서 0.5로 포화) |
codePresence | +0.25 | 코드 펜스(```), 코드 토큰, 파일 확장자 |
reasoningSignals | +0.40 | 추론 키워드 — 분석·설계·증명·디버깅, prove·optimize·trade-off … (한/영) |
structuredOutput | +0.15 | tools / tool_choice / JSON response_format 사용 여부 |
simplicitySignals | −0.25 | 요약·분류·번역·추출 키워드, 아주 짧은 프롬프트 (점수를 깎음) |
conversationDepth | +0.10 | 멀티턴 대화 깊이 (누적 컨텍스트) |
점수 → 티어 매핑 (기본 balanced 다이얼 기준): score ≥ 0.62 → Tier 1, score ≥ 0.30 → Tier 2, 그 미만은 Tier 3입니다. 산출된 점수는 응답 메타의 classifier_score로 확인할 수 있습니다.
인텐트 다이얼
같은 분류기라도 워크로드마다 원하는 트레이드오프가 다릅니다. celon.dial(요청 단위) 또는 키의 라우팅 정책(routing.dial)으로 4가지 프리셋 중 하나를 고릅니다. 적용된 다이얼은 응답 메타 dial과 x-celon-dial 헤더로 확인합니다.
| 다이얼 | 동작 원리 | 추천 워크로드 |
|---|---|---|
balanced | 기본값. 임계값 0.62 / 0.30, 스티키 가중치 0.5 — 비용과 품질의 균형점. | 범용 백엔드 · 사내 어시스턴트 · 기본 통합 |
strict-quality | 임계값을 0.45 / 0.18로 낮춰 상위 티어 승격을 쉽게 하고, 스티키 라우팅을 항상 적용합니다. 다운그레이드에 보수적입니다. | 고객 대면 챗봇 · 법률/의료 등 오답 비용이 큰 업무 |
max-savings | 임계값을 0.85 / 0.55로 올리고 항상 최저가 후보를 강제합니다 (anchor를 넘는 초고난도 쿼리만 예외). | 대량 배치 · 오프라인 파이프라인 · 태깅/분류 |
low-latency | 후보를 latencyClass fast 우선으로 재정렬하고, 캐시가 따뜻한(스티키) 프로바이더를 항상 우선합니다. 임계값은 기본과 동일합니다. | 실시간 UI · 자동완성 · 음성/스트리밍 프런트 |
목적 라우터 — 목적은 모델 이름으로
다이얼을 직접 고르는 대신, 목적 라우터 id를 모델 문자열로 지정할 수 있습니다. 코딩 워크로드에는 celon/code, 품질이 무조건 중요하면 celon/quality(항상 프론티어), 속도가 생명이면 celon/nitro(실측 처리량 랭킹), 비용이 최우선이면 celon/floor(실시간 최저가 랭킹) — 전부 가상 모델 id라 어떤 OpenAI SDK에서도 model 문자열 하나로 적용됩니다.
| 라우터 id | 용도 | 선택 방식 | 후보 구성 |
|---|---|---|---|
celon/code | 코딩 — 코딩 특화 — 어려운 코드는 프론티어로, 가벼운 코드는 코딩 강점 모델 체인으로 보냅니다. | tiered | T2: qwen/qwen3-235b → moonshot/kimi-k2.6 · T3: zhipu/glm-5.2 → deepseek/deepseek-v3.2 → meta-llama/llama-4-scout |
celon/quality | 최고 품질 — 항상 프론티어(Tier-1) 모델만 사용합니다. 난이도 분류 없음 — 프론티어 체인 + 폴백. | frontier | T1: anthropic/claude-fable-5 → openai/gpt-5.2 → anthropic/claude-opus-4.8 |
celon/nitro | 최고 속도 — 실측 처리량(tokens/sec)·지연 기준으로 가장 빠른 모델을 고릅니다. 난이도 티어 없음. | nitro | 텍스트 카탈로그 전체 (모달리티·컨텍스트·가용성 제약만) |
celon/floor | 최저가 — 실시간 가격 기준으로 가장 저렴한 모델을 고릅니다. 난이도 티어 없음. | floor | 텍스트 카탈로그 전체 (모달리티·컨텍스트·가용성 제약만) |
절감 목표 라우팅
celon.anchor(품질 상한)와 celon.savings_target(목표 절감률, 0–0.8 범위)을 함께 지정하면, 라우터가 목표 절감률에 수렴하도록 하향 라우팅 강도를 자동 보정합니다. 예: 0.4는 “항상 앵커만 썼을 때 대비 40% 절감”이 목표입니다.
{
"model": "celon/auto",
"messages": [{ "role": "user", "content": "이번 분기 지표를 요약해줘" }],
"celon": {
"anchor": "anthropic/claude-fable-5",
"savings_target": 0.4
}
}피드백 루프는 사용 원장(usage ledger) 기반입니다 — 키의 실제 과금 기록에서 실현 절감률(앵커 baseline 대비)을 집계해, 목표에 못 미치면 하향 라우팅을 더 공격적으로, 목표를 넘어서면 더 보수적으로 되돌립니다. 추정치가 아니라 원장에 남은 실현 값이 기준이므로 캐시 히트·폴백 비용까지 그대로 반영됩니다.
4단계 제약 인지 파이프라인
celon/auto의 라우팅 결정은 난이도 점수 하나가 아니라, 요청의 제약을 순서대로 반영하는 4단계 파이프라인으로 이뤄집니다. 각 단계의 판정은 응답 메타 pipeline 배열에 트레이스로 남습니다.
| 단계 | 이름 | 동작 |
|---|---|---|
| 1 | 모달리티 필터 | 이미지 입력·tool calling·JSON 스키마 등 요청이 요구하는 기능을 지원하지 않는 후보를 먼저 제거합니다 (modality:pass). |
| 2 | 컨텍스트 / 압축 | 프롬프트가 후보의 컨텍스트 윈도를 넘으면 제외하고, context_compression: true면 중간 부분을 잘라(lost-in-the-middle trim) 저렴한 모델에 맞춥니다 (context:fit). |
| 3 | 스티키 캐시 라우팅 | 같은 session_id의 대화는 프롬프트 캐시가 따뜻한 프로바이더를 우선합니다 — 캐시 재읽기 단가(예: Anthropic·DeepSeek 0.1×)가 낮을수록 가중치가 커집니다 (sticky:hit, 헤더 x-celon-sticky). |
| 4 | 난이도 + 앵커 폴백 | 남은 후보에 난이도 점수와 다이얼 임계값을 적용해 티어를 정합니다. anchor 모델이 지정되면 초고난도 쿼리도 앵커 이상으로는 올라가지 않습니다 (difficulty:0.41→tier2). |
3단계 티어
티어별 모델은 fallback 순서대로 나열됩니다 — 첫 모델이 실패하면 다음 모델로 자동 전환됩니다. 가격은 $/1M 토큰 (input / output) 기준입니다.
| 티어 | 성격 | 모델 (fallback 순서) | 가격 ($/1M in / out) |
|---|---|---|---|
| Tier 1 | 프론티어 — 고난도 추론·에이전트, confident-wrong 실패의 최종 방어선 | anthropic/claude-fable-5 → openai/gpt-5.2 | $10 / $50 · $1.75 / $14 |
| Tier 2 | 고성능 오픈웨이트 — 일반 업무·요약·RAG 응답 | meta-llama/llama-4-maverick → qwen/qwen3-235b | $0.15 / $0.60 · $0.09 / $0.60 |
| Tier 3 | 초고속·저비용 — 분류·추출·단순 Q&A·대량 배치 | deepseek/deepseek-v3.2 → zhipu/glm-5.2 → meta-llama/llama-4-scout | $0.27 / $0.40 · $0.85 / $2.68 · $0.08 / $0.30 |
동적 가격 추적
위 가격표는 스냅샷입니다. 실제 과금 단가는 LiteLLM·OpenRouter 가격 피드에서 주기적으로 동기화되며(기본 6시간), 변경 이력은 model_pricing 이력 테이블에 기록됩니다. 현재 단가는 GET /admin/pricing으로 조회하고, POST /admin/pricing/refresh로 즉시 재동기화하거나, PUT /admin/pricing/override로 특정 모델의 단가를 수동 고정할 수 있습니다.
명시적 모델 지정
카탈로그 id는 vendor/model 형식입니다 — 예: anthropic/claude-fable-5, openai/gpt-5.2, deepseek/deepseek-v3.2. 전체 목록은 GET /v1/models로 조회합니다. 모델을 명시하면 분류기를 거치지 않고 그대로 전달되며(classifier_score: null), 카탈로그에 없는 id는 404 model_not_found로 거부됩니다. 명시 모델 요청에서는 celon.tier 힌트가 무시됩니다.
요청별 celon 옵션
요청 본문의 celon 객체로 라우팅·캐시 동작을 요청 단위로 제어할 수 있습니다. 모든 필드는 선택 사항입니다.
{
"model": "celon/auto",
"messages": [{ "role": "user", "content": "핵심 API를 설계해줘" }],
"celon": {
"dial": "strict-quality",
"anchor": "anthropic/claude-fable-5",
"savings_target": 0.3,
"session_id": "conv_8f2a91",
"context_compression": true,
"no_cache": true,
"fallbacks": ["meta-llama/llama-4-maverick", "deepseek/deepseek-v3.2"]
}
}| 필드 | 타입 | 설명 |
|---|---|---|
dial | balanced | strict-quality | max-savings | low-latency | 이 요청의 인텐트 다이얼. 생략 시 키에 설정된 다이얼, 그다음 balanced. |
anchor | string | 앵커(상한) 모델 id — 초고난도 쿼리도 이 모델 이상으로는 폴백하지 않습니다. 키의 routing.anchorModel보다 우선합니다. |
savings_target | number (0–0.8) | 앵커 대비 목표 절감률 — 원장의 실현 절감률을 피드백 삼아 라우팅 강도를 자동 보정합니다. 절감 목표 라우팅 참조. |
session_id | string | 스티키 라우팅 세션 id — 같은 id의 대화는 프롬프트 캐시가 따뜻한 프로바이더로 고정됩니다 (x-celon-sticky 헤더로 확인). |
context_compression | boolean | 과도하게 긴 프롬프트의 중간을 잘라(lost-in-the-middle trim) 더 저렴한 모델의 컨텍스트 윈도에 맞춥니다. |
tier | 1 | 2 | 3 | celon/auto 전용 — 분류기를 건너뛰고 해당 티어를 강제합니다. |
no_cache | boolean | 이 요청의 캐시 조회·저장을 모두 비활성화합니다. |
no_pii_mask | boolean | 키에 PII 마스킹이 켜져 있어도 이 요청만 마스킹 없이 전달합니다. |
fallbacks | string[] | 명시 모델 요청 전용 — 지정한 모델 뒤에 이어 붙는 카탈로그 id 체인입니다. celon/auto에서는 티어 체인이 이미 fallback으로 동작합니다. |
shadow | boolean | 검증(섀도) 모드 — 응답은 앵커(없으면 기준 모델)가 그대로 서빙하고, 라우터가 골랐을 모델과 예상 비용은 응답 메타 celon.shadow(would_model · would_tier · would_cost_usd)와 x-celon-shadow 헤더에 기록만 합니다. 실제 트래픽으로 라우터를 무위험 검증할 때 쓰세요. 키의 routing.shadow보다 우선하며, 자동 라우팅에만 적용됩니다. |
Fallback 체인의 동작
- 재시도 조건 — 업스트림이
429또는5xx를 반환하거나 네트워크/타임아웃 오류가 나면 다음 후보로 자동 전환합니다. 그 외4xx는 즉시 실패합니다. - 전환 순서 — 같은 모델의 대체 프로바이더(
altProviders, 예: DeepInfra → Novita)를 먼저 시도한 뒤, 다음 후보 모델로 넘어갑니다. - 추적 — 시도한 경로는 응답 메타의
attempts배열과x-celon-attempts헤더에 기록됩니다. - 전부 실패 시 —
502 upstream_unavailable로 응답합니다. - 예산 다운그레이드 — 키 예산 초과 +
downgrade정책이면celon/auto요청이 Tier 3로 강제됩니다. 거버넌스 참조.
응답 메타데이터
모든 응답에는 라우팅 결과가 본문 celon 필드와 x-celon-* 헤더로 붙습니다.
{
"id": "chatcmpl-…",
"object": "chat.completion",
"model": "meta-llama/llama-4-maverick",
"choices": [ … ],
"usage": { "prompt_tokens": 21, "completion_tokens": 96, "total_tokens": 117 },
"celon": {
"model": "meta-llama/llama-4-maverick",
"provider": "deepinfra",
"tier": 2,
"classifier_score": 0.41,
"cache_hit": null,
"cost_usd": 0.000122,
"saved_usd": 0.003886,
"latency_ms": 842,
"pii_masked": 0,
"attempts": [],
"dial": "balanced",
"sticky": true,
"pipeline": ["modality:pass", "context:fit", "sticky:hit", "difficulty:0.41→tier2"],
"guardrails": { "mode": "mask", "findings": 0, "blocked": false }
}
}| 헤더 | 값 |
|---|---|
x-celon-model | 실제 서빙한 카탈로그 모델 id |
x-celon-tier | 라우팅된 티어 (0–3, 해당 시) |
x-celon-cache | exact | semantic | miss |
x-celon-cost-usd | 이 요청의 비용 (USD, 소수 6자리) |
x-celon-saved-usd | Tier 1 baseline 대비 절감액 (USD) |
x-celon-attempts | 실패한 시도 목록 (fallback 발생 시에만) |
x-celon-dial | 적용된 인텐트 다이얼 — balanced · strict-quality · max-savings · low-latency |
x-celon-sticky | 1 — 스티키 라우팅이 캐시-웜 프로바이더로 고정한 경우에만 |
x-celon-guardrail-findings | 가드레일 탐지 건수 (0이면 생략) — 티어드 가드레일 참조 |
스트리밍에서는 비용을 미리 알 수 없으므로 시작 시 x-celon-model · x-celon-tier · x-celon-dial · x-celon-sticky · x-celon-attempts만 헤더로 나가고, 스트림의 마지막 데이터 청크(choices: [])에 usage와 celon 메타 전체가 담긴 뒤 data: [DONE]이 옵니다.