Usage
The system message holds the instructions and the schema text (the CREATE TABLE
statements with comments that list the exact spellings of string values); the user
message is the question. Generate with enable_thinking=False, which reproduces the
empty think block the model was trained with. The model writes one SQL query and
ends with <|endoftext|>, where the bundled generation config stops.
from huggingface_hub import hf_hub_downloadfrom transformers import AutoModelForCausalLM, AutoTokenizer repo = "RakhatM/qwen3-1.7b-kazakh-text-to-sql-dpo"tok = AutoTokenizer.from_pretrained(repo)model = AutoModelForCausalLM.from_pretrained(repo, torch_dtype="auto", device_map="auto") # The schema text of the database (here the Qazaqstan one from the dataset repo)schema = open(hf_hub_download("RakhatM/kazakh-text-to-sql", "schema.sql", repo_type="dataset")).read().strip()system = ("You translate questions written in Kazakh into SQLite queries for the database below.\n" "Reply with one SQL query and nothing else. String values must use the exact spellings " "given in the schema comments.\n\n" + schema)messages = [{"role": "system", "content": system}, {"role": "user", "content": "Қарағанды облысында қанша қала бар?"}]inputs = tok.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=False, return_tensors="pt", return_dict=True).to(model.device)out = model.generate(**inputs, max_new_tokens=256, do_sample=False)print(tok.decode(out[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True))# SELECT COUNT(*) FROM cities WHERE region_id = (SELECT id FROM regions WHERE name = 'Қарағанды облысы')
For the other databases of the dataset use db/aux/<name>.schema.sql; for your own,
the same kind of commented schema. Run generated SQL read-only: sqlutil.py in the
dataset repo does that and scores queries by execution match.
With vLLM, through the OpenAI-compatible API:
vllm serve RakhatM/qwen3-1.7b-kazakh-text-to-sql-dpo --served-model-name kazsql --max-model-len 4096
Send the same two messages with "temperature": 0 and
"chat_template_kwargs": {"enable_thinking": false}.
Training
- Started from: RakhatM/qwen3-1.7b-kazakh-text-to-sql-sft.
- Data: the
dpo config of RakhatM/kazakh-text-to-sql:
1,650 pairs for training questions that the SFT model sometimes gets wrong;
chosen is the gold SQL, rejected one of the model's own wrong answers. 1,568
pairs for training, 82 held out for evaluation.
- Method: DPO (sigmoid loss, β 0.1) plus an RPO term (
rpo_alpha 1.0: the
negative log-likelihood of the chosen answer is added to the loss). QLoRA with the
same LoRA settings as the SFT stage, on top of the merged SFT model.
- Settings: learning rate 5e-5, cosine schedule, 5% warmup, 1 epoch, effective
batch 16 (2 × 8), bf16. 98 steps, 6.8 min on one H100, 11.5 GB peak GPU memory.
- Why the RPO term: plain DPO at this learning rate widened the margin between
chosen and rejected answers while making the gold SQL itself less likely
(
rewards/chosen fell to about −0.9), and accuracy dropped (test_hero
66.7 → 59.7). With the NLL term rewards/chosen stayed near −0.1.
- The adapter was merged into the SFT model (bf16).
Evaluation
Execution match (%) on the test sets of the dataset, greedy decoding:
Table with columns: model, test_hero, test_unseen, test_independent, test_unseen_independent| model | test_hero | test_unseen | test_independent | test_unseen_independent |
|---|
| Qwen3-1.7B-Base, 3-shot | 35.8 | 36.8 | 31.2 | 33.8 |
| SFT | 66.7 | 64.8 | 63.7 | 51.2 |
| DPO (+RPO) | 72.1 | 68.0 | 73.8 | 51.2 |
| GRPO | 75.6 | 67.8 | 71.2 | 53.8 |
test_hero is held out from the training database by gold SQL; test_unseen uses
two databases never seen in training; the independent sets were written by another
model without access to the training data. With 80–400 questions per set,
differences of a few points are within noise. Four of the 80 test_independent
questions also occur in the training data (see the dataset card).
Limitations
- Trained on small schemas (4 tables, at most 200 rows) and on questions that models
wrote. Expect lower accuracy on large real schemas and on how real users phrase
questions: on a new schema with independently written questions it is right about
half of the time.
- It writes SQLite; other SQL dialects were not tested.
- The figures in the Qazaqstan database are approximate, so answers about Kazakhstan
are only as accurate as that database.
License
Apache 2.0, like the base model.