Work in progress: this page is under construction · noindex · access code required.
← Back to portfolio

Case study · in progress

CICERO — rhetoric analysis for political debate transcripts

A modular pipeline that reads a debate transcript, labels the rhetorical move behind each turn (question, deflection, attack, straw man, Gish gallop, whataboutism, tu quoque, loaded question — plus constructive markers), and links the statements into a typed, explorable graph.

TypeScript NLP / LLM Graph databases React / Cytoscape Pipeline architecture CI / Testing
CICERO — rhetoric analysis for political debate transcripts
Role
Concept by Jan Häusle · implementation solo by Ivo Häusle — architecture, NLP/LLM detectors, graph modelling, backend, React frontend, CI/deploy
Stack
TypeScript · Node/Fastify · Graph DB (Apache AGE) · React/Cytoscape · LLM
Timeline
Year
2026
Status
In progress (private preview, password-gated)

A modular pipeline that reads a political debate transcript, labels the rhetorical move behind each turn — question, deflection, attack, straw man, Gish gallop, whataboutism, tu quoque, loaded question, plus constructive markers — and links the statements into a typed, explorable graph.

The challenge

Built on an original concept by Jan Häusle; implemented by Ivo Häusle. The idea: political debates are full of moves — dodging a question, attacking the person, flooding with weak points (a "Gish gallop"), changing the subject — that a reader feels but rarely pins down. The challenge was to turn that intuition into something a machine can surface honestly: segment a raw transcript, name the rhetorical function of each turn without passing moral judgement, and connect who is responding to, contradicting or supporting whom — then make the whole structure explorable rather than a wall of text. Doing it credibly meant crossing several disciplines end to end: transcript ingestion that survives messy real-world data, NLP/LLM detectors that are precise rather than trigger-happy, a graph data model, and a frontend that makes the analysis legible.

The approach

  • A five-stage pipeline behind clean seams. Ingestion → segmentation → strategy detection → relationship analysis → export, as a TypeScript monorepo (shared / pipeline / web). External systems (graph DB, embedding model, LLM, HTTP framework) sit behind adapters, so swapping a vendor touches one adapter, not the core.
  • A plugin architecture for detectors. New rhetorical detectors are added through a single StrategyPlugin interface without touching the core. The question detector is rule-based; the rest run on an open-weight, Ollama-compatible LLM with confidence scores and context rules — deliberately tuned for precision (guards against false positives) rather than eager labelling.
  • A growing, sourced label set. Beyond the first five strategies (question, deflection, attack, straw man, Gish gallop) the detector set now covers whataboutism, tu quoque, and loaded-question / biased framing — plus the first constructive markers (evidence reference, concession, acknowledgement), so the analysis is not purely about bad-faith moves.
  • A typed relationship graph. Statements are linked with content verification and typed edges (responds-to, contradicts, supports, topic-shift) and persisted in a graph store; embedding-based topic-shift detection (BGE-M3) drives segmentation and relationship reassignment.
  • An explorer, not a report. A React + Cytoscape GUI renders the annotated debate as an interactive graph with a colour legend, a sourced theory-&-method glossary, in-app speaker and example management, and force-directed de-tangling of dense graphs.
  • Legally clean data by design. The demo corpus is built from public-domain German Bundestag plenary records (§ 5 UrhG) plus one US presidential debate — chosen so the shipped product carries no rights baggage, with sources named and only analysed excerpts committed.
  • Real test and CI discipline. CI runs typecheck, unit tests, integration tests against a real graph database, and a license gate (permissive-only, findings recorded in ADRs); the pipeline has been run end-to-end against a live local LLM, not just statically checked.

The result

  • A working end-to-end system: a debate goes in, an annotated typed graph comes out, rendered as an interactive Cytoscape view in the browser — all detectors firing against a live open-weight LLM.
  • Deployed and review-gated. The frontend is live at a private URL behind HTTP Basic Auth; the Fastify backend runs on a dedicated machine and is reachable over a Tailscale funnel, with a single end-to-end login chain (browser → Vercel edge → backend) verified.
  • Substantial, honest engineering documentation: a PRD (~35 user stories), 16+ ADRs recording the decisions and their rejected alternatives, and a documented set of real-world input limitations (diarisation noise, missing speaker labels) that the ingestion handles as warnings-as-data rather than crashes.
  • A truthful "today vs. roadmap" split: shipped today is the core pipeline, the detector set and the explorer; on the roadmap are a gold-annotated accuracy corpus, further GUI views (quality axis, convergence view), debate comparison, and English as a fully second language.

What this demonstrates

  • Interdisciplinary breadth owned end to end: applied NLP/LLM (precision-tuned detectors, prompt engineering), graph data modelling, a clean pipeline architecture, a React/Cytoscape frontend, and CI/deployment.
  • Comfort with genuinely hard, fuzzy problems — labelling rhetorical function without moralising, surviving messy real-world transcripts — not just CRUD.
  • Architecture-first, decision-driven work: adapters and plugin seams, configuration over hard-wiring, and an ADR trail that shows why, not just what.
  • Legal and licensing care suited to a commercial product: public-domain source data, a permissive-only dependency gate, sources named.
  • Modern, AI-assisted delivery, steered and curated by a human — turning someone else's sharp idea into a polished, documented, deployed product.

Tech at a glance

TypeScript · Node / Fastify · Apache AGE (graph DB) · Embedded graph store · LLM (Ollama-compatible, open-weight) · BGE-M3 embeddings · React · Cytoscape · Vite · Docker · CI (GitHub Actions) · Tailscale funnel