File size: 4,388 Bytes
f4c1149
0ce44e7
 
f4c1149
 
 
0ce44e7
 
 
 
 
 
 
 
 
f4c1149
 
0ce44e7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f4c1149
0ce44e7
 
 
 
 
f4c1149
0ce44e7
f4c1149
0ce44e7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
---
base_model: Qwen/Qwen2.5-0.5B-Instruct
library_name: peft
license: apache-2.0
language:
- en
pipeline_tag: text-generation
tags:
- text-to-sql
- sql
- grpo
- reinforcement-learning
- lora
- trl
- unsloth
---

# SQL-GRPO 0.5B

A LoRA adapter for **Qwen2.5-0.5B-Instruct**, trained with **GRPO** (Group Relative Policy Optimization) to turn natural-language questions into SQLite queries. The reward comes from **executing the generated SQL** against the real database: no human-labeled feedback, the database is the judge.

🚀 **[Live demo](https://huggingface.co/spaces/bimal2004/sql-grpo-demo)** (uses the 1.5B version) · 💻 **[Code](https://github.com/bimal1023/sql-grpo)** · 🔗 **[1.5B version](https://huggingface.co/bimal2004/sql-grpo-1.5b)**

## Results

Spider dev set (1,034 questions on databases not seen during training), execution accuracy:

| Model | Accuracy | Valid SQL | Correct format |
| --- | --- | --- | --- |
| Qwen2.5-0.5B-Instruct (untrained) | 18.18% | 35.40% | 66.73% |
| **This model (GRPO)** | **41.68%** | **73.21%** | **99.81%** |
| Qwen2.5-1.5B-Instruct (untrained, for reference) | 40.72% | 58.41% | 76.89% |
| gpt-4.1-mini (prompted, for reference) | 74.37% | 98.74% | 100.00% |

GRPO more than doubled accuracy (2.3×); the trained 0.5B model outperforms the untrained 1.5B model, which is 3× its size. The gain isn't only formatting: among well-formatted answers, correctness rose from about 27% to about 42%.

## How to use

```python
import re
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel

base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct", torch_dtype="auto")
model = PeftModel.from_pretrained(base, "bimal2004/sql-grpo-0.5b")
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B-Instruct")

schema = """CREATE TABLE singer (
  Singer_ID int, Name text, Country text, Age int,
  PRIMARY KEY (Singer_ID)
)"""
question = "How many singers are from France?"

messages = [
    {"role": "system", "content": (
        "You are a SQLite expert. Given a database schema and a question, "
        "write one SQLite query that answers it. "
        "Put only the query inside <sql></sql> tags.")},
    {"role": "user", "content": f"Schema:\n{schema}\n\nQuestion: {question}"},
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=256, do_sample=False)
answer = tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)

sql = re.search(r"<sql>(.*?)</sql>", answer, re.DOTALL).group(1).strip()
print(sql)
```

**Prompt format matters:** the model was trained with exactly this system prompt, with the schema given as `CREATE TABLE` statements, and answers inside `<sql></sql>` tags.

At 0.5B parameters, this model is small enough to run on a laptop CPU.

## Training details

- **Method:** GRPO via Hugging Face TRL `GRPOTrainer` + Unsloth, LoRA rank 32 (about 3.4% of parameters trained)
- **Data:** Spider train split (6,289 questions after filtering very long schemas)
- **Reward:** +1.0 if the query returns the same rows as the gold SQL, +0.2 if it runs without error, +0.1 for correct `<sql>` formatting, −0.1 for overly long output. Queries run on a read-only connection with a 2-second timeout.
- **Setup:** 400 steps (~2 hours), 8 sampled answers per question, learning rate 5e-6, on a single free Kaggle T4 GPU

## Limitations

- Trained and evaluated only on **Spider** (SQLite); performance on other SQL dialects or very large real-world schemas is untested.
- Accuracy is about 42%: most complex questions (JOINs, nested queries) are still answered incorrectly. For better accuracy, use the [1.5B version](https://huggingface.co/bimal2004/sql-grpo-1.5b) (57.74%).
- Common errors include referencing columns that don't exist and missing JOINs.
- Some correct answers on borderline questions can flip under different numerical precision or batching. Evaluate on many questions, not single examples.
- Always review generated SQL before running it on important data.

## Credits

Built by [Bimal Kumal](https://bimalkumal7.com.np). Base model: [Qwen2.5-0.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct). Data: [Spider](https://github.com/taoyds/spider) (Yu et al., 2018).