← All work

UK AI Talent Pipeline Visualiser

An interactive metro-map simulation of the UK's AI talent pipeline, showing how education, labour-market and immigration levers shift the national AI talent pool.

Status
prototype
Period
TODO (James) — confirm start date
Role
Sole developer
Placeholder hero image for the UK AI Talent Pipeline Visualiser — TODO: replace with a real screenshot of the metro-map view or the Interventions comparison dashboard

What it does

The tool models the UK’s AI talent pipeline end to end — from school through further and higher education into the AI labour market, plus international arrivals and departures — and renders the whole thing as a single interactive map, styled like a metro/Tube diagram rather than a conventional flow chart. Twenty-one policy variables, grouped by education, research, visas, labour market and infrastructure, can be moved on sliders to see the national AI talent pool respond immediately: which pipelines grow, which shrink, and where the flow gets displaced rather than added to. A second mode applies twenty curated real-world interventions (drawn from DSIT’s own AI talent intervention library) as one-click scenario presets, with a before/after diff highlighted directly on the map, and a comparison dashboard ranking all twenty by cost-effectiveness against whichever headline statistic matters most.

How it works

A pure, deterministic simulation engine (simulate()) runs a topological forward pass over a config-driven graph of pipeline nodes and edges — no backend, no database, safe to run in a Web Worker. A separate layout engine turns the simulation’s output into pixel coordinates: a D3 grid layout for node position, octilinear routing (straight lines and 45° diagonals only, like a Tube map) for the flows between them, and D3’s pie/arc generators for the sector-composition rings drawn on top of labour-market nodes. Every UI value — slider positions, flow widths, summary statistics — animates through a single shared requestAnimationFrame loop rather than one animation per component, and every value the app renders traces back to one central Config object rather than anything hard-coded in a component.

The interesting problem

The engine’s headline number — the total AI-relevant talent pool — was wrong for most of the build, and not in an obvious way. The bug: relevanceFraction (the share of a stage’s population that’s AI-relevant) was being applied at every node in the chain, so it compounded downward through the education pipeline until the domestic route collapsed to a handful of people by A-Level, and the pool ended up driven almost entirely by exogenous immigration — moving an education policy lever barely moved the total at all, which is exactly backwards for a tool meant to show education policy mattering. The fix was to change what actually propagates through the graph: flows now carry the full head-count stock end to end, and ai_stock = stock × relevanceFraction is computed only once, at the point of measurement, rather than being baked into the flow itself. Roughly twenty postgraduate and labour-market-entry coefficients had to be re-derived once that changed what “the pool” actually meant, and a related sign bug — where raising T-Level uptake perversely reduced the STEM route it was meant to feed — needed a new mechanism (an edge that explicitly offsets against a policy lever) rather than a coefficient tweak, since the two edges’ outcomes are genuinely coupled.

Stack and why

D3 does the layout and flow-path maths (linear/sqrt scales, pie/arc generators, an octilinear router), while React owns everything state-driven — the reducer holding policy overrides, memoised re-simulation on every change, and the component tree. Keeping the simulation engine and layout engine as plain, DOM-free TypeScript functions (not React hooks, not classes) was a deliberate constraint from the start, so either could later run inside a Web Worker without a rewrite if the simulation ever gets heavy enough to jank the main thread. Vitest’s per-file execution made it possible to keep a large, fast-growing test suite (165 tests) green even when the full suite hit sandbox performance limits.

What I would do differently

TODO (James) — short, in your own words.

Stack

React 18 / TypeScript / Vite
Application shell, build tooling and component layer
D3.js
Metro-map/Sankey layout, octilinear flow routing, zoom/pan, and the shared animation loop
Tailwind CSS
Styling, including a full brand/neutral/semantic colour palette pass
Vitest
Engine, layout, config and diff test suite

21

modelled policy variables

20

curated DSIT intervention presets

165/165

engine and layout tests passing

  • Repository — private repository