◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/API & SDK
⬡ API & SDK/2026-07-13Advanced

Precision Lives in the Second Stage: Reranking a Personal Knowledge Search with Claude

Embedding search alone leaves 'semantically close but not the answer' passages at the top. This is a two-stage design that gathers candidates broadly, then lets Claude reorder them by answerability, with structured scoring, abstention, and a cost estimate.

claude-api83rerankretrievalrag4embeddingstructured-output5knowledge-base

✦ Premium Article

I once stopped mid-search through my own notes. Over years as an indie developer I had accumulated app FAQs and implementation memos, and when I ran an embedding search asking "what is the refund deadline," the top hit was a paragraph describing the philosophy behind the refund policy. The wording was a close match. But the number of days appeared nowhere in it.

Close, yet not answering. That is almost always the shape of an embedding search's misses. My first suspect was the embedding model's accuracy, but that is not what I fixed. I only added a second stage: take the candidates gathered roughly, and have Claude reorder them once more. This article records the design and implementation of that two-stage search, using a small personal knowledge base as the subject.

"Semantically Close" Is Not "Answers the Question"

Embedding search converts the question and documents into vectors in the same meaning space and returns the nearest ones. What it is good at is topical closeness. Ask about refunds, and it gathers every paragraph written about refunds.

The trouble is that this ranking is ordered by topical closeness, not by how well a passage answers the question. A paragraph on refund philosophy could not be closer to the topic of refunds. But for the question "how many days is the deadline," a plainer, operational sentence containing an actual number is more precise. Take the embedding-only top-3 as-is, and candidates that are close in meaning but not the answer push past the ones that actually contain it.

Swapping in a more expensive embedding model does not fundamentally remove this. You are trying to solve a mismatch of measures with more precision on the wrong measure. What you need is a second stage that re-scores the gathered candidates by answerability.

The Shape of a Two-Stage Search

What you do is simple. Gather broadly and shallowly in the first stage; choose narrowly and deeply in the second.

The first stage (recall) is embedding search, and it thinks only about missing nothing, so it grabs a wide top-20 rather than a top-3. The goal here is to make sure a passage containing the answer is somewhere in the candidate set; the correctness of the order does not matter yet. In the second stage (rerank), Claude scores those 20 by "how precisely does this answer the question" and keeps only the top few.

StageHandled byGoalMeasure
First: recallEmbedding searchMiss nothing (broad top-20)Topical closeness
Second: rerankClaudeNarrow to a precise few (top-3)Answerability

The first stage is fast and cheap; the second is smart. Splitting the roles lets Claude cover the embedding's weakness, while the embedding spares Claude from reading every document.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A complete two-stage retrieval implementation: embeddings gather a broad top-N, then Claude reorders them with a structured relevance score (all candidates batched into one request for a consistent rubric and bounded cost)
✦An abstain threshold so the search declines rather than answering when it is not confident, plus returning which passage was chosen and why
✦A cost estimate derived from candidate count and average tokens, with a rule for when Haiku is enough, when Sonnet is needed, and when reranking is unnecessary at all
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ API & SDK2026-05-10
Bulletproof JSON Output with Claude API Prefill: A Four-Layer Defense Pattern from Indie SaaS
How I went from late-night JSON parse failures to a 99.98% parse success rate across thousands of monthly Claude API requests, and what a 1,081-sample truncation benchmark revealed about the repair code I had originally published here.
⬡ API & SDK2026-04-29
Production Semantic Cache for Claude API — Similarity Thresholds, Pollution Defense, and What to Track
A production playbook for adding a semantic cache in front of Claude API — threshold tuning, multi-tenant isolation, pollution prevention, fallbacks, how it stacks with Anthropic's prompt caching, and the metrics that actually prove it works.
⬡ API & SDK2026-09-22
Character counts won't predict PDF input tokens — bracket the cost per page before you send
How to estimate the input tokens of a PDF before sending it to the Claude API, by bracketing from page count rather than character count. Includes a measured 6.6x gap on a nine-page A4 document, the two separate increases that come with current models, and the count_tokens limitation that bites when you use file_id.