georgian-io/query_form_experiment

Repository for query form experiment.

4

stars

2

commits

Python

primary language

Sep 3, 2026

updated

README

query_form_experiment

The code and the evidence behind Your Queries Can Reorder the Leaderboard.

I explored what happens to a retrieval leaderboard when you change only the form of the queries, holding the corpus and the relevance labels fixed. This repository is the harness that ran the experiment and the per-query score files it produced. If you have just read the post and want to see where a number came from, the table below is the index. Every number recomputes from a clone, offline, with nothing paid:

uv sync
uv run python scripts/05_analyze.py        # the reproduction gate, model by model
uv run python tools/transform_analysis.py  # reshuffle tables, controls, levelling

Where the post's numbers come from

In the postHereProduced by
The four query forms (CUREv1 example)qid 000001 in results/queries__curev1_en__{condition}__gemini-2.5-pro.jsonscripts/02_run_transform.py
Reproducing published scoresReproduction gatescripts/05_analyze.py
The τ table, three rewrites × three datasetsReshuffle, averaged over the four generatorstools/transform_analysis.py
Figure 1, the board reordered by elaborationRank movestools/chart_data.pytools/make_post_figures.py
Figure 2, the per-model ΔNDCG heatmapdeltas.trec_covid in the chart datasame
The human-phrasing τ tableHuman phrasingstools/transform_analysis.py, tools/chart_data.py
Figure 3, three human phrasings rankedhuman_fields in the chart datasame
Compression improves 19 models; the +0.44 and -0.78 strength correlationsLevellingtools/transform_analysis.py
Figure 4 and the one-gold vs pooled-key tableThe sparse-key arithmetictools/make_sparse_key_figure.py
The τ ranges by label densityReshuffle, the per-generator tablestools/transform_analysis.py

Figures live in docs/figures/. Regenerate them with:

uv run python tools/chart_data.py chart_data.json
uv run python tools/make_post_figures.py chart_data.json docs/figures

What was run

Three datasets: ChatDoctor marks one relevant document per query, CUREv1 about forty, and TREC-COVID several hundred, graded 0/1/2. Each dataset's queries were rewritten three ways (paraphrase, terse, verbose) by four LLMs from four families. The rewriters worked independently, so if only one of them produces an effect it shows up as such.

Twenty-one embedding models. All 21 ran on CUREv1 and TREC-COVID. 17 of them ran on ChatDoctor, which is why its board is shorter. Retrieval is turbopuffer, dense by default, with BM25 and hybrid RRF available as controls.

The harness also carries AILAStatutes and HumanEval as pilots. They were just used to explore before moving on to the larger corpora, and their runs are still in results/, but the post does not use them.

The reproduction gate

The first task was to tune the harness so that it could reproduce each model's published NDCG@10 on the original queries from each same dataset.

datasetpublished resultswithin 0.01worst absolute delta
ChatDoctor16160.00493 (voyage-4-large)
CUREv117160.03345 (text-embedding-004)
TREC-COVID850.10769 (bge-base-en-v1.5)
AILAStatutes (pilot)23220.01274 (bge-m3)
HumanEval (pilot)22220.00328 (embed-multilingual-v3.0)

81 of 86 pairs match within 0.01. The three TREC-COVID misses are all bge-*-en-v1.5 prefix models and they all miss low by a similar amount, so the ordering survives - my TREC-COVID board reproduces the published one at τ = 1.000, an exact order match. The five prefix-free models on that dataset land within 0.003. I think the bge gap is a prompting difference in how the published run handled those models, but I have not closed it and I don't want to explain it away, so I'll keep it on the books as a miss.

Leaderboard reshuffle

Kendall's τ between each transformed-query leaderboard and the same dataset's original human-query leaderboard, dense retrieval, averaged over the four generators. This is the post's headline table:

rewriteChatDoctor (1 gold)CUREv1 (~40)TREC-COVID (graded)
paraphrase0.9150.9570.900
terse0.9050.8880.748
verbose0.9380.8340.607

Averaging hides whether the generators agree, so the per-generator numbers follow, with RBO (p = 0.9) alongside. Board size differs by dataset because not every model has a published anchor on every one.

ChatDoctor, 17-model board, 5,591 queries:

