IEEE Access · EnterpriseRAG-Bench artifacts

Vector retrieval drift under corpus growth

Dense Hit@k falls as an enterprise RAG corpus grows from 5k to 100k documents. Metadata still helps. The decline replicates on Amazon Titan Text Embeddings V2 — with an important HNSW vs exact-search caveat for reviewers.

Research goal

Enterprise RAG systems keep adding documents. Practitioners often assume dense retrieval quality stays roughly stable if the gold answer document remains in the index. This study asks whether that holds on a controlled enterprise bench, and what metadata can rescue.

  1. Measure drift. Hold a fixed primary-200 question bank and gold-pinned ladder; grow the distractor corpus from 5k → 100k (9 points) and track Hit@1 / Hit@5 / Hit@10 / MRR under raw dense search.
  2. Measure rescue. Compare the same ladder with lightweight metadata conditioning; report Δmeta and whether a collapse onset N★(τ = 0.10) appears on this bank.
  3. Replicate on a second embedder. Rerun the identical gold-pinned ladder with Amazon Titan Text Embeddings V2 and test whether endpoint decline (5k→100k) is negative for Hit@1, Hit@10, and MRR.
  4. Separate embedding drift from ANN error. Exact cosine controls show whether HNSW recall loss — not the embedder — drives apparent OpenAI–Titan gaps.

Protocol constants, seed 42, and headline results: STUDY_PROTOCOL.md. Threats: THREATS_TO_VALIDITY.md.

Primary findings (OpenAI, n = 200)

On text-embedding-3-small with HNSW (m = 16), raw dense Hit@1 falls 0.600 → 0.305 and Hit@10 0.795 → 0.510 as N grows from 5k to 100k. MRR falls 0.658 → 0.365. Metadata Hit@10 lift stays ≥ +0.13 from 10k–100k (N★(τ = 0.10) is undefined on this ladder; last Δmeta≥0.10 point is 100k).

N Hit@1 raw Hit@10 raw Hit@10 meta Δmeta
5k0.6000.7950.875+0.080
20k0.4100.6000.775+0.175
40k0.3500.5650.700+0.135
100k0.3050.5100.640+0.130

Log-linear fit for raw Hit@10: a − b·log(N) with a≈1.474, b≈0.086 (erb_full_primary200_to100k_fit.json. Promotion record: CANONICAL_METRICS.json.

Titan V2 — second-embedder replication

Same gold anchors, same scales, same primary-200 questions. Titan model: amazon.titan-embed-text-v2:0. Status: complete (2026-09-23). Raw Hit@1, Hit@10, and MRR all decline 5k→100k on both embedders (all_three_replicate = true).

Metric (raw) OpenAI 5k OpenAI 100k Δ Titan 5k Titan 100k Δ Rep?
Hit@1 0.6000.305−0.295 0.6200.385−0.235 yes
Hit@5 0.7400.460−0.280 0.7300.565−0.165 yes
Hit@10 0.7950.510−0.285 0.7850.610−0.175 yes
MRR 0.6580.365−0.293 0.6710.465−0.206 yes

Exact cosine vs HNSW (reviewer-critical)

On the deployed HNSW curves, Titan’s 5k→100k Hit@10 drop is milder than OpenAI’s (paired bootstrap B = 5000, seed 42: Titan−OpenAI drop ≈ +0.110, 95% CI [+0.040, +0.175]). Under exact cosine search that gap shrinks to ≈ +0.035 [−0.025, +0.100] — statistically indistinguishable.

Sources: openai_vs_titan_primary200.json, openai_vs_titan_bootstrap.json, exact_control_titan.json, TITAN_A8_STATUS.md.

Static JSON for reviewers

Everything below is served from this GitHub Pages site (no database required). Start with landing_summary.json for headline numbers, then drill into the comparison files.

FileWhat it contains
landing_summary.json Compact study goal, OpenAI headlines, Titan V2 endpoints, bootstrap, catalog
CANONICAL_METRICS.json Integrity-clean promotion record + Hit@10 fit coefficients
erb_full_primary200_to100k_fit.json OpenAI ladder fit + bootstrap CIs
openai_vs_titan_primary200.json Full OpenAI vs Titan ladder + drift replication flags
openai_vs_titan_bootstrap.json Paired bootstrap (B=5000) HNSW vs exact
exact_control_titan.json Titan exact cosine ≡ HNSW identity check
exact_control_mvp.json OpenAI exact cosine vs HNSW (ANN gap)
primary_questions_200.json Primary-200 question bank (seed 42)
paper_metrics_for_tex.json Numbers wired into the Access LaTeX draft
Verify UI + data/verification/ Per-query Hit@k, ranks, retrieved ids, chunk text (no DB)

Full multi-MB sweep dumps (erb_full_primary200_to100k.json, erb_titan_primary200_to100k.json) are included on Pages when present in the deploying clone. Embeddings live in the GitHub Release Postgres dump (~1 GB), not on this static site.

Reproduce (no re-embedding required)

Download the published Postgres dump, restore it, and re-run sweeps against frozen vectors. You do not need to re-embed 100k documents.

  1. Clone the repo and create .env from .env.example.
  2. Start Postgres + API: docker compose up -d --build vector-drift-postgres vector-drift-api
  3. Download erb_tables.dump.gz from the latest GitHub Release into data/backups/.
  4. Restore: ./scripts/erb/restore_from_backup.sh data/backups/erb_tables.dump.gz
  5. Validate: python3 scripts/erb/validate_study.py
  6. Optional OpenAI re-sweep: python /app/scripts/erb/run_scale_sweep.py --primary-questions … (see REPLICATE.md). Titan tables: document_chunks_titan / vector_drift_results_titan.

Step-by-step: REPLICATE.md. L4 audit (LLM-assisted + author spot-check): HUMAN_AUDIT.md.

Cite & links

@misc{peddapudi2026vectordrift,
  title  = {Vector Retrieval Drift under Corpus Growth: A Controlled Empirical
            Study with Metadata Filtering on EnterpriseRAG-Bench},
  author = {Peddapudi, Bhargava Chary},
  year   = {2026},
  note   = {Manuscript submitted to IEEE Access.
            Artifacts: https://pedapudibhargav.github.io/vector-drift-study/}
}