Ooru

Arranging the words

Why is 'copper' next to 'bronze'?

8 min read

what3words shuffles its vocabulary deliberately, so that table.chair.lamp and table.chair.lamps land on different continents. Ooru does the opposite: words are laid out so that neighbouring cells hold neighbouring meanings. This page describes how, and — more importantly — how much it actually worked.

One semantic domain per level

Each level draws from a disjoint domain. This is not decoration: it means a bare word announces which level it belongs to, so a transposed address can be rejected at parse time rather than resolved to somewhere plausible and wrong.

LevelDomainWordsExample neighbourhood
1 · Regionlandscape & water120dell, pass, glen, heath, knoll
2 · Localitymaterials, colour & texture400spruce, cedar, rosewood, cobble, balsa
3 · Spotliving things400papaya, mango, guava, tulip, hibiscus
4 · Pinpointlight & weather16dew, monsoon, squall, shower, breeze

The pipeline

The layout is generated offline by scripts/build-lexicon.ts and committed, so no model or network call is involved in serving the site.

  1. Curate. Hand-written candidate lists per domain, tagged with rough semantic groups, deliberately over-supplied so the filter has room to work.
  2. Filter. Enforce the vocabulary contract: plain lowercase ASCII, 2–12 characters, globally unique across levels, and — the important one — Levenshtein distance at least 2 from every other accepted word anywhere in the system.
  3. Embed. Each word is encoded with Xenova/all-MiniLM-L6-v2 into a 384-dimensional vector.
  4. Organise.A Kohonen self-organising map is trained over the level’s exact lattice, then a Hungarian optimal assignment decides which word sits in which cell.
  5. Measure. Report whether the result is actually more coherent than chance.

Why words are embedded inside a frame

Single words are embedded as “a photo of a {word} rather than bare. This is the standard trick for coaxing a sentence encoder into behaving like a word encoder: a bare token gives the model no syntactic context, and the resulting vectors tend to cluster by morphology — words that look alike — rather than by meaning. That is precisely backwards for this purpose.

Why a SOM and not PCA

The task is to place N words on an N-cell grid so grid neighbours are semantic neighbours. Projecting the embeddings to 2-D with PCA and snapping to the grid is the obvious approach and it is measurably worse: PCA is a linear projection that preserves the two directions of greatest global variance and shreds the local neighbourhood structure that actually matters here.

A SOM is trained to preserve topology instead. Each lattice node holds a prototype vector in the full embedding space, and every update drags the winning node and its lattice neighbours toward the sample:

w_i ← w_i + α(t) · h(d(i, bmu), σ(t)) · (x − w_i)
w is a node's prototype, x the sample, α the learning rate, and h a Gaussian neighbourhood over lattice distance whose radius decays during training. Both α and the radius decay geometrically from a whole-sheet sweep to single-node fine-tuning.

The lattice therefore folds itself through the embedding cloud like a sheet, and adjacent nodes end up holding similar prototypes by construction.

Why Hungarian assignment afterwards

The SOM alone does not give an assignment — several words can share a best-matching node and some nodes get none, which a grid cannot represent. A Hungarian (Kuhn–Munkres) solve over the word × node cost matrix finds the globally cost-minimal one-to-one mapping in O(n³); at n = 400 that is about 64 million operations, a few seconds offline. The SOM decides the shape of the map; the assignment decides who sits where.

Did it work?

Two measurements, both computed at build time over every pair of cells in each level and recorded in the shipped lexicon manifest.

LevelNeighbour similarityRandom pairCoherence liftRank correlation
1 · Region0.55530.45281.226×0.3808
2 · Locality0.53540.41471.291×0.2126
3 · Spot0.54050.40881.322×0.2789
4 · Pinpoint0.58120.51921.119×0.3486
Coherence lift is the mean cosine similarity of 4-connected grid neighbours divided by that of random pairs — if the layout did nothing this would be 1.000. Rank correlationis Spearman’s ρ between grid distance and embedding distance across all 79,800 pairs at levels 2 and 3.

One thing that was tried and did not work

The obvious next move is to denoise before organising: a 400-word vocabulary drawn from a single domain cannot plausibly span 384 meaningful directions, so projecting onto the leading principal components first ought to let the SOM spend its capacity on real structure instead of on noise. It was implemented and measured. It made things worse.

LevelCoherence lift — full 384dwith PCA→32dRank ρ — fullwith PCA→32d
1 · Region1.226×1.232×0.38080.3396
2 · Locality1.291×1.284×0.21260.1543
3 · Spot1.322×1.318×0.27890.2811
4 · Pinpoint1.119×1.012×0.34860.0443
Coherence lift is a wash; rank correlation is clearly degraded at three of four levels, and level 4 collapses to near-random. Both columns are measured in the ORIGINAL 384-d space, so they are directly comparable — scoring a reduced layout inside its own reduced space would be marking your own homework.

The reading is that the discarded components were not noise. Distinctions this vocabulary genuinely depends on — the difference between a fabric and a mineral, between a bird and a fish — apparently live in directions of comparatively low global variance, exactly the ones PCA throws away first. The full-dimensional layout is what ships. The switch survives as bun run lexicon --reduce=32 so the result can be re-checked rather than taken on trust.

What it looks like

The clearest evidence is not a statistic but the level-1 grid itself. Read west to east and the vocabulary walks from water to relief without anyone having arranged it by hand:

wharf bay strait atoll cove gulf dune sand basin butte harbour shore coast island isle moor desert canyon valley rift tide surf beach reef bog plain orchard mesa summit steppe
Rows 10–12 of the level-1 lattice, printed with north at the top. Water words gather along one edge, high ground along the other.

The atlas shows every level in full, coloured by semantic cluster.

Meaning drives appearance too

The three principal components of each word’s embedding are stored alongside it, and the 3-D marker on the map derives its hue, its mass and its proportions from them. Two words that mean similar things therefore produce markers you would describe the same way. It is the same data doing two jobs: deciding where the word sits and what it looks like.

  • signature[0] → hue, so the dominant semantic axis becomes the dominant colour axis
  • signature[1] → mass: huts in the village, tower height, storeys in the house
  • signature[2] → taper, waist and twist