conditiongeneratorτRBO
paraphrasegemini-2.5-pro+0.92650.9101
paraphraseclaude-opus-4-8+0.92650.9371
paraphrasegpt-5.1+0.89710.9101
paraphrasellama-3.3-70b+0.91180.9101
tersegemini-2.5-pro+0.91180.9101
terseclaude-opus-4-8+0.89710.9011
tersegpt-5.1+0.91180.9002
tersellama-3.3-70b+0.89710.8980
verbosegemini-2.5-pro+0.97060.9952
verboseclaude-opus-4-8+0.94120.9371
verbosegpt-5.1+0.91180.9088
verbosellama-3.3-70b+0.92650.9713

CUREv1, 21-model board, 2,000 queries:

conditiongeneratorτRBO
paraphrasegemini-2.5-pro+0.95240.9947
paraphraseclaude-opus-4-8+0.96190.9933
paraphrasegpt-5.1+0.95240.9894
paraphrasellama-3.3-70b+0.96190.9933
tersegemini-2.5-pro+0.88570.9604
terseclaude-opus-4-8+0.88570.9604
tersegpt-5.1+0.89520.9762
tersellama-3.3-70b+0.88570.9604
verbosegemini-2.5-pro+0.84760.9135
verboseclaude-opus-4-8+0.85710.9153
verbosegpt-5.1+0.82860.8783
verbosellama-3.3-70b+0.80000.8762

TREC-COVID, 21-model board, 50 topics. With only 50 queries, τ carries a seeded 1,000-resample query-level bootstrap CI, and I only count a τ below 0.9 if its interval excludes 0.9:

conditiongeneratorτ95% CIRBO
paraphrasegemini-2.5-pro+0.9048[+0.781, +0.924]0.9244
paraphraseclaude-opus-4-8+0.9048[+0.762, +0.914]0.9041
paraphrasegpt-5.1+0.9333[+0.771, +0.924]0.9098
paraphrasellama-3.3-70b+0.8571[+0.762, +0.905]0.8817
tersegemini-2.5-pro+0.7238[+0.619, +0.781]0.8222
terseclaude-opus-4-8+0.7429[+0.648, +0.810]0.7808
tersegpt-5.1+0.8095[+0.695, +0.848]0.8983
tersellama-3.3-70b+0.7143[+0.609, +0.752]0.7827
verbosegemini-2.5-pro+0.6000[+0.457, +0.667]0.5971
verboseclaude-opus-4-8+0.6952[+0.524, +0.724]0.6620
verbosegpt-5.1+0.5238[+0.314, +0.619]0.6013
verbosellama-3.3-70b+0.6095[+0.486, +0.657]0.5789

I see a pattern across the three tables. Verbose is the gentlest condition on ChatDoctor and the harshest on the two densely-labelled datasets, and all four generators agree on that ordering, so I don't read it as one rewriter's quirk. This isn't quite a controlled ablation though since the datasets differ in more than their label density.

The board reordered by elaboration

TREC-COVID, 21 models, ranked by the benchmark's own questions and then by the generator-averaged verbose rewrite of those same questions. This is Figure 1:

questionverbosemodel
13voyage-3-large
26embed-multilingual-v3.0
35voyage-4-large
42text-embedding-004
57voyage-4
68voyage-3.5-int8-512
74text-embedding-3-large
810gemini-embedding-001
99voyage-4-lite
1013text-embedding-3-small
1115embed-v4.0
1212bge-base-en-v1.5
1316bge-small-en-v1.5
1414bge-large-en-v1.5
151qwen3-embedding-8b
1611voyage-law-2
1718multi-qa-MiniLM-L6-cos-v1
1820bge-m3
1917all-mpnet-base-v2
2019all-MiniLM-L12-v2
2121all-MiniLM-L6-v2

Three models gain three or more places and four lose three or more. qwen3-embedding-8b goes 15th to 1st. Five of the original top six move down.

Human phrasings: the control on LLM style

Every rewrite above was written by an LLM, so the obvious objection is that the result is about how language models write. Since each TREC-COVID topic also ships both of a human-written keyword query and a paragraph-length narrative alongside the question the benchmark scores, I can use these as a check without involving LLMs.

τ against the question board, over the 20 models that have all three human phrasings (bge-m3 has no human-field run):

query formτ vs question
keyword (human)+0.8211
terse (LLM)+0.7500
narrative (human)+0.7263
verbose (LLM)+0.6526

A human-written paragraph reorders the board at τ = 0.726 with no change in meaning and no LLM involved. The LLM rewrites are each somewhat harsher than the human form they imitate, so my read is that they overstate the effect a little without creating it. The two extremes, keyword against narrative, sit at +0.7158, no further apart than either is from the middle form, which makes me doubt that length alone explains this.

