The work.
Four systems, and the constraint that shaped each one.
Rippli
Production
Financial Intelligence
A platform that maps how a single news event ripples across global markets — entity extraction,
relationship mapping, and sentiment over a live financial knowledge graph.
Live at app.rippli.ai.
-
Replaced local models with an LLM, without breaking the system.
Entity extraction and sentiment moved off self-hosted FinBERT and spaCy onto Claude Haiku.
I kept the original method signatures and dataclasses intact, so every downstream consumer
kept working through the migration.
-
Parallelised inference to hold a hard latency budget.
Serial per-article calls took ~22s — over the pipeline's 12s Phase 1 timeout.
Fanning the batch out across a thread pool brought it to ~7–8s and put the stage back inside budget.
-
RAG grounded in the production database, not a vector store bolt-on.
Before the model sees a query, a context service pulls company profiles, persisted relationships,
historical mention context, key executives, SEC financial metrics, and category assignments
out of PostgreSQL. The context budget is deliberate and measured: ~2–5KB per ticker,
~75KB for a 15-company query.
-
Progressive enhancement so users aren't waiting on the slow path.
A fast LLM pass returns a usable answer immediately; an AI-search enrichment pass upgrades
the result in place when it lands. The response carries its own analysis tier
(
fast / hybrid / enhanced) and confidence score.
-
Provider abstraction with a real degradation path.
Anthropic, OpenAI, and Gemini sit behind one search-provider interface, auto-selected from
environment. When no keys are configured, a no-op fallback provider returns empty results
gracefully — a misconfigured deploy degrades instead of crashing.
-
Knowledge graph built from unstructured news.
14,000+ companies, executives, and relationships in Neo4j, discovered from live articles via
NLP rather than hand-curated — plus LLM-classified signal duration
(
SHORT / MEDIUM / STRUCTURAL) so a one-day headline
isn't scored like a structural shift.
Claude
Gemini
Python 3.11
Flask 3
PostgreSQL 15
Neo4j 5.15
Redis 7
Celery
Next.js 16
Docker
Impact OS
Production
Admissions & Behavioural Scoring
The engine behind Cycle28's participant programmes. It decides who enters a 90-day programme
that carries real money — stipends, data support, mentorship — so the scoring has to be defensible,
not just clever. Primary KPI: verified income earned before day 90.
-
The problem: everyone now writes like a consultant.
Development programmes across the continent screen applicants on written English. Since generative
models became universal, that filter selects for access to a chatbot, not readiness. The same
profile of applicant kept qualifying, and the people the programme existed for kept missing out.
-
Score readiness, not polish.
Intake runs four diagnostic probes — action orientation, market awareness, rejection resilience,
and commitment signal — through scenario-based questions with no correct-sounding answer to copy.
Each probe scores 0–1 into a composite readiness score with risk flags and an
ADMIT / WAITLIST / REJECT recommendation.
-
The Skill Triad.
Capability is assessed across three dimensions — technical, commercial, and soft — because each
one alone produces a predictable failure: a specialist who can't earn, a hustler with nothing to
sell, or someone likeable with nothing to offer. Imbalance is surfaced explicitly, and
graduation requires a threshold on all three.
-
Hard limits on what the model may decide.
The AI classifies, tags failure types, personalises missions, and flags disengagement.
It is explicitly forbidden from motivating emotionally, overriding rules, making exceptions,
or deciding graduation — income is the only proof. The model is a referee, not a judge.
-
Degrades to rules, never to nothing.
With no API key configured the service logs a warning and falls back to deterministic
rule-based scoring. An intake cohort is never blocked because a provider is down.
Claude
NestJS
Prisma
PostgreSQL
Next.js
Rules engine
Krawl
Production
Inference & Extraction Infrastructure
The ingestion and extraction engine underneath Rippli — a resilient content pipeline that pulls
full-text articles and filings from primary sources, then runs LLM extraction over them at scale.
This is where the cost and quota engineering lives.
-
Self-hosted inference gateway.
I built a FastAPI service that fronts Ollama running on a GPU machine, adding API-key auth,
per-client rate limiting, request batching, and clean extract / summarize / classify endpoints.
Bulk extraction runs against hardware I control instead of metered API tokens.
-
Batch inference for a ~50% cost reduction.
I wrote a Gemini Batch Mode client directly against the REST API rather than pulling in
another SDK. Batch processing carries no per-minute rate limit, so a universe-scale extraction
can't 429 and deplete credits mid-run the way the synchronous lane did.
-
Failure is the default assumption.
The batch control plane is rate-limited, so uploads and batch creates retry with
exponential backoff on
429 / 500 / 503. Response parsing
digs defensively for state and output fields because their location shifts between API revisions.
-
Model fallback chains via litellm.
Extraction runs
gemini-2.5-flash as primary with flash-lite and Groq behind it.
Every call carries a hard timeout ceiling so a hung request can't stall the ingestion loop that awaits it.
-
Vision extraction where text parsing gives up.
A minority of congressional disclosure filings are image scans with no extractable text.
I render those pages to PNGs with pypdfium2 and ask a vision model for the trade rows —
returning the exact dict schema the text parser returns, so nothing downstream
can tell which path produced the data.
-
Quota governance across competing workloads.
Vision calls and knowledge-graph extraction draw on the same provider quota, so the vision path
is gated behind environment flags and per-cycle caps. Every function fails soft — a quota 429
or an unreadable scan logs and returns empty rather than breaking ingestion.
litellm
Gemini Batch API
Groq
Ollama
Vision / OCR
FastAPI
Playwright
PostgreSQL
Docker Compose
SEO Engine
Production
Multi-Tenant LLM Pipeline
A multi-workspace content pipeline where each workspace is a separate site with its own niche,
voice, sources, and article store — and content never crosses workspace boundaries.
-
The cheapest token is the one you never send.
Topic signals are collected from Reddit, Hacker News, and Google Trends, then filtered by
deterministic scoring — engagement plus each workspace's own positive and negative keyword
lists — before any LLM spend. The model only ever sees candidates worth paying for.
-
Quality gate with automated remediation.
A style firewall scans every generated draft for AI tells and sends failures back for LLM
edit retries. Drafts that still fail are held for human review instead of being published —
the pipeline degrades to a queue, never to bad output.
-
Provider-agnostic by construction.
Anthropic runs on its native SDK; OpenAI, Gemini, Ollama, and any OpenAI-compatible endpoint
run through the OpenAI SDK with a base URL override. Each workspace can pin its own provider
and model, or inherit the server default. Missing keys fail with an actionable message,
naming the workspace and the variable.
-
Multi-tenant isolation as a first-class concern.
Per-workspace tone of voice, voice rules, and banned phrases; API keys stored hashed and
rotatable; delivery webhooks signed with per-workspace HMAC-SHA256. A worker auto-schedules
runs for every active workspace on a 6-hour cycle.
Claude Haiku
OpenAI SDK
Ollama
Next.js
Prisma
PostgreSQL
Docker
Also shipping with LLMs
Dirra
AI-powered learning and mastery platform. Generative models drive content and assessment
over a Node service layer.
OfferAlert
Fixed-income opportunity discovery for Nigerian retail investors. FastAPI backend with
litellm-based document understanding over prospectuses and filings.
CPD Base
Continuing-education platform with an Anthropic-backed generation layer on Next.js and Prisma.