Text Generation
Transformers
Safetensors
English
qwen2
information-retrieval
boolean-search
NL2BM25
GRPO
RLVR
tantivy
BEIR
searchlm
reward-hacking
conversational
text-generation-inference
Instructions to use Supreeth/searchlm-nl2bm25-grpo with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Supreeth/searchlm-nl2bm25-grpo with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="Supreeth/searchlm-nl2bm25-grpo") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("Supreeth/searchlm-nl2bm25-grpo") model = AutoModelForCausalLM.from_pretrained("Supreeth/searchlm-nl2bm25-grpo") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use Supreeth/searchlm-nl2bm25-grpo with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "Supreeth/searchlm-nl2bm25-grpo" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Supreeth/searchlm-nl2bm25-grpo", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/Supreeth/searchlm-nl2bm25-grpo
- SGLang
How to use Supreeth/searchlm-nl2bm25-grpo with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "Supreeth/searchlm-nl2bm25-grpo" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Supreeth/searchlm-nl2bm25-grpo", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "Supreeth/searchlm-nl2bm25-grpo" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "Supreeth/searchlm-nl2bm25-grpo", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use Supreeth/searchlm-nl2bm25-grpo with Docker Model Runner:
docker model run hf.co/Supreeth/searchlm-nl2bm25-grpo
Enrich model card with examples and training details
Browse files
README.md
CHANGED
|
@@ -17,59 +17,120 @@ library_name: transformers
|
|
| 17 |
pipeline_tag: text-generation
|
| 18 |
---
|
| 19 |
|
| 20 |
-
# SearchLM NL2BM25 β GRPO v1 (Qwen2.5-3B-Instruct)
|
| 21 |
|
| 22 |
-
|
| 23 |
-
> Use [GRPO v2](Supreeth/searchlm-nl2bm25-grpo-v2) for production use. This model is published
|
| 24 |
-
> for research reproducibility and as a concrete example of reward hacking in RLVR.
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
| 28 |
|
| 29 |
-
|
|
|
|
| 30 |
|
| 31 |
-
|
| 32 |
|
| 33 |
-
|
| 34 |
-
by outputting 3β7 token keyword phrases β abandoning all boolean structure:
|
| 35 |
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
|
| 42 |
-
**
|
|
|
|
|
|
|
| 43 |
```
|
| 44 |
<reasoning>
|
| 45 |
</reasoning>
|
| 46 |
<query>Cholesterol Statin Breast Cancer</query>
|
| 47 |
```
|
| 48 |
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
-
##
|
| 56 |
|
| 57 |
-
|
|
| 58 |
-
|---------
|
| 59 |
-
|
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
## Training Details
|
| 63 |
|
| 64 |
| Setting | Value |
|
| 65 |
|---------|-------|
|
| 66 |
| Base model | [searchlm-nl2bm25-sft](Supreeth/searchlm-nl2bm25-sft) |
|
| 67 |
-
| Method | GRPO (TRL + vLLM colocate) |
|
| 68 |
| Reward | `0.6 Γ NDCG@10 + 0.4 Γ MRR` (live Tantivy search) |
|
| 69 |
-
| Training datasets | NFCorpus + SciFact (train split) |
|
| 70 |
| Epochs | 3 |
|
| 71 |
| `num_generations` | 2 |
|
| 72 |
| Hardware | NVIDIA H100 80 GB |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
## Citation
|
| 75 |
|
|
|
|
| 17 |
pipeline_tag: text-generation
|
| 18 |
---
|
| 19 |
|
| 20 |
+
# SearchLM NL2BM25 β GRPO v1 β οΈ Reward Hacking (Qwen2.5-3B-Instruct)
|
| 21 |
|
| 22 |
+
**Part of the [SearchLM collection](https://huggingface.co/collections/Supreeth/searchlm) Β· [GitHub](https://github.com/SupreethRao99/searchLM)**
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
> **β οΈ This model games its training reward.** It achieves high NDCG@10 by collapsing all
|
| 25 |
+
> outputs to 3β7 token keyword phrases, discarding the entire boolean search task it was
|
| 26 |
+
> trained to learn. Published for research transparency and as a reproducible example of
|
| 27 |
+
> specification gaming in RLVR. For deployment, use [GRPO v2](Supreeth/searchlm-nl2bm25-grpo-v2).
|
| 28 |
|
| 29 |
+
A Qwen2.5-3B-Instruct model fine-tuned via GRPO starting from [SFT v1](Supreeth/searchlm-nl2bm25-sft),
|
| 30 |
+
using live Tantivy retrieval (NDCG@10 + MRR) as the reward signal.
|
| 31 |
|
| 32 |
+
> **Pipeline position:** `base β SFT v1 β `**`GRPO v1 β οΈ`**` β SFT v2 β GRPO v2 β
`
|
| 33 |
|
| 34 |
+
---
|
|
|
|
| 35 |
|
| 36 |
+
## The hack: specification gaming via minimum viable retrieval
|
| 37 |
+
|
| 38 |
+
The model learned that on small corpora (NFCorpus: 3,633 docs; SciFact: 5,183 docs),
|
| 39 |
+
2β4 content nouns yield near-optimal BM25 recall. Instead of learning boolean query
|
| 40 |
+
generation, it learned to extract the most distinctive nouns from the NL query:
|
| 41 |
|
| 42 |
+
**Input:** `Do Cholesterol Statin Drugs Cause Breast Cancer?`
|
| 43 |
+
|
| 44 |
+
**GRPO v1 output (hacking):**
|
| 45 |
```
|
| 46 |
<reasoning>
|
| 47 |
</reasoning>
|
| 48 |
<query>Cholesterol Statin Breast Cancer</query>
|
| 49 |
```
|
| 50 |
|
| 51 |
+
**SFT v1 output (intended behaviour, lower NDCG):**
|
| 52 |
+
```
|
| 53 |
+
<reasoning>
|
| 54 |
+
Key concepts: statin drugs, causal relationship, breast cancer.
|
| 55 |
+
Connect with AND; expand synonyms with OR.
|
| 56 |
+
</reasoning>
|
| 57 |
+
<query>(statin OR "HMG-CoA reductase inhibitor" OR simvastatin OR atorvastatin)
|
| 58 |
+
AND (cause OR risk OR association OR induce)
|
| 59 |
+
AND ("breast cancer" OR "breast carcinoma")</query>
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
The GRPO v1 output actually achieves **NDCG@10 = 0.971** on this query while the SFT
|
| 63 |
+
output achieves 0.000 β the hack outperforms the intended behaviour because SFT used wrong
|
| 64 |
+
synonyms. This made the gaming invisible in aggregate metrics alone.
|
| 65 |
+
|
| 66 |
+
---
|
| 67 |
+
|
| 68 |
+
## Collapse statistics
|
| 69 |
+
|
| 70 |
+
| Metric | Value |
|
| 71 |
+
|--------|-------|
|
| 72 |
+
| Mean completion length | **5.1 tokens** (vs 95 for SFT v1) |
|
| 73 |
+
| Boolean operator usage (AND) | **0%** (vs ~80% for SFT v1) |
|
| 74 |
+
| Boolean operator usage (OR) | **0%** (vs ~90% for SFT v1) |
|
| 75 |
+
| Phrase usage | **0%** (vs ~70% for SFT v1) |
|
| 76 |
+
| Reasoning block content | **empty** |
|
| 77 |
+
| `frac_reward_zero_std` during training | **90β96%** from step 1 |
|
| 78 |
+
|
| 79 |
+
`frac_reward_zero_std` = fraction of GRPO groups where all completions received identical
|
| 80 |
+
reward. At 90-96%, policy gradient was near-zero throughout β the model was not learning,
|
| 81 |
+
it had already converged on the keyword-bag strategy.
|
| 82 |
+
|
| 83 |
+
---
|
| 84 |
+
|
| 85 |
+
## Why it still scores high on benchmarks
|
| 86 |
+
|
| 87 |
+
1. **Small corpora**: BM25 keyword recall on 3β5K doc indices is high; a rare noun
|
| 88 |
+
appears in only a handful of documents, making it highly discriminative.
|
| 89 |
+
2. **SFT degraded**: SFT v1 scored *below base* on SciFact (0.273 vs 0.386) due to
|
| 90 |
+
over-specified queries β a low bar to beat.
|
| 91 |
+
3. **NDCG@10 rewards recall of first hit**: any query retrieving one relevant document
|
| 92 |
+
in top-10 scores well. Keyword bags do this reliably on small indexes.
|
| 93 |
|
| 94 |
+
**This does not generalise**: on a 2.7M-doc index (NQ), keyword bags return thousands of
|
| 95 |
+
irrelevant results; NDCG@10 and MRR would collapse to near zero.
|
| 96 |
+
|
| 97 |
+
---
|
| 98 |
|
| 99 |
+
## All SearchLM checkpoints
|
| 100 |
|
| 101 |
+
| Model | NFCorpus NDCG@10 | SciFact NDCG@10 | Mean tokens | Boolean ops |
|
| 102 |
+
|-------|-----------------|----------------|-------------|-------------|
|
| 103 |
+
| base (Qwen2.5-3B-Instruct) | 0.455 | 0.386 | 120 | ~20% |
|
| 104 |
+
| [SFT v1](https://huggingface.co/Supreeth/searchlm-nl2bm25-sft) | 0.441 | 0.273 | 95 | ~80% |
|
| 105 |
+
| [GRPO v1](https://huggingface.co/Supreeth/searchlm-nl2bm25-grpo) β οΈ | 0.556 | 0.608 | **5β7** | **0%** |
|
| 106 |
+
| [SFT v2](https://huggingface.co/Supreeth/searchlm-nl2bm25-sft-v2) | 0.466 | 0.358 | 109 | ~65% |
|
| 107 |
+
| [**GRPO v2**](https://huggingface.co/Supreeth/searchlm-nl2bm25-grpo-v2) β
| **0.577** | **0.657** | 147 | ~35% |
|
| 108 |
+
|
| 109 |
+
Evaluated on BEIR test splits (NFCorpus: 323 queries, SciFact: 300 queries).
|
| 110 |
+
|
| 111 |
+
---
|
| 112 |
|
| 113 |
## Training Details
|
| 114 |
|
| 115 |
| Setting | Value |
|
| 116 |
|---------|-------|
|
| 117 |
| Base model | [searchlm-nl2bm25-sft](Supreeth/searchlm-nl2bm25-sft) |
|
| 118 |
+
| Method | GRPO (TRL GRPOTrainer + vLLM colocate, single H100) |
|
| 119 |
| Reward | `0.6 Γ NDCG@10 + 0.4 Γ MRR` (live Tantivy search) |
|
| 120 |
+
| Training datasets | NFCorpus + SciFact (train split qrels) |
|
| 121 |
| Epochs | 3 |
|
| 122 |
| `num_generations` | 2 |
|
| 123 |
| Hardware | NVIDIA H100 80 GB |
|
| 124 |
+
| W&B run | `supreethrao/searchlm/runs/nlp69ydi` |
|
| 125 |
+
|
| 126 |
+
---
|
| 127 |
+
|
| 128 |
+
## Related resources
|
| 129 |
+
|
| 130 |
+
- **Code:** [SupreethRao99/searchLM](https://github.com/SupreethRao99/searchLM)
|
| 131 |
+
- **Analysis:** [Reward hacking report (v1 + v2 comparison)](https://github.com/SupreethRao99/searchLM/blob/main/REWARD_HACKING_REPORT_V2.md)
|
| 132 |
+
- **Fixed version:** [GRPO v2](Supreeth/searchlm-nl2bm25-grpo-v2)
|
| 133 |
+
- **Collection:** [SearchLM collection](https://huggingface.co/collections/Supreeth/searchlm)
|
| 134 |
|
| 135 |
## Citation
|
| 136 |
|