The LLM τ values above are the mean of the four per-generator τ values on that 20-model board, which is why they differ slightly from the 21-model figures in the reshuffle tables.

Comparing boards is one thing. Matching the shifts model by model is stricter:

human shiftsynthetic shiftSpearman ρpsign agreement
questionquery (keyword)terse+0.749<0.00180%
questionnarrativeverbose+0.6710.00145%

Keyword compression is well mimicked. Elaboration is only partly mimicked - sign agreement near chance means the LLM elaboration and a human's both reshuffle hard but land the per-model effect differently. That is a caveat on the verbose numbers specifically and it does not touch the terse ones.

Levelling

Elaboration costs the strongest models the most and lifts several of the weakest. Going the other way, compressing narrative back to question improves 19 of the 20 models with human phrasings, by an average of +0.1098 NDCG@10.

Correlating a change score against the same baseline it was computed from invites regression to the mean, so I also measured strength on a separate dataset and report both readings:

shiftstrength measured onSpearman ρpn
TREC-COVID verboseCUREv1 (independent)-0.779<0.000121
TREC-COVID verboseits own baseline (naive)-0.887<0.000121
CUREv1 verboseTREC-COVID (independent)-0.3100.1721
CUREv1 verboseits own baseline (naive)-0.2780.2221
TREC-COVID human narrativeCUREv1 (independent)-0.4440.0520
TREC-COVID human narrativeits own baseline (naive)-0.5650.00920
TREC-COVID compression, narrative → questionCUREv1 (independent)+0.4440.0520

From what I can see, some of the effect is that artifact and most of it isn't, at least on TREC-COVID, where the independent measure holds at -0.779. On CUREv1 it doesn't reach significance either way. So I wouldn't state this as a general law - it is one dataset's result, with a second dataset declining to confirm it.

Controls not in the post

Two further checks, both out of tools/transform_analysis.py, on whether the verbose result is a property of the queries or an artifact of something else.

The first is BM25, which isolates surface-word change since a lexical scorer only sees tokens. ΔNDCG@10 against the human-query BM25 run, averaged over the four generators:

datasetbaselineparaphraseterseverbose
ChatDoctor0.3277-0.021+0.054-0.021
CUREv10.3555-0.062+0.009-0.005
TREC-COVID0.6083-0.057+0.097+0.026

Verbose leaves BM25 near flat on all three while moving the dense board hard. I read that as semantic broadening - the tokens barely change, but the meaning the dense models see does. Terse on TREC-COVID is the opposite case. BM25 climbs 0.097 there because the rewrite really is more keyword-like.

The second is a cross-lineage LLM audit, with the judge never drawn from the rewriter's own family, flagging rewrites that changed the underlying information need. Pooled drift rate against a 15% threshold, n = 120 sampled queries per cell (50 on TREC-COVID):

datasetparaphraseterseverbose
ChatDoctor1.9%17.7%26.3%
CUREv13.1%10.0%32.4%
TREC-COVID5.0%8.0%27.9%

Verbose breaches the threshold, so drift is a live worry, but it is generator-split. gpt-5.1 and llama drift hard on verbose (52.5% and 56.7% on CUREv1) while claude (6.0-7.5%) and gemini (12.6-14.9%) elaborate faithfully. The faithful lineages still move the dense board about as far as the drifting ones - claude's verbose gives τ 0.857 on CUREv1 and 0.695 on TREC-COVID, against 0.962 and 0.905 for its own paraphrase. So far as I can tell the effect survives the drift control.

Per-generator rates are in results/audit__{dataset}__{condition}.json.

Data

results/ contains 1,386 files - every number from the experiment recomputes without re-running any pipelines. The dense__* and bm25__* files carry run metadata and a per-query map of qid to NDCG@10. The queries__* files carry the generated rewrites themselves, and the audit__* files carry the drift judgments.

Running it

uv sync
uv run pytest        # unit tests; integration tests are deselected by default

uv run python scripts/01_build_index.py   --dataset aila_statutes --model gemini-embedding-001
uv run python scripts/03_run_retrieval.py --dataset aila_statutes --model gemini-embedding-001 --mode dense

--mode also takes bm25 and hybrid; --condition and --generator select a rewrite. scripts/05_analyze.py and tools/transform_analysis.py take dataset names as positional arguments and default to chatdoctor curev1_en trec_covid.

Contributors

georgian-io/query_form_experiment

