Running the Retrieval Quality Harness

Wikantik's retrieval-quality harness runs a curated query set against the live search stack, on demand and every night, so a retrieval change can be judged with numbers instead of a vibe check. The scheduled runner, the database-backed query-set store (retrieval_query_sets / retrieval_queries / retrieval_runs), the Prometheus gauges and the admin dashboard are Phase 5 of AgentGradeContentDesign, and all of them have shipped.

When to use this runbook

Before merging a retrieval-touching change (chunker, embeddings, fusion weights, query parsing), when investigating an anecdotal quality regression, or when you want to read the nightly quality gauges.

Context

DefaultRetrievalQualityRunner (wikantik-main, package com.wikantik.knowledge.eval) is the harness. For one (query set, mode) pair it:

  1. loads the set's queries from retrieval_queries (tables retrieval_query_sets, retrieval_queries, retrieval_runs come from migration V016);
  2. runs each query through the live retrieval stack in the requested mode;
  3. resolves the returned page names to canonical_ids and scores them against the query's expected_ids with binary relevance — nDCG@5, nDCG@10, Recall@20 and MRR;
  4. averages across the set, writes a retrieval_runs row, and updates the wikantik_retrieval_* Prometheus gauges.

The seeded set is core-agent-queries (V017): 16 hand-curated questions, one per agent-cookbook runbook plus a cross-cluster query. Queries with empty expected_ids are skipped; a query whose retriever throws is skipped and marks the run degraded.

Modes (com.wikantik.api.eval.RetrievalMode):

ModeWhat it runs
bm25Lucene BM25 only
hybridBM25 + dense, RRF-fused — the production default
hybrid_graph, hybrid_graph_weightedRetired. The Knowledge Graph rerank was deleted in 2026-07; the names survive only so historical retrieval_runs.mode rows still parse, and a fresh run degrades to hybrid

Walkthrough

  1. Read the baseline. Open Admin → Retrieval Quality (/admin/retrieval-quality): one row per (query set, mode) with the latest value and a sparkline per metric.
  2. Run now. Click Run now on the row, or call POST /admin/retrieval-quality/run with {"query_set_id":"core-agent-queries","mode":"hybrid"} (admin session required). The call is synchronous and returns ndcg_at_5, ndcg_at_10, recall_at_20, mrr, queries_evaluated, queries_skipped and degraded.
  3. Compare with history. GET /admin/retrieval-quality?query_set_id=core-agent-queries&mode=hybrid&limit=30 returns recent runs. An absolute drop of more than 5 points in nDCG@5 against the previous run of the same set and mode is the design's alert threshold; the same figure is the wikantik_retrieval_ndcg_at_5{set,mode} gauge.
  4. Check the quality of the run itself — degraded and queries_skipped — before trusting the number.
  5. Spot-check any wiki without admin access with bin/search-eval, which scores eval/retrieval-queries.csv through GET /api/search (see WikantikSearchRefinement).

The same runner fires nightly at wikantik.retrieval.cron.hour_utc (default 03:00 UTC) for every non-retired mode when wikantik.retrieval.cron.enabled is true (the default); each failed (set, mode) pair is logged at WARN and counted in wikantik_retrieval_run_failed_total. Operator detail lives in docs/admin/RetrievalQuality.md.

Two sibling harnesses exist. The context bundle has a section-recall corpus (eval/bundle-corpus/, bin/eval/run-baseline.py, floors in thresholds.properties) that a scheduler can run when wikantik.bundle.eval.interval.hours is above 0 (default 0 = disabled). The offline embedding-model and fusion experiments are described on RetrievalExperimentHarness.

Pitfalls


Cluster Hub: Agent Cookbook (agent-cookbook)