Vol. II·Issue 08·The Benchmark Desk·Jul 2026·9 min read

§ Product

Search with the answer,
not the question.

Semantic search now takes hyde: true: a language model drafts the passage a relevant judgment would contain, and retrieval runs on that. Across nine landmark-case queries against production, HyDE nearly doubled first-place hits and raised mean reciprocal rank by 36%. Every number below is reproducible — including the two queries where it loses.


The problem: queries don’t sound like judgments.

Embedding search measures how close your query sits to judgment prose in vector space. A full sentence — “under what conditions may personal data be transferred to a third country” — lands close. But that isn’t how people search. People type credit scoring article 22, and four keywords sit a long way from the paragraph the Court actually wrote. The right case exists in the corpus, scores mid-pack, and never makes your top three.


One query, three engines.

Before the benchmark, the shape of the problem. Take the terse query and ask EUR-Lex-style keyword search, plain semantic search, and HyDE the same thing: which case decides whether a credit score is an Article 22 automated decision? The answer is SCHUFA (C-634/21).

“credit scoring article 22” — where is SCHUFA?
keyword search3,042 results — zero case-law in the top 10 (all financial-services legislation)
semantic
#5
semantic + hyde
#1

Keyword search matches words, and the words “credit scoring” appear in a mountain of prudential regulation. Plain semantic search understands the topic, but the terse query embeds far from judgment prose. HyDE closes the remaining gap.


How it works — fusion, not replacement.

the hyde pipeline
your query
↓   ↘
query embedding
LLM drafts a hypothetical judgment passage
↓   ↓
retrieval №1
retrieval №2 — passage embedding
↘   ↙
reciprocal-rank fusion

The two retrievals run concurrently and the rankings are fused — a weak generation can only reorder the union, never make results worse than the plain baseline’s candidates. Scores stay honest cosine values, so min_score means what it always meant. For the terse query above, the drafted passage reads:

“The Court recalls that Article 22(1) of Regulation (EU) 2016/679 (GDPR) prohibits solely automated decision-making which produces legal effects…”

— and that lands right next to SCHUFA. Generation is best-effort by contract: on failure the search silently falls back to plain retrieval, the response reports "hyde": false, and the credit premium is refunded automatically. The drafted passage comes back as hypotheticalDocument, so a surprising result is always explainable.

curl https://lex-api.com/api/v1/search/semantic \
  -H "x-api-key: $LEX_KEY" -H "content-type: application/json" \
  -d '{"query": "credit scoring article 22", "limit": 10, "hyde": true}'

The benchmark: nine landmark cases.

Nine queries, each with a known landmark answer, run against production on 2–3 July 2026. “Rank” is where the landmark appears in the top 10.

5 vs 3
ranked #1
HyDE vs plain, of 9 queries
7 vs 6
in the top 3
HyDE vs plain, of 9 queries
+36%
mean reciprocal rank
0.685 vs 0.504
rank of the landmark case — plain (grey) vs hyde (indigo)
SCHUFA — “credit scoring article 22”
#5
#1
SCHUFA (long) — “credit scoring probability value third party bank Article 22 a…”
not in top 10
#2
Schrems II — “transfer of personal data to a third country surveillance safe…”
#2
#1
Google Spain — “right to be forgotten delisting search engine”
#1
#1
Digital Rights Ireland — “general and indiscriminate retention of traffic data”
#1
#2
Aziz — “unfair terms consumer mortgage contract national court assessm…”
#3
#1
Sturgeon — “airline compensation flight delay three hours”
not in top 10not in top 10
Svensson — “hyperlinks to protected works communication to a new public”
#1
#1
G4S / Achbita — “employer ban headscarf workplace neutrality policy”
#2
#6

The pattern is consistent: HyDE wins exactly where plain retrieval struggles. The two hardest queries — terse keywords, and operational language plain retrieval missed entirely — became #1 and #2. Queries plain search already nailed stayed nailed (three #1 ties), occasionally shuffling within the top 2 — the “displacement” in the retention query was the Advocate General’s opinion in La Quadrature du Net, hardly a wrong answer.


Where it loses — because a benchmark that never loses is a brochure.

  • G4S / Achbita regressed from #2 to #6. The drafted passage framed the headscarf question through general discrimination doctrine, and the fused ranking pulled adjacent equal-treatment cases ahead of the target. This is the designed failure mode: fusion bounds the damage — the case stayed on the first page — but the hypothetical steered toward the doctrine rather than the specific dispute. If your query already names the precise factual setting, plain retrieval can be the sharper tool.
  • Sturgeon (flight-delay compensation) missed in both modes. No retrieval trick fixes a coverage gap: if the judgment’s text sits far from anything the query or a hypothetical can reach, HyDE can’t conjure it. Honest conclusion: HyDE improves ranking, not reach.

What it costs.

median latency across the nine benchmark queries
plain
2.3 s
hyde
11.6 s
ranges: plain 0.8–4.0 s (one 11.9 s cold start) · hyde 8.7–17.9 s
  • Latency. One model call plus an extra embedding and a second retrieval. HyDE is for when recall matters more than milliseconds — research sessions, agent pipelines, RAG indexing — not for type-ahead.
  • Price. 15 credits against plain semantic’s 5. If generation falls back, the 10-credit premium is refunded automatically and the response says so.
  • When to skip it. Full-sentence queries in legal register usually don’t need it — three of our nine queries tied at #1 either way. HyDE earns its cost on short, keyword-style queries and on questions phrased in operational language rather than the Court’s.

hyde is live on POST /api/v1/search/semantic for every credit plan — details in the docs. One flag in both SDKs: client.semantic_search(q, hyde=True) in Python, client.semanticSearch({ query, hyde: true }) in TypeScript.