Repository for query form experiment.

4

stars

2

commits

Python

primary language

Sep 3, 2026

updated

README

query_form_experiment

The code and the evidence behind Your Queries Can Reorder the Leaderboard.

I explored what happens to a retrieval leaderboard when you change only the form of the queries, holding the corpus and the relevance labels fixed. This repository is the harness that ran the experiment and the per-query score files it produced. If you have just read the post and want to see where a number came from, the table below is the index. Every number recomputes from a clone, offline, with nothing paid:

uv sync
uv run python scripts/05_analyze.py        # the reproduction gate, model by model
uv run python tools/transform_analysis.py  # reshuffle tables, controls, levelling

Where the post's numbers come from

In the postHereProduced by
The four query forms (CUREv1 example)qid 000001 in results/queries__curev1_en__{condition}__gemini-2.5-pro.jsonscripts/02_run_transform.py
Reproducing published scoresReproduction gatescripts/05_analyze.py
The τ table, three rewrites × three datasetsReshuffle, averaged over the four generatorstools/transform_analysis.py
Figure 1, the board reordered by elaborationRank movestools/chart_data.pytools/make_post_figures.py
Figure 2, the per-model ΔNDCG heatmapdeltas.trec_covid in the chart datasame
The human-phrasing τ tableHuman phrasingstools/transform_analysis.py, tools/chart_data.py
Figure 3, three human phrasings rankedhuman_fields in the chart datasame
Compression improves 19 models; the +0.44 and -0.78 strength correlationsLevellingtools/transform_analysis.py
Figure 4 and the one-gold vs pooled-key tableThe sparse-key arithmetictools/make_sparse_key_figure.py
The τ ranges by label densityReshuffle, the per-generator tablestools/transform_analysis.py

Figures live in docs/figures/. Regenerate them with:

uv run python tools/chart_data.py chart_data.json
uv run python tools/make_post_figures.py chart_data.json docs/figures

What was run

Three datasets: ChatDoctor marks one relevant document per query, CUREv1 about forty, and TREC-COVID several hundred, graded 0/1/2. Each dataset's queries were rewritten three ways (paraphrase, terse, verbose) by four LLMs from four families. The rewriters worked independently, so if only one of them produces an effect it shows up as such.

Twenty-one embedding models. All 21 ran on CUREv1 and TREC-COVID. 17 of them ran on ChatDoctor, which is why its board is shorter. Retrieval is turbopuffer, dense by default, with BM25 and hybrid RRF available as controls.

The harness also carries AILAStatutes and HumanEval as pilots. They were just used to explore before moving on to the larger corpora, and their runs are still in results/, but the post does not use them.

The reproduction gate

The first task was to tune the harness so that it could reproduce each model's published NDCG@10 on the original queries from each same dataset.

datasetpublished resultswithin 0.01worst absolute delta
ChatDoctor16160.00493 (voyage-4-large)
CUREv117160.03345 (text-embedding-004)
TREC-COVID850.10769 (bge-base-en-v1.5)
AILAStatutes (pilot)23220.01274 (bge-m3)
HumanEval (pilot)22220.00328 (embed-multilingual-v3.0)

81 of 86 pairs match within 0.01. The three TREC-COVID misses are all bge-*-en-v1.5 prefix models and they all miss low by a similar amount, so the ordering survives - my TREC-COVID board reproduces the published one at τ = 1.000, an exact order match. The five prefix-free models on that dataset land within 0.003. I think the bge gap is a prompting difference in how the published run handled those models, but I have not closed it and I don't want to explain it away, so I'll keep it on the books as a miss.

Leaderboard reshuffle

Kendall's τ between each transformed-query leaderboard and the same dataset's original human-query leaderboard, dense retrieval, averaged over the four generators. This is the post's headline table:

rewriteChatDoctor (1 gold)CUREv1 (~40)TREC-COVID (graded)
paraphrase0.9150.9570.900
terse0.9050.8880.748
verbose0.9380.8340.607

Averaging hides whether the generators agree, so the per-generator numbers follow, with RBO (p = 0.9) alongside. Board size differs by dataset because not every model has a published anchor on every one.

ChatDoctor, 17-model board, 5,591 queries:

