Argus
Elevator pitch: Live debate → real-time claim–evidence graph.
Inspiration
Debates move fast. The logic underneath — what's a claim, what evidence was offered, what actually counters what — usually stays trapped in people's heads. Judges and audiences hear rhetoric; they don't see structure.
We wanted the opposite of another chatbot. We wanted a stage moment: two people talk, and a living map of the argument builds itself — with zero seat-clicks, zero speaker toggles, zero "paste the transcript later."
That meant treating Gemini as a structured reasoning engine, not a chat box: extract claims, attach speaker-provided evidence, link counters and responses, then score the graph of the debate — not declare who's "right."
What it does
Argus listens to a live, two-speaker debate in one browser and turns speech into a real-time claim–evidence graph.
- Speakers hit Open the floor and talk — no manual turn control.
- Audio is chunked via MediaRecorder and sent to Gemini for STT + speaker diarization (A / B).
- Transcript windows hit
/api/extract, which returns deltas:- Claims (graph nodes) —
argumentorcounterargument - Evidence (attached, never nodes) — statistics, citations, examples, etc.
- Relations —
countersorresponds_tobetween claims only
- Claims (graph nodes) —
- A force-directed graph animates claim nodes and relations live. Click a claim → inspector shows speaker, nature, attached evidence, sources, fallacies, and linked claims.
- Evidence is corroborated asynchronously via Gemini + Google Search (
/api/verify-evidence) — without blocking the live graph. - A deterministic debate score (
scoreA/scoreB) updates who is structurally ahead, plus an end-of-debate summary with stats and narrative.
Core ontology rule (the "Messi test"):
"Messi is better because he won a World Cup…" → one claim node + one attached evidence item — never two claim nodes glued by a fake "supports" edge.
Argus never labels claims true / false. Language stays structural: unsupported, pending confirmation, sources corroborate / contest.
How we built it
Stack
Next.js 16 (App Router) · React 19 · TypeScript · Tailwind v4 · MediaRecorder · @google/genai (Gemini 3 Flash) · Zod · react-force-graph-2d · Vitest · Vercel
Pipeline
Mic → /api/transcribe (STT + diarization)
→ /api/extract (claims + evidence + relations + soft fallacies)
→ async /api/verify-evidence (Google Search, two-pass)
→ /api/score (pure graph math) + /api/summary
→ live claim graph + momentum UI
Backend surfaces
| Endpoint | Role |
|---|---|
POST /api/transcribe |
Gemini audio STT + A/B diarization |
POST /api/extract |
Structured deltas; one-call extract + speaker + fallacy tags |
POST /api/verify-evidence |
Async two-pass Search corroboration (never on extract hot path) |
POST /api/score |
Deterministic who-is-ahead score — no API key |
POST /api/summary |
Stats + narrative + embedded debateScore |
Deterministic scoring (structure, not truth)
Winning means stronger argument structure + evidence quality signals, not claim truth.
For each claim (c) with attached evidence contribution (E(c)) and soft penalties (P(c)):
[ S_{\text{claim}}(c) = B(c) + E(c) + P(c) ]
Evidence unit before split across supported claims:
[ V(v) = w_{\text{ver}}(v) \cdot w_{\text{rel}}(v) \cdot 1.5 ]
Relation moves credit the speaker of from: counters (+2), responds_to (+1), plus rebuttal/undercut when attacking unsupported opponent claims. Raw speaker totals floor-shift into non-negative masses, then:
[ \mathrm{scoreA} + \mathrm{scoreB} = 100,\quad \mathrm{isDecisive} \iff \mathrm{leaderShare} \ge 0.62 ]
Full formula + worked proofs: docs/DEBATE_SCORING.md.
Frontend
Client session state holds claims / evidence / relations, merges extract deltas by id, serializes a verify queue (concurrency 1), and drives momentum from /api/score. Graph nodes are claims only; evidence lives in badges + Claim Inspector.
Challenges we ran into
1. Claim vs evidence separation. Naive extractors turn every fact into a node. Fixing the "Messi double-node" bug required a strict ontology, prompt rules, merge semantics, and FE acceptance tests so justifications never become graph nodes.
2. Automatic speakers with no toggle. Diarization + extract-time inference is harder than a spacebar seat switch — and overconfident wrong labels kill a demo. We hedge confidence in the UI and fall back to low-confidence heuristics on weak model signal.
3. Latency vs live feel. Mic chunks (~4s) + model time fight the "wow" cadence. We debounce extract (~3s / char threshold), return deltas only, and keep verify off the hot path so the graph never freezes waiting for Search.
4. Grounding + JSON schema. Google Search grounding and strict JSON on one call can silently drop sources. Verify uses a two-pass design: grounded prose first, then structured JSON against allowlisted sources only — corroborated requires ≥1 real source.
5. Scoring without becoming a fact-checker. Judges need a clear "who's ahead," but we refuse claim true/false labels. The score is pure graph math over nature, evidence verification/relevance, unsupported penalties, fallacies, and relation credits — testable and deterministic.
Accomplishments that we're proud of
- A full live vertical slice: talk → graph grows → inspector → async corroboration → who-is-ahead score.
- A clean claim–evidence–relation contract with FE handoff docs, fixtures, and backend tests.
- Two-pass Search verify that never blocks extraction, with honest statuses (
corroborated/contested/inconclusive/not_verifiable). - A deterministic scoring engine with documented invariants (
scoreA + scoreB === 100, evidence never scored as a claim, UNKNOWN speakers contribute 0). - Soft fallacy tags and confidence-aware speaker labels — warnings, not gotchas.
- A polished debate-floor UI where the lit moment is obvious: structure appears as people speak.
What we learned
- Structured extraction is a product problem, not just a prompt: ontology, IDs, merge rules, and UI must agree.
- Separating speaker support (did they offer evidence?) from external corroboration (do sources align?) keeps the demo honest.
- For live demos, hedging beats false certainty — especially on speaker labels.
- Async side paths (verify) are what let AI features feel instant.
- Deterministic math on top of model output makes "who's winning" explainable and demo-safe.
What's next for Argus
- Soft score influence from corroboration beyond provisional pending weights
- Live transcript sync (click claim → originating sentence)
- Replay mode: animate the full graph build from (t = 0)
- Steelman Mode: strongest version of the opposing argument
- Topic clustering / post-hoc speaker re-labeling
- Deploy hardening for shared demo keys and production smoke on the rehearsal script
Repo: github.com/skhdemo/Argus (develop)
Docs: PRD.md · DEBATE_SCORING.md · FRONTEND_HANDOFF.md
Built With
- gemini
- next.js
- node.js
- react
- tailwind
- typescript
Log in or sign up for Devpost to join the conversation.