Skip to content

Commit dd92326

Browse files
committed
paper: refresh experiments and submission artifacts
1 parent 3fc48ce commit dd92326

171 files changed

Lines changed: 22411 additions & 44389 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

submission/README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ In this study, semantic chunks produced from long documents are modeled as knaps
1414

1515
The selection task is formulated as a 0/1 Knapsack Problem. The exact dynamic programming solution is compared with heuristic or retrieval-oriented approaches such as top-k, budget-aware greedy selection, MMR, and prompt-compression baselines such as LLMLingua-2 in the QASPER experiments.
1616

17-
The current scoring taxonomy is intentionally separated into baseline profiles (`cosine`, `hybrid`), the default evidence-selection profile (`evidence-hybrid`), a budget-stressed profile (`knapsack-aware`), a related-work proxy profile (`budgetmem-style`), and experimental profiles (`query-support`, `decision-aware`, `instruction-ami`). The `budgetmem-style` profile is an approximate feature-family baseline, not a reproduction of BudgetMem's learned policy. The `query-support` profile is general query/instruction-aware scoring and does not use LongBench-specific answer-option features. The `decision-aware` profile is for tasks with explicit candidate answers or decisions, and scores whether a chunk helps discriminate among candidates.
17+
The default chunker is structure-aware and semantic-aware: it preserves file, section, content-type, and code-symbol boundaries, while using adjacent block embedding similarity to split topic shifts inside compatible document sections. The production scoring path is intentionally narrow: `evidence-hybrid` is the only selectable scoring profile. Older profiles (`cosine`, `hybrid`, `knapsack-aware`, `budgetmem-style`, `query-support`, `decision-aware`) remain in `tokenpack.scoring_experimental` for ablation and historical comparison, not for default runs.
1818

19-
The selector taxonomy is similarly conservative: `knapsack-redundancy` remains the main TokenPack selector used in the paper, while `knapsack-coverage` is an experimental grounded-generation ablation that favors complementary query coverage after redundancy adjustment.
19+
The selector taxonomy is similarly conservative: `budget-top-k` is now the main TokenPack selector used in the paper. In the paper text this is called hybrid-greedy because it combines evidence-hybrid scoring with a budget-feasible greedy fill. `knapsack`, `knapsack-redundancy`, and `knapsack-coverage` remain as algorithmic baselines and historical ablations.
2020

2121
## Folder Structure
2222

@@ -36,8 +36,6 @@ The selector taxonomy is similarly conservative: `knapsack-redundancy` remains t
3636
- `results/knapsack_summary_table.tex`: LaTeX table used in the paper.
3737
- `results/knapsack_timeout_table.tex`: DP scalability table used in the paper.
3838
- `results/figures/*.png`: Runtime scaling, approximation gap, and DP scalability plots generated by the experiment script.
39-
- `gold/candidate_gold.jsonl`: Auto-proposed evidence dataset that is ready for human review, but should not be treated as fully validated gold evidence.
40-
- `gold/README.md`: Human review instructions for the candidate evidence dataset.
4139
- `source_code_manifest.md`: Explains where the main source code is located and how to run it.
4240

4341
## Quick Experiment Run
@@ -61,15 +59,15 @@ python -m pytest -p no:cacheprovider
6159
QASPER selector ablation, using a locally downloaded converted parquet file:
6260

6361
```powershell
64-
python submission\experiments\qasper_selector_eval.py --data-file C:\tmp\qasper-validation.parquet --backend hash --max-papers 40 --max-questions 200 --budget-ratios 0.05,0.10,0.20 --output-dir submission\results\qasper
62+
python submission\experiments\qasper_selector_eval.py --data-file C:\tmp\qasper-validation.parquet --max-papers 40 --max-questions 200 --budget-ratios 0.05,0.10,0.20 --output-dir submission\results\qasper
6563
```
6664

6765
If `--data-file` is omitted, the script tries to read the converted QASPER parquet URL from Hugging Face. A local parquet file is more reliable on restricted networks.
6866

6967
QASPER cost-quality proxy:
7068