conditiongeneratorτRBO
paraphrasegemini-2.5-pro+0.92650.9101
paraphraseclaude-opus-4-8+0.92650.9371
paraphrasegpt-5.1+0.89710.9101
paraphrasellama-3.3-70b+0.91180.9101
tersegemini-2.5-pro+0.91180.9101
terseclaude-opus-4-8+0.89710.9011
tersegpt-5.1+0.91180.9002
tersellama-3.3-70b+0.89710.8980
verbosegemini-2.5-pro+0.97060.9952
verboseclaude-opus-4-8+0.94120.9371
verbosegpt-5.1+0.91180.9088
verbosellama-3.3-70b+0.92650.9713

CUREv1, 21-model board, 2,000 queries:

conditiongeneratorτRBO
paraphrasegemini-2.5-pro+0.95240.9947
paraphraseclaude-opus-4-8+0.96190.9933
paraphrasegpt-5.1+0.95240.9894
paraphrasellama-3.3-70b+0.96190.9933
tersegemini-2.5-pro+0.88570.9604
terseclaude-opus-4-8+0.88570.9604
tersegpt-5.1+0.89520.9762
tersellama-3.3-70b+0.88570.9604
verbosegemini-2.5-pro+0.84760.9135
verboseclaude-opus-4-8+0.85710.9153
verbosegpt-5.1+0.82860.8783
verbosellama-3.3-70b+0.80000.8762

TREC-COVID, 21-model board, 50 topics. With only 50 queries, τ carries a seeded 1,000-resample query-level bootstrap CI, and I only count a τ below 0.9 if its interval excludes 0.9:

conditiongeneratorτ95% CIRBO
paraphrasegemini-2.5-pro+0.9048[+0.781, +0.924]0.9244
paraphraseclaude-opus-4-8+0.9048[+0.762, +0.914]0.9041
paraphrasegpt-5.1+0.9333[+0.771, +0.924]0.9098
paraphrasellama-3.3-70b+0.8571[+0.762, +0.905]0.8817
tersegemini-2.5-pro+0.7238[+0.619, +0.781]0.8222
terseclaude-opus-4-8+0.7429[+0.648, +0.810]0.7808
tersegpt-5.1+0.8095[+0.695, +0.848]0.8983
tersellama-3.3-70b+0.7143[+0.609, +0.752]0.7827
verbosegemini-2.5-pro+0.6000[+0.457, +0.667]0.5971
verboseclaude-opus-4-8+0.6952[+0.524, +0.724]0.6620
verbosegpt-5.1+0.5238[+0.314, +0.619]0.6013
verbosellama-3.3-70b+0.6095[+0.486, +0.657]0.5789

I see a pattern across the three tables. Verbose is the gentlest condition on ChatDoctor and the harshest on the two densely-labelled datasets, and all four generators agree on that ordering, so I don't read it as one rewriter's quirk. This isn't quite a controlled ablation though since the datasets differ in more than their label density.

The board reordered by elaboration

TREC-COVID, 21 models, ranked by the benchmark's own questions and then by the generator-averaged verbose rewrite of those same questions. This is Figure 1:

questionverbosemodel
13voyage-3-large
26embed-multilingual-v3.0
35voyage-4-large
42text-embedding-004
57voyage-4
68voyage-3.5-int8-512
74text-embedding-3-large
810gemini-embedding-001
99voyage-4-lite
1013text-embedding-3-small
1115embed-v4.0
1212bge-base-en-v1.5
1316bge-small-en-v1.5
1414bge-large-en-v1.5
151qwen3-embedding-8b
1611voyage-law-2
1718multi-qa-MiniLM-L6-cos-v1
1820bge-m3
1917all-mpnet-base-v2
2019all-MiniLM-L12-v2
2121all-MiniLM-L6-v2

Three models gain three or more places and four lose three or more. qwen3-embedding-8b goes 15th to 1st. Five of the original top six move down.

Human phrasings: the control on LLM style

Every rewrite above was written by an LLM, so the obvious objection is that the result is about how language models write. Since each TREC-COVID topic also ships both of a human-written keyword query and a paragraph-length narrative alongside the question the benchmark scores, I can use these as a check without involving LLMs.

τ against the question board, over the 20 models that have all three human phrasings (bge-m3 has no human-field run):

query formτ vs question
keyword (human)+0.8211
terse (LLM)+0.7500
narrative (human)+0.7263
verbose (LLM)+0.6526

A human-written paragraph reorders the board at τ = 0.726 with no change in meaning and no LLM involved. The LLM rewrites are each somewhat harsher than the human form they imitate, so my read is that they overstate the effect a little without creating it. The two extremes, keyword against narrative, sit at +0.7158, no further apart than either is from the middle form, which makes me doubt that length alone explains this.

