v0.2.0 — /compare endpoint + React frontend + rate limiting
Demo layer release: a side-by-side comparison endpoint and a production React frontend that consumes it.
Live
| URL | |
|---|---|
| Frontend (Vercel) | https://agent-router-five.vercel.app |
| Backend (Cloud Run) | https://agent-router-909428365094.us-central1.run.app |
| Model release | https://github.com/raulmn00/agent-router/releases/tag/v0.1.0 |
Highlights
POST /compareendpoint — runs all three routers (DistilBERT, LLM zero-shot via gpt-4o-mini, embeddings + LogReg) on the same input and returns one row per router with measuredlatency_ms, derivedconfidence, computedcost_per_1k_usd, and either an intent or anerrorstring. Each router is isolated behind try/except — a single failure leaves the others' rows intact and the endpoint still returns 200.- React + TypeScript frontend (Vite, hand-written CSS, no UI library,
strict: true, noany). Two modes: Roteamento (single/routecall → IntentBadge + ConfidenceGauge + PathFlow + collapsible Trace; the Trace auto-expands when intent iscomplex_taskto show Planner → Executors → Critic) and Comparação (three columns revealing in the order of the measured latency). - Confidence everywhere —
LLMRouter.classify_with_confidencederives a[0, 1]score from the OpenAI logprobs of the first output token;EmbedRouter.classify_with_confidencereturnspredict_proba.max().OpenAIProvider.complete_with_logprobsis a new optional method on the provider abstraction. - Rate limiting via slowapi —
30 req/min/IPon/route,10 req/min/IPon/compare(it burns real tokens).429returns a friendly message; the frontend handles it gracefully. - Persisted embeddings LogReg —
python -m eval.fit_embed_routersaves the fitted classifier toeval/models/embed_router.joblib(~25 KB, committed). The backend loads it once at startup; cold-start no longer pays the training cost. ProviderUnavailableError— typed exception inagents/providers.pymapped to503by the backend with a generic message that never leaks the env var name.
Migration from v0.1.0
- New backend dependency:
slowapi==0.1.*(inbackend/requirements.txt). - Optional env var:
EMBED_ROUTER_PATH(defaults to<repo>/eval/models/embed_router.joblib). - The Dockerfile now copies
eval/into the image and adds it toPYTHONPATH. Cloud Run deploys must be re-built — the v0.1.0 image will start but/comparewould 500 withModuleNotFoundError: eval. /routeis behavior-compatible: same request, same response, same422/503/500error codes. The only addition is429on overuse.- Frontend is brand-new (
frontend/subdir of the monorepo). Deployed independently on Vercel;VITE_API_URLpoints at the Cloud Run backend.
Test counts
router/tests/ 11 schema, balance, stratified split, classifier softmax/argmax
agents/tests/ 15 orchestrator happy path + critic-reproves-and-retries
backend/tests/ 19 /route 4 dispatch paths + /compare cases + 422/429/503/500
eval/tests/ 17 accuracy, f1_macro, cost_per_1k pinning + sklearn cross-check
──
62
npm run build in frontend/ runs tsc -b first — type-check failures break the build.