This repository contains the official implementation for our EMNLP 2026 paper:
Group-Aware Adaptive Retrieval for Evidence Navigation June Park*, Jun Kwon*, Jonghyo Kim, Jongwuk Lee† (* : equal contribution) Sungkyunkwan University, Republic of Korea
Official paper: arXiv:2609.02188
Reasoning-intensive retrieval addresses queries whose relevance cannot be identified by surface-level matching, thereby requiring multi-step reasoning. Because relevant documents rarely appear in the initial candidate set, retrieval systems suffer from the bounded recall problem. Existing methods iteratively expand a candidate pool at the document level over a corpus graph, examining each neighbor in isolation and drifting toward a narrow region of the corpus. To address this problem, we propose Group-Aware Adaptive Retrieval for Evidence Navigation (GAREN), which explores the corpus graph through group-level expansion. GAREN organizes documents into semantically coherent and distinguishable groups based on their connections in the corpus graph. The information in each group indicates what can be accessed by expanding through it, providing guidance beyond individual document-level signals. At each iteration, GAREN uses a group-level navigator to identify promising expansion directions, retrieves documents from the selected groups, and applies a document-level Reranker to evaluate the updated candidate set. Extensive experiments show that GAREN achieves up to 8.0% improvement over the strongest baseline on BRIGHT.
| Component | Role | Model |
|---|---|---|
| Reranker | Listwise document reranking over the current window (Step 1) | Qwen/Qwen3-Next-80B-A3B-Instruct-FP8 |
| Navigator | Pointwise group scoring that picks expansion directions (Step 2) | Qwen/Qwen3-Reranker-4B |
| Evidence Propagation | Cluster-coherent post-hoc rerank; lifts documents sharing a group with high-ranked evidence | — |
At each iteration the Navigator scores the top-K_g voted groups, GAREN pulls documents from
the selected groups into the next window, and the Reranker re-evaluates it. The candidate
picking policy follows an explore → exploit schedule: early iterations spread the expansion
budget across groups (breadth-first), and after --pick_transition iterations it concentrates
on the highest-scoring groups (depth-first).
conda env create -f environment.yaml
conda activate GAREN
The group construction stage additionally needs graspologic (Leiden community detection) and
faiss (exact-cosine k-NN):
conda install -c conda-forge graspologic faiss-gpu
GAREN runs in two stages: (A) build the group structure once per corpus, then (B) run retrieval. Both stages talk to vLLM servers over an OpenAI-compatible API.
# Reranker (Step 1) — Qwen3-Next-80B on GPUs 0,1, port 9201
bash bash/server/start_qwen3next80b_server.sh 0,1 9201
# Navigator (Step 2) — Qwen3-Reranker-4B /score endpoint on GPU 2, port 9202
GPUS=2 PORT=9202 bash bash/server/start_start_qwen3re4b.sh
The Navigator is served in sequence-classification mode (/score, /v1/rerank) via
--hf_overrides; the launch script sets this up.
# 1. Corpus → document embeddings → doc-doc k-NN graph (Qwen3-Embedding-4B)
bash bash/build_group/build_graph.sh
# 2. k-NN graph → Leiden L1 communities → LLM group summaries (needs the Reranker server)
bash bash/build_group/build_group.sh
# 3. graph + communities → L0↔L1 anchors
bash bash/build_group/build_anchor.sh
Each step writes into data/ and skips work that already exists (FORCE=1 to rebuild):
data/corpus/<task>.jsonl input corpus
data/embed/<task>_corpus_embs.pt document embeddings
data/GRAPH/qwen3/graph/<task>/ L0 doc-doc k-NN graph
data/GRAPH/qwen3/summary/<task>/ L1 communities + group summaries
data/anchor/<task>/{l0_l1_anchor,l1_doc_ids}.json L0↔L1 anchors
data/first_stage/bm25/ first-stage retrieval caches
If you already have a k-NN graph in this format, skip step 1.
# Default: BM25 + original queries, all 12 BRIGHT categories
bash bash/run_ours.sh
# A subset of tasks
TASKS="biology earth_science" bash bash/run_ours.sh
# A different first-stage retriever / prompt
RETRIEVER=reasonir PROMPT_MODE=reasoning_and_ranking bash bash/run_ours.sh
Results land in results/main_table_<model>_<prompt>/ours_<navigator>_<retriever>_<query_type>/<task>/.
ABL=eval_neigh bash bash/run_ours_ablation.sh # score graph neighbours, no groups
ABL=explore_full bash bash/run_ours_ablation.sh # explore every iteration
ABL=exploit_full bash bash/run_ours_ablation.sh # exploit every iteration
ABL=no_page_aware bash bash/run_ours_ablation.sh # w/o Evidence Propagation
ABL=topk10 bash bash/run_ours_ablation.sh # Navigator budget K_g = 10
ABL=topk30 bash bash/run_ours_ablation.sh # Navigator budget K_g = 30
The explore→exploit transition point is swept with PICK_TRANSITION:
PICK_TRANSITION=2 ABL=explore_then_exploit bash bash/run_ours_ablation.sh
Defaults match the main-table configuration; every knob is an environment variable for the
bash scripts and a CLI flag for python -m scripts.run.
| Parameter | Default | Description |
|---|---|---|
--n_iters | 9 | Expansion iterations |
--window_size | 20 | Reranker window size |
--top_keep | 10 | Documents carried over per iteration (expansion slots = 20 − 10) |
--top_k_groups | 20 | Navigator budget K_g: groups scored per iteration |
--top_k_docs | 1000 | First-stage candidate pool |
--pick_mode | explore_then_exploit | explore | exploit | explore_then_exploit |
--pick_transition | 4 | Iteration at which the schedule switches to exploit |
--max_dlen | 512 | Document truncation length |
--pa_p / --pa_alpha | prompt-mode specific | Evidence Propagation: RBP persistence / sibling-lift weight |
Evidence Propagation is on by default (--no_page_aware disables it). Its two weights
default per prompt mode: relevance → (p=0.60, α=0.01), reasoning_and_ranking → (p=0.50, α=0.01).
GAREN/
├── scripts/ # Retrieval pipeline
│ ├── run.py # Entry point (--task ours)
│ ├── parser.py # CLI arguments
│ ├── pipeline.py # run_ours: wiring, I/O, evaluation
│ ├── ours_pipeline.py # GAREN loop (voting, expansion, EvalNeigh ablation)
│ ├── reranker.py # Reranker — listwise document reranking (Step 1)
│ ├── navigator.py # Navigator — pointwise group scoring (Step 2)
│ ├── evidence_propagation.py # Cluster-coherent post-hoc rerank
│ └── llm.py / dataset.py # vLLM client, dataset wrappers
├── hier_community/ # Group construction (preprocessing)
│ ├── embed_corpus.py # Corpus → embeddings (Qwen3-Embedding-4B)
│ ├── build_knn_graph.py # Embeddings → doc-doc k-NN graph (faiss, exact cosine)
│ ├── build_hierarchy.py # Leiden communities + LLM group summaries
│ └── build_anchor.py # L0↔L1 anchors
├── bash/
│ ├── build_group/ # build_graph.sh · build_group.sh · build_anchor.sh
│ ├── server/ # vLLM launch scripts
│ ├── run_ours.sh # Main runner
│ └── run_ours_ablation.sh # Ablation sweeps
├── utils/ # Prompts and shared helpers
└── environment.yaml
All preprocessed artifacts are released on the Hub:
Jun421/GAREN-data (6.7 GB).
hf download Jun421/GAREN-data --repo-type=dataset --local-dir data/
This gives you everything the runners expect — chunked corpora, queries, BM25 first-stage
caches, L0 k-NN graphs, L1 group summaries, and L0↔L1 anchors — so you can skip
bash/build_group/*.sh entirely and go straight to bash bash/run_ours.sh.
| Path | Description |
|---|---|
data/corpus/<task>.json | Chunked corpus (docno, content) |
data/qa_data/<task>.json | Queries with gold_ids, excluded_ids |
data/GRAPH/qwen3/graph/<task>/ | L0 doc–doc k-NN graph (k=16) |
data/GRAPH/qwen3/summary/<task>/ | L1 communities + group summaries |
data/anchor/<task>/ | l0_l1_anchor.json, l1_doc_ids.json |
data/first_stage/bm25/ | BM25 first-stage caches (top-1000) |
Covers all 12 BRIGHT categories: 1,333,166 documents, 1,384 queries, 121,349 L1 groups. The artifacts are derived from BRIGHT (Su et al., 2024) — please cite it alongside our paper.
If you find our work useful for your research, please cite our paper:
@misc{park2026groupawareadaptiveretrievalevidence,
title={Group-Aware Adaptive Retrieval for Evidence Navigation},
author={June Park and Jun Kwon and Jonghyo Kim and Jongwuk Lee},
year={2026},
eprint={2609.02188},
archivePrefix={arXiv},
primaryClass={cs.IR},
url={https://arxiv.org/abs/2609.02188},
}
This repository contains the official implementation for our EMNLP 2026 paper:
Group-Aware Adaptive Retrieval for Evidence Navigation June Park*, Jun Kwon*, Jonghyo Kim, Jongwuk Lee† (* : equal contribution) Sungkyunkwan University, Republic of Korea
Official paper: arXiv:2609.02188
Reasoning-intensive retrieval addresses queries whose relevance cannot be identified by surface-level matching, thereby requiring multi-step reasoning. Because relevant documents rarely appear in the initial candidate set, retrieval systems suffer from the bounded recall problem. Existing methods iteratively expand a candidate pool at the document level over a corpus graph, examining each neighbor in isolation and drifting toward a narrow region of the corpus. To address this problem, we propose Group-Aware Adaptive Retrieval for Evidence Navigation (GAREN), which explores the corpus graph through group-level expansion. GAREN organizes documents into semantically coherent and distinguishable groups based on their connections in the corpus graph. The information in each group indicates what can be accessed by expanding through it, providing guidance beyond individual document-level signals. At each iteration, GAREN uses a group-level navigator to identify promising expansion directions, retrieves documents from the selected groups, and applies a document-level Reranker to evaluate the updated candidate set. Extensive experiments show that GAREN achieves up to 8.0% improvement over the strongest baseline on BRIGHT.
| Component | Role | Model |
|---|---|---|
| Reranker | Listwise document reranking over the current window (Step 1) | Qwen/Qwen3-Next-80B-A3B-Instruct-FP8 |
| Navigator | Pointwise group scoring that picks expansion directions (Step 2) | Qwen/Qwen3-Reranker-4B |
| Evidence Propagation | Cluster-coherent post-hoc rerank; lifts documents sharing a group with high-ranked evidence | — |
At each iteration the Navigator scores the top-K_g voted groups, GAREN pulls documents from
the selected groups into the next window, and the Reranker re-evaluates it. The candidate
picking policy follows an explore → exploit schedule: early iterations spread the expansion
budget across groups (breadth-first), and after --pick_transition iterations it concentrates
on the highest-scoring groups (depth-first).
conda env create -f environment.yaml
conda activate GAREN
The group construction stage additionally needs graspologic (Leiden community detection) and
faiss (exact-cosine k-NN):
conda install -c conda-forge graspologic faiss-gpu
GAREN runs in two stages: (A) build the group structure once per corpus, then (B) run retrieval. Both stages talk to vLLM servers over an OpenAI-compatible API.
# Reranker (Step 1) — Qwen3-Next-80B on GPUs 0,1, port 9201
bash bash/server/start_qwen3next80b_server.sh 0,1 9201
# Navigator (Step 2) — Qwen3-Reranker-4B /score endpoint on GPU 2, port 9202
GPUS=2 PORT=9202 bash bash/server/start_start_qwen3re4b.sh
The Navigator is served in sequence-classification mode (/score, /v1/rerank) via
--hf_overrides; the launch script sets this up.
# 1. Corpus → document embeddings → doc-doc k-NN graph (Qwen3-Embedding-4B)
bash bash/build_group/build_graph.sh
# 2. k-NN graph → Leiden L1 communities → LLM group summaries (needs the Reranker server)
bash bash/build_group/build_group.sh
# 3. graph + communities → L0↔L1 anchors
bash bash/build_group/build_anchor.sh
Each step writes into data/ and skips work that already exists (FORCE=1 to rebuild):
data/corpus/<task>.jsonl input corpus
data/embed/<task>_corpus_embs.pt document embeddings
data/GRAPH/qwen3/graph/<task>/ L0 doc-doc k-NN graph
data/GRAPH/qwen3/summary/<task>/ L1 communities + group summaries
data/anchor/<task>/{l0_l1_anchor,l1_doc_ids}.json L0↔L1 anchors
data/first_stage/bm25/ first-stage retrieval caches
If you already have a k-NN graph in this format, skip step 1.
# Default: BM25 + original queries, all 12 BRIGHT categories
bash bash/run_ours.sh
# A subset of tasks
TASKS="biology earth_science" bash bash/run_ours.sh
# A different first-stage retriever / prompt
RETRIEVER=reasonir PROMPT_MODE=reasoning_and_ranking bash bash/run_ours.sh
Results land in results/main_table_<model>_<prompt>/ours_<navigator>_<retriever>_<query_type>/<task>/.
ABL=eval_neigh bash bash/run_ours_ablation.sh # score graph neighbours, no groups
ABL=explore_full bash bash/run_ours_ablation.sh # explore every iteration
ABL=exploit_full bash bash/run_ours_ablation.sh # exploit every iteration
ABL=no_page_aware bash bash/run_ours_ablation.sh # w/o Evidence Propagation
ABL=topk10 bash bash/run_ours_ablation.sh # Navigator budget K_g = 10
ABL=topk30 bash bash/run_ours_ablation.sh # Navigator budget K_g = 30
The explore→exploit transition point is swept with PICK_TRANSITION:
PICK_TRANSITION=2 ABL=explore_then_exploit bash bash/run_ours_ablation.sh
Defaults match the main-table configuration; every knob is an environment variable for the
bash scripts and a CLI flag for python -m scripts.run.
| Parameter | Default | Description |
|---|---|---|
--n_iters | 9 | Expansion iterations |
--window_size | 20 | Reranker window size |
--top_keep | 10 | Documents carried over per iteration (expansion slots = 20 − 10) |
--top_k_groups | 20 | Navigator budget K_g: groups scored per iteration |
--top_k_docs | 1000 | First-stage candidate pool |
--pick_mode | explore_then_exploit | explore | exploit | explore_then_exploit |
--pick_transition | 4 | Iteration at which the schedule switches to exploit |
--max_dlen | 512 | Document truncation length |
--pa_p / --pa_alpha | prompt-mode specific | Evidence Propagation: RBP persistence / sibling-lift weight |
Evidence Propagation is on by default (--no_page_aware disables it). Its two weights
default per prompt mode: relevance → (p=0.60, α=0.01), reasoning_and_ranking → (p=0.50, α=0.01).
GAREN/
├── scripts/ # Retrieval pipeline
│ ├── run.py # Entry point (--task ours)
│ ├── parser.py # CLI arguments
│ ├── pipeline.py # run_ours: wiring, I/O, evaluation
│ ├── ours_pipeline.py # GAREN loop (voting, expansion, EvalNeigh ablation)
│ ├── reranker.py # Reranker — listwise document reranking (Step 1)
│ ├── navigator.py # Navigator — pointwise group scoring (Step 2)
│ ├── evidence_propagation.py # Cluster-coherent post-hoc rerank
│ └── llm.py / dataset.py # vLLM client, dataset wrappers
├── hier_community/ # Group construction (preprocessing)
│ ├── embed_corpus.py # Corpus → embeddings (Qwen3-Embedding-4B)
│ ├── build_knn_graph.py # Embeddings → doc-doc k-NN graph (faiss, exact cosine)
│ ├── build_hierarchy.py # Leiden communities + LLM group summaries
│ └── build_anchor.py # L0↔L1 anchors
├── bash/
│ ├── build_group/ # build_graph.sh · build_group.sh · build_anchor.sh
│ ├── server/ # vLLM launch scripts
│ ├── run_ours.sh # Main runner
│ └── run_ours_ablation.sh # Ablation sweeps
├── utils/ # Prompts and shared helpers
└── environment.yaml
All preprocessed artifacts are released on the Hub:
Jun421/GAREN-data (6.7 GB).
hf download Jun421/GAREN-data --repo-type=dataset --local-dir data/
This gives you everything the runners expect — chunked corpora, queries, BM25 first-stage
caches, L0 k-NN graphs, L1 group summaries, and L0↔L1 anchors — so you can skip
bash/build_group/*.sh entirely and go straight to bash bash/run_ours.sh.
| Path | Description |
|---|---|
data/corpus/<task>.json | Chunked corpus (docno, content) |
data/qa_data/<task>.json | Queries with gold_ids, excluded_ids |
data/GRAPH/qwen3/graph/<task>/ | L0 doc–doc k-NN graph (k=16) |
data/GRAPH/qwen3/summary/<task>/ | L1 communities + group summaries |
data/anchor/<task>/ | l0_l1_anchor.json, l1_doc_ids.json |
data/first_stage/bm25/ | BM25 first-stage caches (top-1000) |
Covers all 12 BRIGHT categories: 1,333,166 documents, 1,384 queries, 121,349 L1 groups. The artifacts are derived from BRIGHT (Su et al., 2024) — please cite it alongside our paper.
If you find our work useful for your research, please cite our paper:
@misc{park2026groupawareadaptiveretrievalevidence,
title={Group-Aware Adaptive Retrieval for Evidence Navigation},
author={June Park and Jun Kwon and Jonghyo Kim and Jongwuk Lee},
year={2026},
eprint={2609.02188},
archivePrefix={arXiv},
primaryClass={cs.IR},
url={https://arxiv.org/abs/2609.02188},
}