Retail-loyalty churn detection + retention-offer cinematic demo on SynapCores AIDB.
50,000 loyalty members in a single table. Train a churn model with one SQL statement. Score every member with another. Stream personalized retention offers to the ten most at-risk. Sixty seconds. One database.
Watch first: docs/demo/churngraph-2026-05-24.mp4 — 64 s, 1440x900.
This is the flagship ML-headlining demo in the SynapCores demo family:
ML is the protagonist, not the sidekick. AIDB's CREATE EXPERIMENT
trains a real binary-classification model on a calibrated cohort
(sub-second); SELECT AUTOML.PREDICT(…) then scores all 50,000
members and returns real probabilities for ranking; SELECT GENERATE(...) calls the database's built-in LLM to write a
personalized retention offer for each of the top-10 at-risk Gold
members.
churnGraph/
├── bff/ port 4006
│ └── src/
│ ├── sdk.ts — minimal gateway client (login + execSql + createExperiment)
│ ├── env.ts — loads .env via process.loadEnvFile
│ ├── index.ts — Fastify server, /api/demo serves the snapshot
│ ├── bootstrap/
│ │ ├── schema.sql — loyalty_members + loyalty_members_sample DDL
│ │ ├── seed.ts — deterministic 50K-member generator (Mulberry32, seed=42) + stratified sample
│ │ ├── train.ts — wraps CREATE EXPERIMENT on the sample, parses best_score
│ │ ├── calibrate.ts — top-10 at-risk Gold + per-member offer
│ │ ├── verify.ts — post-bootstrap sanity check
│ │ └── run.ts — orchestrator: seed → train → calibrate → verify → snapshot
│ └── demo/snapshot.{ts,json}
├── frontend/ port 5180
│ └── src/presentation/
│ ├── App.tsx — orchestrator, scene switcher
│ ├── acts.ts — 5-act timeline (0-8, 8-22, 22-36, 36-54, 54-60 s)
│ ├── store.ts — zustand cinema state
│ ├── useTimeline.ts — rAF clock
│ ├── theme.ts — loyalty-tier palette (gold / silver / bronze / platinum)
│ └── components/
│ ├── KickoffCard.tsx
│ ├── TopBar.tsx
│ ├── CaptionStrip.tsx
│ ├── LedgerScene.tsx — Act 1: 50K-cell density grid
│ ├── TrainScene.tsx — Act 2: CREATE EXPERIMENT typewriter + real best_score
│ ├── PredictScene.tsx — Act 3: SELECT AUTOML.PREDICT + top-10 constellation
│ ├── SaveScene.tsx — Act 4: per-member retention offers, typewriter stream
│ └── CloseCard.tsx — Act 5: chips + URL
├── scripts/
│ ├── record-demo.ts — Playwright → docs/demo/churngraph-<date>.mp4
│ └── screenshot-probe.ts — visual smoke (no recording)
├── docs/
│ ├── STORYBOARD.md
│ └── demo/churngraph-<date>.mp4
├── package.json (npm workspaces: bff, frontend)
├── tsconfig.base.json
├── .env, .env.example
└── README.md
- Node 20+
- A running SynapCores AIDB gateway (the demo doesn't own one) with
AutoML (
CREATE EXPERIMENT/AUTOML.PREDICT) and a built-in LLM (GENERATE). Point.envat it: copy.env.exampleand setAIDB_PORT+AIDB_ADMIN_PASS(first-boot admin credentials are printed in the gateway/container logs). The default ishttp://127.0.0.1:8080.
cd churnGraph
npm install
cp .env.example .env # edit if your gateway lives elsewhere
# 1. Populate the snapshot — seeds 50K rows + a stratified sample,
# trains the model (sub-second), pre-computes the at-risk list +
# real LLM offers. Takes ~30-60 s end-to-end (LLM offers dominate).
npm run bootstrap
# 2. Start BFF (:4006) + frontend (:5180) together.
npm run dev
# 3. Browse to http://localhost:5180 and hit Engage.# After `npm run dev` is up:
npm run demo:record
# → docs/demo/churngraph-<date>.mp4The recorder drives headless Chromium through the same 60-second timeline a human viewer would see, then transcodes the .webm to h264 mp4 via ffmpeg.
- The SQL on screen IS the SQL we run. Both Act 2's CREATE EXPERIMENT and Act 3's SELECT AUTOML.PREDICT statements are sourced from the bootstrap snapshot, which the BFF wrote at the moment it ran them against the gateway.
- Bootstrap is idempotent. Re-running
npm run bootstrapDROPs both tables, re-seeds at the same seed (42), rebuilds the stratified sample, retrains the model, and rewrites the snapshot — entity counts and top-10 ids reproduce. - The demo never owns the gateway. It connects to whatever AIDB
instance
.envpoints at. Don't run two demo bootstraps against the same gateway concurrently — the schema DDL conflicts.
See docs/STORYBOARD.md for the act-by-act narrative.