7169
```powershell
72-
python submission\experiments\qasper_cost_quality_curve.py --data-file C:\tmp\qasper-validation.parquet --backend hash --chunkers semantic-threshold --scorings hybrid --strategies budget-top-k,greedy-density,knapsack --budget-ratios 0.20,0.40,0.60,0.80,1.00 --candidate-pool 10000 --output-dir submission\results\qasper_cost_quality_widepool
70+
python submission\experiments\qasper_cost_quality_curve.py --data-file C:\tmp\qasper-validation.parquet --chunkers structure-aware --scorings evidence-hybrid --strategies production-rag,budget-top-k,greedy-density,knapsack,knapsack-redundancy --budget-ratios 0.50,0.70,0.80,1.00 --candidate-pool 300 --chunk-size-preset low-budget --output-dir submission\results\qasper_cost_quality_hybrid_greedy_rerun
7371
```
7472

7573
## Building the LaTeX PDF

submission/TokenPack-paper.pdf

114 KB
Binary file not shown.

submission/experiments/build_qa_review_packet.py

Lines changed: 0 additions & 167 deletions
This file was deleted.

submission/experiments/chunking_ablation.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
if str(SRC) not in sys.path:
1616
sys.path.insert(0, str(SRC))
1717

18-
from tokenpack.chunking import ParagraphGroupChunker, SemanticThresholdChunker, StructureAwareChunker
18+
from tokenpack.chunking import SemanticThresholdChunker, StructureAwareChunker
1919
from tokenpack.embeddings import EmbeddingCache, make_embedder
2020
from tokenpack.index import ChunkIndex, save_index
2121
from tokenpack.loaders import iter_supported_files, load_text_blocks
@@ -28,7 +28,7 @@
2828
DEFAULT_SOURCE = ROOT / "resources"
2929
DEFAULT_OUTPUT_DIR = ROOT / "submission" / "results"
3030
DEFAULT_WORK_DIR = ROOT / ".tokenpack" / "chunking-ablation"
31-
CHUNKERS = ["paragraph", "semantic-threshold", "structure-aware"]
31+
CHUNKERS = ["semantic-threshold", "structure-aware"]
3232
TOKEN_RE = re.compile(r"[A-Za-z][A-Za-z-]{3,}")
3333
SENTENCE_RE = re.compile(r"(?<=[.!?])\s+")
3434
STOPWORDS = {
@@ -67,7 +67,6 @@ class EvidenceTemplate:
6767
def main() -> int:
6868
parser = argparse.ArgumentParser(description="Compare chunking strategies under the same knapsack solver.")
6969
parser.add_argument("--source", default=str(DEFAULT_SOURCE))
70-
parser.add_argument("--backend", default="hash", choices=["auto", "hash", "sentence-transformers"])
7170
parser.add_argument("--model", default="sentence-transformers/all-MiniLM-L6-v2")
7271
parser.add_argument("--budget-ratios", default="0.01,0.03,0.05")
7372
parser.add_argument("--budgets", help="Optional comma-separated absolute budgets; overrides --budget-ratios.")
@@ -95,7 +94,7 @@ def main() -> int:
9594
work_dir.mkdir(parents=True, exist_ok=True)
9695

9796
token_counter = TokenCounter()
98-
embedder = make_embedder(backend=args.backend, model_name=args.model, local_files_only=True)
97+
embedder = make_embedder(model_name=args.model, local_files_only=True)
9998
blocks = _load_experiment_blocks(
10099
Path(args.source),
101100
max_documents=args.max_documents,
@@ -239,10 +238,16 @@ def _build_index(
239238
token_counter: TokenCounter,
240239
) -> ChunkIndex:
241240
cache = EmbeddingCache(work_dir / f"{chunker_name}.embeddings.json")
242-
if chunker_name == "paragraph":
243-
chunker = ParagraphGroupChunker(target_tokens, min_tokens, max_tokens, token_counter=token_counter)
244-
elif chunker_name == "structure-aware":
245-
chunker = StructureAwareChunker(target_tokens, min_tokens, max_tokens, token_counter=token_counter)
241+
if chunker_name == "structure-aware":
242+
block_embeddings = cache.get_or_embed([block.text for block in blocks], embedder)
243+
chunker = StructureAwareChunker(
244+
target_tokens,
245+
min_tokens,
246+
max_tokens,
247+
token_counter=token_counter,
248+
block_embeddings=block_embeddings,
249+
semantic_threshold=semantic_threshold,
250+
)
246251
elif chunker_name == "semantic-threshold":
247252
block_embeddings = cache.get_or_embed([block.text for block in blocks], embedder)
248253
chunker = SemanticThresholdChunker(
@@ -299,6 +304,7 @@ def _evaluate_index(
299304
budget: int,
300305
candidate_pool: int,
301306
scoring: str,
307+
scorer=score_chunks,
302308
) -> dict[str, float]:
303309
totals = {
304310
"evidence_term_recall": 0.0,
@@ -310,7 +316,7 @@ def _evaluate_index(
310316
}
311317
for template in templates:
312318
query_embedding = embedder.embed([template.query])[0]
313-
scored = score_chunks(
319+
scored = scorer(
314320
query_embedding,
315321
index.chunks,
316322
index.embeddings,

submission/experiments/heterogeneity_advantage.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,8 @@ def main() -> int:
4141
parser.add_argument("--dataset", choices=["hotpotqa"], default="hotpotqa")
4242
parser.add_argument("--data-file", help="Optional local HotpotQA JSON/JSONL/Arrow file.")
4343
parser.add_argument("--split", default="validation", choices=["validation", "train"])
44-
parser.add_argument("--backend", default="hash", choices=["auto", "hash", "sentence-transformers"])
4544
parser.add_argument("--model", default="sentence-transformers/all-MiniLM-L6-v2")
46-
parser.add_argument("--chunker", choices=["paragraph", "semantic-threshold", "structure-aware"], default="paragraph")
45+
parser.add_argument("--chunker", choices=["semantic-threshold", "structure-aware"], default="structure-aware")
4746
parser.add_argument(
4847
"--scoring",
4948
choices=list(SCORING_PROFILES),
@@ -76,7 +75,7 @@ def main() -> int:
7675
work_dir.mkdir(parents=True, exist_ok=True)
7776

7877
token_counter = TokenCounter()
79-
embedder = make_embedder(backend=args.backend, model_name=args.model, local_files_only=True)
78+
embedder = make_embedder(model_name=args.model, local_files_only=True)
8079
chunk_size = resolve_chunk_size_config(
8180
args.chunk_size_preset,
8281
args.target_tokens,

submission/experiments/hotpotqa_selector_eval.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
DEFAULT_OUTPUT_DIR = ROOT / "submission" / "results" / "hotpotqa"
3636
DEFAULT_WORK_DIR = ROOT / ".tokenpack" / "hotpotqa"
37-
STRATEGIES = ["budget-top-k", "greedy-density", "knapsack", "knapsack-redundancy", "knapsack-augment"]
37+
STRATEGIES = ["production-rag", "budget-top-k", "greedy-density", "knapsack", "knapsack-redundancy", "knapsack-augment"]
3838
TOKEN_RE = re.compile(r"[A-Za-z][A-Za-z-]{2,}")
3939
STOPWORDS = {
4040
"and",
@@ -74,9 +74,8 @@ def main() -> int:
7474
parser = argparse.ArgumentParser(description="Evaluate selectors on HotpotQA supporting facts.")
7575
parser.add_argument("--data-file", help="Optional local HotpotQA JSON/JSONL file.")
7676
parser.add_argument("--split", default="validation", choices=["validation", "train"])
77-
parser.add_argument("--backend", default="hash", choices=["auto", "hash", "sentence-transformers"])
7877
parser.add_argument("--model", default="sentence-transformers/all-MiniLM-L6-v2")
79-
parser.add_argument("--chunker", choices=["paragraph", "semantic-threshold", "structure-aware"], default="paragraph")
78+
parser.add_argument("--chunker", choices=["semantic-threshold", "structure-aware"], default="structure-aware")
8079
parser.add_argument(
8180
"--scoring",
8281
choices=list(SCORING_PROFILES),
@@ -108,7 +107,7 @@ def main() -> int:
108107
work_dir.mkdir(parents=True, exist_ok=True)
109108

110109
token_counter = TokenCounter()
111-
embedder = make_embedder(backend=args.backend, model_name=args.model, local_files_only=True)
110+
embedder = make_embedder(model_name=args.model, local_files_only=True)
112111
chunk_size = resolve_chunk_size_config(
113112
args.chunk_size_preset,
114113
args.target_tokens,

0 commit comments

Comments
 (0)