llm-routing
LLM 라우팅: 측정된 벤치마크, 그리고 그것이 주장하는 라우터
비용 인지형 LLM 라우팅 서비스(LangGraph + MCP)와, 그 정책을 결정하는 417개 작업 벤치마크.
정답을 검증할 수 있는 가장 저렴한 모델로 답하고, 검증이 실패할 때만 상위 모델로 에스컬레이션합니다. 이것이 단순히 최고 모델에 비용을 지불하는 것보다 나은지 여부는 의견의 문제가 아닙니다. 선택하는 모델에 달려 있으며, 이 저장소는 세 가지 실제 가격 사다리에서 이를 측정합니다.
한 문장으로 요약한 결론: 최상위 단계가 진정으로 더 우수하고 검증 비용이 저렴할 때 캐스케이드하라 — 어떤 가격 비율 임계값도 세 사다리 모두에 맞지 않는다. 배포된 라우터는 커밋된 측정값에서 사다리별로 이 판정을 계산하며, 데이터가 없는 사다리에 대해서는 응답을 거부합니다.
실행되는 것 | LangGraph 상태 머신 — |
정책을 결정하는 것 | 417개 작업(MBPP+ 코드, MATH-500 레벨 5), 9개 정책, 3개 가격 사다리, 모두 실제 모델에서 측정: 비용-정확도 프런티어, 정확한 McNemar, paired bootstrap. |
구축 도구 | Python 3.10–3.13 · LangGraph · MCP · Anthropic + DeepSeek API · pytest (268개 테스트) · GitHub Actions. 연구 핵심은 순수 표준 라이브러리 — 어떤 의존성도 벤치마크 숫자를 바꿀 수 없습니다. |
증거 | 5,075개의 실제 모델 응답, 커밋됨. $8.51 지출. 모든 그림과 표는 API 키 없이 오프라인에서 $0.00으로 재생성됩니다. |
빠른 시작
pip install -e ".[agent]"
python -m llm_routing.build_taskset
python -m router_agent.cli --demo # real model output, no API key, $0.00계정도, 키도, 돈도 필요 없습니다. 응답은 한 번 구매되어 커밋되었으므로, 라우터는 시뮬레이션 대신 실제 모델 출력을 재생합니다.
python scripts/demo.py는 세 가지 표준 트레이스를 출력합니다 — 저렴한 단계에서 승리하는 캐스케이드, 두 번 지불하는 캐스케이드, 그리고 검증이 정확하고 무료인 코드 사례. 그중 첫 번째:
1. The cascade's win - verified at the cheap rung
--------------------------------------------------------------------------
query: Let f(x) = x^3 - 3x + 1. Find the sum of the squares of all real roots. [...]
classify domain=math, start=cheap, verifier=self_consistency
answer cheap (deepseek-v4-flash) answered
verify self_consistency -> ACCEPT, confidence=1.00
finalize done: verified
answered by deepseek-v4-flash
verified True (self_consistency)
cost $0.000315 backend $0.000000이 네 줄은 아래 그래프를 한 바퀴 도는 것입니다. 그래프는 그려진 것이 아니라 router_agent/graph.py에서 파싱됩니다 — 에스컬레이션 엣지는 answer로 다시 루프백하며, 이 루프가 라우터가 아닌 캐스케이드가 되게 만드는 핵심입니다.
DeepSeek에서 세 번의 독립적 추출이 모두 올바른 답을 주었으므로, 캐스케이드는 수락하고 Opus 5를 호출하지 않았습니다 — 최상위 단계로 직접 라우팅하는 것보다 약 27배 저렴합니다. 검증이 실패하면 캐스케이드는 에스컬레이션하고 두 단계 모두에 비용을 지불합니다. 이 트레이드가 가치 있는지 여부가 이 저장소의 나머지가 측정하는 내용입니다.
결론
항상 최고 모델에 비용을 지불하는 것과의 사전 등록 비교. paired 결과에 대한 정확한 McNemar, 사다리당 보류된 209개 작업, n=209.
사다리 | 단계 | 캐스케이드 | 항상-비쌈 | Δ 정확도 | p | Δ 비용/작업 |
| v4-flash → Opus 5 | 95.7% | 92.3% | +3.3% | 0.039 | −$0.00307 |
| Haiku 4.5 → Sonnet 5 → Opus 5 | 96.7% | 92.3% | +4.3% | 0.012 | +$0.00097 |
| v4-flash → v4-pro | 86.6% | 83.7% | +2.9% | 0.070 | −$0.00000 |
wide 사다리에서 캐스케이드는 더 정확하고 동시에 4배 저렴합니다. claude 사다리에서는 정확도를 프리미엄으로 구매합니다 — 저렴한 단계가 Haiku이고 수학 절반이 그 단계에서 다섯 개 샘플을 추출할 때 검증은 무료가 아닙니다. 사다리가 부호를 결정하므로, 아래 라우터는 가정하지 않고 사다리를 읽습니다.
세 가지 추가 결과, 각각의 숫자와 주의사항은 docs/RESULTS.md에 있습니다:
예측 라우팅은 동전 던지기를 이기지 못합니다 — 여섯 비교 중 여섯. LLM-as-router도 RouteLLM의 사전 훈련된 BERT도 어떤 사다리에서도 비용 일치 무작위 귀무가설을 이기지 못하는 반면, 캐스케이드는 모든 사다리에서 둘 다 이깁니다. 차이는 결정이 언제 이루어지는가입니다: 예측 라우터는 시도를 보기 전에 결정하고, 캐스케이드는 시도를 검증한 후 결정합니다. → 여섯 비교와 그 뒤의 프런티어 AUC
정확도는 라우터가 실제로 무엇을 했는지 숨깁니다. 두 정책이 올바른 열 개 작업을 에스컬레이션하거나 모든 것을 에스컬레이션하여 동일한 정확도에 도달할 수 있습니다.
always_expensive는 27개의 구조를 사기 위해 201개 작업을 에스컬레이션하여 답을 개선할 수 없는 에스컬레이션에 $0.71을 태우는 반면,cascade는 그 구조 중 24개를 얻고 $0.084를 낭비합니다. → 정책별 성과표모든 정책은 점이 아니라 곡선입니다. 여기 각 라우터에는 정확도와 비용을 맞바꾸는 손잡이가 있으므로, 각각 한 설정에서 두 개를 비교하면 손잡이를 설정한 사람이 승자를 고를 수 있습니다.
frontier.py는 각 손잡이를 전체 범위에 걸쳐 스윕하고 결과 곡선을 비교합니다. → 프런티어와 가격 비율이 캐스케이드 여부를 결정하지 않는 이유
각각에는 figures/에 그림이 있으며, 각 차트가 주장하는 내용과 runs/의 어떤 아티팩트에서 그려졌는지 나열합니다.
벤치마크는 자체 결론을 제공합니다
테이블로 끝나는 벤치마크는 독자가 적용하도록 남겨둡니다. 이 벤치마크는 함수로 끝납니다. findings.ratio_verdict(ladder)는 해당 사다리의 커밋된 프런티어를 읽고 그에 대한 판정을 반환합니다. 동일한 쿼리, 두 사다리, 반대 답:
$ llm-router --estimate "prove that sqrt(2) is irrational" --ladder wide
recommended policy cascade (measured on the wide ladder)
cascade vs always-best, at matched accuracy -83.1%
$ llm-router --estimate "prove that sqrt(2) is irrational" --ladder claude
recommended policy route (measured on the claude ladder)
cascade vs always-best, at matched accuracy +11.7%이 뒤집힘이 결론이며, 라우터는 가정하지 않고 읽습니다 — 그리고 데이터가 없는 사다리에 대해서는 거부합니다. CLI, MCP explain_routing 도구 및 RouterConfig 기본값은 모두 동일한 함수를 호출하므로, 벤치마크가 측정한 것을 변경하면 라우터가 권장하는 것도 변경됩니다. 날짜가 지나면 어긋나는 상수는 없습니다 — 이전에는 하나가 있었고, 그 세 가지 판정 중 두 개가 거꾸로였습니다.
레이아웃
llm_routing/ the experiment — 16 modules, standard library only
router_agent/ the product — LangGraph cascade + MCP server
cache/ 5,075 real model responses — what makes replay free
runs/ every derived artefact: results, frontiers, scorecards
data/ docs/ figures/ scripts/ tests/ archive/두 절반은 하나의 모델 클라이언트, 하나의 가격 테이블 및 하나의 응답 캐시를 공유하므로, 라우터의 달러 수치가 테이블의 달러 수치와 동일한 의미를 갖습니다. 화살표는 한 방향으로만 흐릅니다 — router_agent는 llm_routing을 가져오고, 그 반대는 없습니다 — CI에는 이를 유지하는 것만을 목적으로 하는 작업이 있습니다. 모듈별로: docs/ARCHITECTURE.md.
MCP 클라이언트에서 사용하기
라우터는 MCP 서버입니다: 다섯 개 도구(route_query, resume_routing, estimate_cost, compare_policies, explain_routing), routing:// 아래의 네 개 읽기 전용 리소스, 그리고 클라이언트가 정책을 선택하도록 안내하는 하나의 프롬프트. .mcp.json이 커밋되어 있으므로, Claude Code는 pip install -e ".[agent,mcp]"만으로 서버를 인식합니다. Claude Desktop이나 다른 클라이언트의 경우, 동일한 블록을 수동으로 등록합니다:
{
"mcpServers": {
"llm-routing": {
"command": "python",
"args": ["-m", "router_agent.mcp_server"],
"env": {"ROUTER_LADDER": "wide", "ROUTER_MODE": "replay",
"ROUTER_K": "3", "ROUTER_AGREEMENT": "1.0"}
}
}
}ROUTER_MODE=replay는 안전한 등록입니다: 서버는 커밋된 응답에서 답하며 돈을 쓸 수 없습니다, 대신 실제로 지불된 프롬프트만 제공합니다 — 그 외의 것은 조작된 답 대신 구조화된 no_cached_response로 반환됩니다. ROUTER_K=3은 해당 응답이 구매된 매개변수와 일치하도록 고정되어 있습니다. 기본값 5는 아무도 구매하지 않은 샘플을 캐시에 요청하게 됩니다. ROUTER_MODE=real과 키는 임의의 쿼리를 제공하고 청구합니다.
에스컬레이션 승인
기본적으로 설정되지 않음. ROUTER_APPROVAL_USD를 추가하면, 그보다 비싸게 예상되는 에스컬레이션은 지출 대신 그래프를 일시 중단합니다: route_query는 stop_reason: awaiting_approval과 thread_id 및 모델과 가격을 명명하는 interrupted 페이로드를 반환하고, resume_routing은 사람의 답을 다시 전달합니다.
"env": {"ROUTER_LADDER": "wide", "ROUTER_MODE": "replay",
"ROUTER_K": "3", "ROUTER_AGREEMENT": "1.0",
"ROUTER_APPROVAL_USD": "0.001"}승인은 에스컬레이션별입니다 — escalate 노드는 통과할 때 이를 지웁니다 — 따라서 세 단계 사다리는 두 번 요청하며, 클라이언트는 stop_reason이 다른 것이 될 때까지 재개해야 합니다. 체크포인트는 서버 프로세스에 있는 InMemorySaver이므로, 두 호출 모두 동일한 실행 중인 서버에 도달해야 합니다: 호출마다 하나를 생성하는 클라이언트(scripts/mcp_call.py 포함)는 이전 것이 일시 중단한 것을 재개할 수 없습니다. 더 이상 존재하지 않는 thread_id는 LangGraph 내부의 KeyError 대신 no_suspended_run으로 반환됩니다.
전체 표면을 한 번에 보기
python scripts/demo_mcp.py실제 stdio 클라이언트 세션을 통한 서버의 스크립트화된 연습 — 광고하는 것과 자체 호출 중 어떤 것이 지출하는지, 리소스, 사다리 뒤집기, 무료 프로젝션, 라우팅된 답, 그리고 양방향으로 답하는 승인 루프. 키도 지출도 없음; 쿼리가 프로덕션에서 얼마였을지와 실제로 계정에서 나간 금액을 인쇄하며 끝납니다.
두 서버를 시작하며, 그 이유가 ROUTER_K의 핵심입니다: self-consistency 샘플은 샘플 인덱스별로 캐시되므로, k는 응답이 구매된 조건으로 시작 시 고정됩니다 — 저렴한 단계에서 검증하는 쿼리는 k=3, 네 번째 추출이 불일치하여 에스컬레이션을 유발하는 쿼리는 k=4. demo.py는 라우터가 무엇을 하는지 보여줍니다; 이것은 서버가 무엇을 하는지 보여줍니다.
터미널에서 구동하기
scripts/mcp_call.py는 일회성 MCP 클라이언트입니다 — 서버를 시작하고, 핸드셰이크를 수행하고, 하나의 도구를 호출하고 결과를 인쇄합니다:
python scripts/mcp_call.py --listpython scripts/mcp_call.py explain_routing ladder=widepython scripts/mcp_call.py --resource routing://findings/probeJSON-RPC를 수동으로 파이프하는 것은 작동하지 않으며, 실패는 조용합니다: 서버는 stdin EOF를 종료로 간주하고 큐를 비우지 않고 종료하므로, echo '...' | python -m router_agent.mcp_server는 initialize 응답을 인쇄하고, 도구 호출을 버리고 0으로 종료합니다. 클라이언트는 파이프를 열어 둡니다.
실제 돈을 쓰려면 모드를 지정하세요 — 이것은 MCP를 통해 라우팅되고 가격이 매겨진 실제 DeepSeek 호출입니다:
ROUTER_MODE=real ROUTER_LADDER=deepseek ROUTER_K=3 ROUTER_AGREEMENT=1.0 python scripts/mcp_call.py route_query query="What is 17 * 23? Give the final answer in \boxed{}." domain=math answered by deepseek-v4-flash (cheap)
verified True via self_consistency
cost $0.000068 backend $0.000068
classify domain=math, start=cheap, verifier=self_consistency
answer cheap (deepseek-v4-flash) answered
verify self_consistency -> ACCEPT, confidence=1.00세 개의 HTTP 호출 — 하나의 탐욕적 답과 자신에 대한 두 번의 추가 확인 — 저렴한 단계에서 만장일치로 수락되어 v4-pro는 건드리지 않았습니다. 두 번째 실행하면 backend_cost_usd는 $0.00이고 cost_usd는 동일합니다: 응답은 나가는 길에 캐시되었으며, 이는 벤치마크가 5,075개를 무료로 재생할 수 있게 하는 동일한 메커니즘입니다. 두 수치는 의도적으로 분리되어 있습니다 — 하나는 프로덕션에서 서빙 비용이고, 다른 하나는 계정에서 나간 금액입니다.
서빙된 쿼리가 구매하는 것은 cache/serving.<ladder>.jsonl에 저장되며, 벤치마크의 cache/raw_calls.<ladder>.jsonl에는 저장되지 않습니다. 둘 다 실제 유료 응답을 보유하지만, 증거는 하나뿐입니다: 벤치마크 파일은 모든 게시된 표가 계산되는 폐쇄 집합이며, 임의의 쿼리가 여기에 추가되면 아래에 인용된 응답 수와 총 지출이 변경됩니다. 서빙은 여전히 벤치마크 캐시를 읽으며, 이것이 --demo를 무료로 만드는 이유입니다.
검증하기
python scripts/check_mcp_server.py두 단계로 구성되며, 두 번째 단계가 핵심입니다. 이 단계는 도구를 프로세스 내에서 나열하고 호출한 다음, 서버를 하위 프로세스로 실행하고 JSON-RPC로 직접 통신합니다. stdio에서는 stdout이 프로토콜이기 때문입니다. 도구 아래에서 발생한 단 한 번의 잘못된 print는 프레임을 손상시키는 반면, 모든 프로세스 내 테스트는 여전히 통과합니다. 이는 가상의 이야기가 아닙니다. response_cache는 route_query만 도달하는 코드 경로에서 stdout으로 오래된 키에 대해 경고했고, 그 결과 서버는 도구를 완벽하게 나열한 후 첫 번째 실제 호출에 대해 손상된 답변을 반환했습니다.
모든 것 재현하기
재생 모드는 커밋된 응답을 대상으로 게시된 분석을 다시 실행합니다. 키도, 네트워크도, 비용도 없습니다. $0.00:
ROUTER_MODE=replay python scripts/run_all_ladders.py --ladders wide # ~30 min세 가지 모두에서 --ladders wide를 빼면 약 75분이 걸립니다. 게시된 수치는 모든 파생 산출물을 삭제한 후 정확히 그 방식으로 생성되었습니다. 백엔드에 도달한 호출은 0건, 시뮬레이션된 행은 0개, 재생성된 모든 파일은 커밋된 파일과 바이트 단위로 동일하게 돌아왔습니다.
재생은 아무것도 설치할 필요가 없습니다. 순수 표준 라이브러리만 사용하고, 오프라인이며, 수치까지 바이트 결정적입니다. 그리고 이것이 기본값이므로 위 명령 중 어떤 것도 모드를 지정하지 않습니다. 실제 모드는 키가 필요하고 비용이 발생합니다. 세 번째 모드인 mock은 테스트 스위트용 응답을 생성하지만 모든 분석 모듈은 이 모드에서 실행을 거부합니다. 세 가지 모드 모두, 모든 분석 진입점, 데이터 구매 순서는 docs/METHOD.md에 있습니다.
문서
파일 | 읽어야 할 때 |
라우팅에 대한 사전 지식 없이도 이해할 수 있는 평이한 버전을 원할 때 — 여기서 시작하세요 | |
모든 발견 사항과 수치, 그리고 그 비용을 원할 때 | |
방법론을 원할 때: 작업 세트, 이러한 데이터셋을 선택한 이유, 래더, 정책, 검증기, 성능 저하 실험, 실제 실행 방법, 그리고 이 프로젝트가 스스로 발견한 버그 | |
벤치마크와 서빙 계층이 모듈별로 어떻게 맞물리는지 알고 싶을 때 | |
주장의 범위를 제한하는 요소를 원할 때 |
주장의 범위를 제한하는 요소와 여기서 새로운 점
뒤에 숨기지 않고 첫 페이지에 명시했습니다: 신호를 생성하는 검증기는 배포되는 검증기가 아닙니다. 코드 부분은 MBPP+가 제공하는 테스트를 실행하여 평가되지만, 배포된 라우터에는 그 테스트가 없습니다.
이 격차는 언급만 되는 것이 아니라 가격이 매겨지며, 이 저장소가 문헌에 추가하는 것은 바로 이 가격 책정입니다. FrugalGPT (2305.05176)는 캐스케이드 기준선이며, 이와 AutoMix는 검증기를 주어진 것으로 간주합니다. Dekoninck 외 (2410.10347)는 품질 추정기 정확도가 이 모든 것이 작동하는지를 결정하는 요소임을 식별하지만, 합성 노이즈를 주입하여 테스트합니다. 여기서 sweep_degraded.py는 대신 객관적으로 평가되는 작업에서 실제 검증기를 통제된 양만큼 성능 저하시키며, 도메인, 모델, 프롬프트, 채점자를 고정합니다. 따라서 프록시 검증기를 배포하는 것은 미지의 영역으로 나아가는 것이 아니라 측정된 곡선을 따라 이동하는 것입니다.
다른 모든 제한 사항은 docs/LIMITATIONS.md에 해결 방법과 함께 한 번 명시되어 있으며, 전체 참고 문헌은 docs/METHOD.md에 있습니다.
라이선스
MIT — LICENSE 참조.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Hosted MCP server for LLM cost estimation, model comparison, and budget-aware routing.
Agent Cost Allocator MCP — multi-tenant LLM cost attribution for chargeback billing. Companion to
AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/APantov/llm-routing-comparison'
If you have feedback or need assistance with the MCP directory API, please join our Discord server