Skip to main content

Yabanin — One-Command Demo

make demo takes a clean clone to a browser tab showing non-zero spend, a non-zero cache-hit rate, a classifier distribution, and a savings figure — in about 25 seconds, with no manual steps. It is a sales asset: it must run without reading any other documentation.

No time to run anything locally? The operator-managed public stand at https://yabanin.ai serves the same stack for evaluation — see Public stand. The rest of this page is about the one-command local demo.

The demo brings up the minimal stack (postgres, redis, migrations, the mock provider, the mock embedder, gateway, logger, admin, dashboard) and not the heavy parts (Prometheus, Grafana, Alertmanager, the ML classifier, the local LLM). The gateway routes to the in-stack mock provider and the embedder is the mock embedder, so there is no model download and no real provider credentials.

Prerequisites​

  • Docker with Docker Compose v2 (docker compose version)
  • make (bundled with Xcode Command Line Tools on macOS)
  • curl and shasum (both bundled on macOS; needed by the replay/seed steps)
  • ~2 GB of free Docker memory for the container set
  • A clean clone of the repo (the deploy/secrets/* files must be present; they are local dev secrets, not tracked by git)

No psql, Go toolchain, or Node is required on the host — the seed runs through the postgres container's own psql, and the service images are built by Docker.

Run it​

make demo

On success the command prints the URLs, the demo API key, and the admin login:

Demo is live.
Dashboard : http://localhost:3000
Admin : http://localhost:9091 (log in at /auth/login)
Gateway : http://localhost:8082 (POST /v1/chat/completions)
API key : demo-key-1234567890
Admin in : demo@local / demo-admin-123

Open http://localhost:3000, log in at /auth/login with demo@local / demo-admin-123, and the dashboard is populated.

With shadow mode (make demo SHADOW=1)​

Optionally mirror the whole demo traffic to a second model so the primary vs shadow comparison has real data. Shadow is off by default and leaves the client response untouched (see shadow-mode.md):

make demo SHADOW=1

What changes:

  • the gateway is started with YABANIN_SHADOW_ENABLED=true and mirrors every non-streaming demo request to gpt-4o on the same mock provider (sample rate 1.0 for the demo, 100 USD daily budget cap — it's a mock, no real spend);

  • after the replay, the script prints the shadow row count and a primary-vs-shadow average-cost-per-request line from request_logs (shadow rows carry ab_group='shadow' and the same request_id as the primary row);

  • the comparison endpoint then answers with a verdict instead of insufficient_data:

    curl -H "Authorization: Bearer $ADMIN_TOKEN" \
    "http://localhost:9091/api/analytics/shadow?days=1"

    # runtime kill switch (gateway admin listener, bearer-protected).
    # The gateway admin listener (container :9090) is published on host
    # :9092 — host :9090 is taken by Prometheus in this stack.
    curl -H "Authorization: Bearer demo-shadow-key" \
    http://localhost:9092/admin/shadow/status
    curl -X POST -H "Authorization: Bearer demo-shadow-key" \
    -d '{"enabled": false}' http://localhost:9092/admin/shadow/toggle

Shadow dashboard (optional, full stack)​

The minimal demo set does not include Prometheus/Grafana. To watch the yabanin_shadow_* metrics live, bring up the observability services too:

docker compose -f deploy/docker-compose.yml up -d prometheus grafana

Then open http://localhost:3001 (Grafana, admin / yabanin) and pick the Yabanin — Shadow Mode dashboard. It shows: shadow enabled state, spend rate (USD/s), budget burned (24h), budget-exhausted events (1h), requests by result, skips by reason, latency P95 by model, and spend by model.

Two Prometheus alerts accompany the dashboard (deploy/prometheus/alert-rules.yml, group yabanin-shadow):

  • ShadowHighErrorRate (warning) — >50% of shadow calls failing over 15m while shadow traffic flows; sustained errors mean the target is misconfigured or unreachable.
  • ShadowBudgetBurn (info) — the daily budget cap is blocking new shadow calls; tune YABANIN_SHADOW_DAILY_BUDGET_USD or the sample rate.

What gets generated​

  • 300 chat requests replayed through the gateway: a mix of easy/medium/hard prompts, a shared system prefix, and deliberate repeats so the semantic cache produces genuine hits rather than a flat zero.
  • A demo org + team + API key + admin user, plus a credit wallet and a team budget, so the gateway's credit guard and budget enforcer let the requests through.
  • Spend, cache, classifier, and savings data written to the database by the logger, which the dashboard reads.

Expected screen state, page by page​

After logging in, every page shows non-zero data:

  1. Overview — total requests (≈300), total spend (non-zero $), and the combined cache + routing savings figure. Point at the request count and the spend total.
  2. Cost — per-model spend breakdown: gpt-4o and gpt-4o-mini, each with a non-zero request count and cost. Point at the model rows and the dollar column.
  3. Cache — a non-zero cache-hit count (the repeated prompts hit the semantic cache) and the hit rate. Point at the hit count and the avoided-cost figure.
  4. Classifier — the easy / medium / hard distribution of the replayed prompts. Point at the class counts.

The savings API behind these pages is GET /api/analytics/savings?days=7; it returns total_requests, actual_cost_usd, cache_hits, and top_models_by_cost, all non-zero after the replay.

Reset​

To tear everything down, including the volumes (so the next make demo starts from a clean state):

make demo-down

To reset and re-run in one step:

make demo-down && make demo

Troubleshooting​

SymptomLikely causeFix
demo FAIL: <service> did not become ready ... within NsA service did not start, or a port is already in use.Check docker compose -f deploy/docker-compose.yml ps and the failing service's logs (... logs <service>). If a port (3000, 8082, 9091, 5432, 6379) is taken by another process, free it or make demo-down first.
Containers start but the gateway returns 502/unsupported protocol schemeThe gateway cannot reach the mock provider.Confirm the gateway has YABANIN_PROVIDER_ADDR: http://mock-openai:8081 (set in the compose file) and that mock-openai is healthy.
demo FAIL: migrations did not create org_credits within 120sA stale volume or a partially-run migration.make demo-down (removes volumes), then make demo again.
Dashboard is blank / unauthorizedNot logged in, or the admin session expired.Log in at /auth/login with demo@local / demo-admin-123. The demo re-seeds the admin user idempotently, so the credentials are stable.
Docker runs out of memory and containers OOMDocker's memory limit is too low for the container set.Raise Docker Desktop's memory allocation to ≥ 4 GB, then make demo-down && make demo.
Re-runs show stale or duplicate dataA previous run's volume was kept.Always make demo-down (it removes volumes) before make demo for a clean state.

Capturing a demo video​

Capture these, in this order, pointing at the named numbers:

  1. Terminal — make demo running, then the Demo is live block (show the URLs and the API key).
  2. Dashboard → Overview — the total request count and the total spend.
  3. Dashboard → Cost — the per-model rows (gpt-4o, gpt-4o-mini) and their costs.
  4. Dashboard → Cache — the cache-hit count and the avoided-cost figure.
  5. Dashboard → Classifier — the easy / medium / hard distribution.
  6. Terminal (optional) — yb audit against a request log to show the offline analyzer's combined savings figure (see docs/audit.md).

Do not commit binary screenshots to the repo; capture them to the video or an external asset store.