Qwen2.5-1.5B text-to-SQL (QLoRA adapter)
This is a LoRA adapter for Qwen2.5-1.5B-Instruct that I trained to write SQL from a table schema and a plain-English question. I built it as a learning project to go through the full fine-tuning cycle: preparing data, training, measuring before and after, and publishing.
Code and training notebook: github.com/PratikshaMahajan15/text2sql-finetune
Results
I tested on 200 questions that were not used in training. A prediction counts as correct if it matches the reference SQL after light cleanup (lowercase, extra whitespace removed, double quotes turned into single quotes, markdown fences and trailing semicolons stripped).
Table with columns: Model, Exact-match accuracy| Model | Exact-match accuracy |
|---|
| Qwen2.5-1.5B-Instruct (base) | 46.0% |
| Base + this adapter | 68.0% |
Most of the base model's misses come from formatting, such as wrapping the query in a markdown block. The adapter mainly teaches the model to output only the SQL in the style of the dataset.
How it was trained
- Data: 2,000 random rows from
b-mc2/sql-create-context (seed 42), split into 1,800 for training and 200 for testing
- Method: QLoRA with a 4-bit base model, using
peft and trl's SFTTrainer
- LoRA settings: r=16, alpha=32, dropout 0.05, applied to all linear layers
- Training: 2 epochs, learning rate 2e-4 with a cosine schedule, batch size 4 with 4 gradient accumulation steps, max length 512, fp16
- Hardware: one Tesla T4 on Kaggle, about 8.5 minutes
- Prompt: a system message, then the schema and the question; the answer is only the SQL
Usage
import torchfrom transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfigfrom peft import PeftModel base_id = "Qwen/Qwen2.5-1.5B-Instruct"adapter_id = "PratikshaMahajan/qwen2.5-1.5b-text2sql-qlora" tok = AutoTokenizer.from_pretrained(base_id)bnb = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.float16)model = AutoModelForCausalLM.from_pretrained(base_id, quantization_config=bnb, device_map="auto")model = PeftModel.from_pretrained(model, adapter_id) messages = [ {"role": "system", "content": "You are an expert SQL writer. Given a table schema and a question, reply with only the SQL query."}, {"role": "user", "content": "Schema:\nCREATE TABLE head (age INTEGER)\n\nQuestion: How many heads are older than 56?"},]prompt = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)inputs = tok(prompt, return_tensors="pt").to(model.device)out = model.generate(**inputs, max_new_tokens=128, do_sample=False)print(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
Limitations
- The score is exact match, so a correct query written differently (another column order, an alias) is counted as wrong. I did not run the queries against a database, so the real accuracy is probably higher.
- The training data is mostly single-table questions with short schemas, so joins and nested queries are weak.
- The test set is only 200 questions, and I have not tried it on real company schemas.
Credits
Base model: Qwen2.5-1.5B-Instruct. Dataset: b-mc2/sql-create-context, which is built from WikiSQL and Spider.