Ties Go to the Provider, and No Match Changes Nothing
Two details make the ranker safe to deploy, and both are about not being confidently wrong.
Equal coverage keeps the provider's order. The ?: in that comparator falls back to the original index, so a tie preserves whatever the provider decided. Their ordering is a real relevance ranking; reshuffling a flat scoreboard would replace information with noise.
When nothing matches at all, return the input untouched:
// Every candidate is equally (un)related — e.g. a Spanish query against
// English alt text. Trust the provider rather than an arbitrary reshuffle
// of a flat scoreboard.
if (array_sum(array_column($scored, 'coverage')) <= 0) {
return $candidates;
}
That case is common and predictable: a Spanish query against English descriptions scores zero everywhere. The ranker cannot help, so it declines to act.
A rescue layer must never be worse than the thing it is rescuing. State the floor explicitly — never a worse pick than today's behaviour — and add the branch that guarantees it.
Deterministic Means Testable
Everything above is a pure function, which is why the reasoning survives as tests: the balayage photo beating the generic salon shot, the janitorial photo beating the party balloons, the mopping photo beating the home office.
That last one is the deleted experiment, pinned. Anyone who reinvents position weighting fails a test whose comment explains why it was tried and dropped. The measurement is in the repository, not in someone's memory.
Where Else This Shape Applies
The pattern recurs whenever a model hands off to something that picks:
- Choosing among search results, documents or products
- Deciding which of several tool results to present first
- Picking a template, a category or a tag from a fixed set
- Any "the model suggested a query, now something else answers it"
In all of them the temptation is to make the model do the picking too. Often the deterministic version is better: it is auditable, free, instant, and it never has an off day. Reach for the model when the judgement genuinely requires language understanding — and measure both before deciding it does.
What This Chapter Argued
- A bad output is often a bad pipeline, not a bad model. Compound queries and first-result-wins produced most of the off-topic imagery.
- Write the deterministic version first. Term coverage, no embeddings, readable in a minute.
- Measure the clever version against the simple one, and delete it when it does not win. Cleverness that measures the same is worse.
- Preserve upstream ordering on ties. A real relevance ranking beats an arbitrary reshuffle.
- Guarantee a floor: never worse than doing nothing, and add the branch that enforces it.
- Pin the measurement as a test so the rejected alternative cannot come back.
- Deterministic beats a model call wherever the judgement does not need language.