The LLM τ values above are the mean of the four per-generator τ values on that 20-model board, which is why they differ slightly from the 21-model figures in the reshuffle tables.

Comparing boards is one thing. Matching the shifts model by model is stricter:

human shiftsynthetic shiftSpearman ρpsign agreement
questionquery (keyword)terse+0.749<0.00180%
questionnarrativeverbose+0.6710.00145%

Keyword compression is well mimicked. Elaboration is only partly mimicked - sign agreement near chance means the LLM elaboration and a human's both reshuffle hard but land the per-model effect differently. That is a caveat on the verbose numbers specifically and it does not touch the terse ones.

Levelling

Elaboration costs the strongest models the most and lifts several of the weakest. Going the other way, compressing narrative back to question improves 19 of the 20 models with human phrasings, by an average of +0.1098 NDCG@10.

Correlating a change score against the same baseline it was computed from invites regression to the mean, so I also measured strength on a separate dataset and report both readings:

shiftstrength measured onSpearman ρpn
TREC-COVID verboseCUREv1 (independent)-0.779<0.000121
TREC-COVID verboseits own baseline (naive)-0.887<0.000121
CUREv1 verboseTREC-COVID (independent)-0.3100.1721
CUREv1 verboseits own baseline (naive)-0.2780.2221
TREC-COVID human narrativeCUREv1 (independent)-0.4440.0520
TREC-COVID human narrativeits own baseline (naive)-0.5650.00920
TREC-COVID compression, narrative → questionCUREv1 (independent)+0.4440.0520

From what I can see, some of the effect is that artifact and most of it isn't, at least on TREC-COVID, where the independent measure holds at -0.779. On CUREv1 it doesn't reach significance either way. So I wouldn't state this as a general law - it is one dataset's result, with a second dataset declining to confirm it.

Controls not in the post

Two further checks, both out of tools/transform_analysis.py, on whether the verbose result is a property of the queries or an artifact of something else.

The first is BM25, which isolates surface-word change since a lexical scorer only sees tokens. ΔNDCG@10 against the human-query BM25 run, averaged over the four generators:

datasetbaselineparaphraseterseverbose
ChatDoctor0.3277-0.021+0.054-0.021
CUREv10.3555-0.062+0.009-0.005
TREC-COVID0.6083-0.057+0.097+0.026

Verbose leaves BM25 near flat on all three while moving the dense board hard. I read that as semantic broadening - the tokens barely change, but the meaning the dense models see does. Terse on TREC-COVID is the opposite case. BM25 climbs 0.097 there because the rewrite really is more keyword-like.

The second is a cross-lineage LLM audit, with the judge never drawn from the rewriter's own family, flagging rewrites that changed the underlying information need. Pooled drift rate against a 15% threshold, n = 120 sampled queries per cell (50 on TREC-COVID):

datasetparaphraseterseverbose
ChatDoctor1.9%17.7%26.3%
CUREv13.1%10.0%32.4%
TREC-COVID5.0%8.0%27.9%

Verbose breaches the threshold, so drift is a live worry, but it is generator-split. gpt-5.1 and llama drift hard on verbose (52.5% and 56.7% on CUREv1) while claude (6.0-7.5%) and gemini (12.6-14.9%) elaborate faithfully. The faithful lineages still move the dense board about as far as the drifting ones - claude's verbose gives τ 0.857 on CUREv1 and 0.695 on TREC-COVID, against 0.962 and 0.905 for its own paraphrase. So far as I can tell the effect survives the drift control.

Per-generator rates are in results/audit__{dataset}__{condition}.json.

Data

results/ contains 1,386 files - every number from the experiment recomputes without re-running any pipelines. The dense__* and bm25__* files carry run metadata and a per-query map of qid to NDCG@10. The queries__* files carry the generated rewrites themselves, and the audit__* files carry the drift judgments.

Running it

uv sync
uv run pytest        # unit tests; integration tests are deselected by default

uv run python scripts/01_build_index.py   --dataset aila_statutes --model gemini-embedding-001
uv run python scripts/03_run_retrieval.py --dataset aila_statutes --model gemini-embedding-001 --mode dense

--mode also takes bm25 and hybrid; --condition and --generator select a rewrite. scripts/05_analyze.py and tools/transform_analysis.py take dataset names as positional arguments and default to chatdoctor curev1_en trec_covid.

Contributors

Languages

Python

97.5%

Shell

2.5%