Input: SQL schema (CREATE TABLE ...) + question in plain English
Output: SQL query that answers the question
Examples
Example 1 — JOIN + aggregation + sorting + limit
Schema:
sql
1CREATETABLE orders (id INT, user_id INT, amount DECIMAL, created_at DATE);2CREATETABLE users (id INT, name VARCHAR, country VARCHAR);
Question:What are top 5 users by total order amount in 2025?
Model output:
sql
1SELECT T1.id, T1.name, T1.country,SUM(T2.amount)AS total_amount
2FROM users AS T1 JOIN orders AS T2 ON T1.id = T2.user_id
3WHERE T2.created_at >=20254GROUPBY T1.id ORDERBY total_amount DESCLIMIT5
Example 2 — AVG with GROUP BY
Schema:CREATE TABLE employees (id INT, name VARCHAR, department VARCHAR, salary INT, hire_date DATE)Question:Show average salary by department, sorted from highest to lowest
sql
1SELECTAVG(salary), department FROM employees
2GROUPBY department ORDERBYAVG(salary)DESC
Example 3 — WHERE with multiple conditions
Schema:CREATE TABLE products (id INT, name VARCHAR, category VARCHAR, price DECIMAL, stock INT)Question:Find all products with stock less than 10 in the 'electronics' category
SELECT * FROM products WHERE category = "electronics" AND stock < 10
Example 4 — COUNT with JOIN
Schema:
sql
1CREATETABLE customers (id INT, name VARCHAR, country VARCHAR);2CREATETABLE orders (id INT, customer_id INT, total DECIMAL);
Question:Count how many orders each customer from Ukraine has made
sql
1SELECTCOUNT(*)FROM orders AS T1 JOIN customers AS T2
2ON T1.customer_id = T2.id WHERE T2.country ="Ukraine"
Manual analysis of the 24 "failures" shows that roughly half are semantically equivalent SQL that exact-match rejects:
Type of "failure"
Example
Strings vs numbers
WHERE runs = 144 vs reference WHERE runs = "144"
Alias differences
SELECT Prime vs reference SELECT Prime AS minister
Ambiguous reference (dataset has minor errors)
SELECT SUM(poles) vs reference SELECT MIN(poles)
Genuine model errors (missing GROUP BY, wrong aggregation)
~10 out of 100
A proper execution accuracy evaluation (running predictions against a real database) would likely show 85–90% correctness. LLM-as-judge with Claude/GPT-4 is the next planned improvement.
Known limitations
English only. Trained on English questions only.
ANSI SQL. No specific dialect (PostgreSQL / MySQL / Oracle).
Naive date comparisons can appear (e.g. created_at >= 2025 instead of created_at >= '2025-01-01').
Implicit GROUP BY is occasionally missed when a question implies "per each X" without saying it.
Trained on the original dataset distribution — complex 3+ table joins or window functions are out of distribution.
How to use
python
1from peft import PeftModel
2from transformers import AutoModelForCausalLM, AutoTokenizer
3import torch
45base ="unsloth/Llama-3.2-3B-Instruct"6adapter ="notingemiu/llama-3.2-3b-text2sql-lora"78tokenizer = AutoTokenizer.from_pretrained(adapter)9model = AutoModelForCausalLM.from_pretrained(base, torch_dtype=torch.float16, device_map="auto")10model = PeftModel.from_pretrained(model, adapter)1112schema ="CREATE TABLE orders (id INT, total DECIMAL, created_at DATE)"13question ="What is total revenue in 2024?"1415messages =[16{"role":"system","content":f"You are a SQL expert. Use this schema:\n{schema}"},17{"role":"user","content": question},18]19inputs = tokenizer.apply_chat_template(20 messages, tokenize=True, add_generation_prompt=True, return_tensors="pt"21).to(model.device)22out = model.generate(input_ids=inputs, max_new_tokens=200, temperature=0.1, do_sample=True)23print(tokenizer.decode(out[0], skip_special_tokens=True))
Author
Built as part of a portfolio for AI/LLM Engineer roles. Comments and feedback welcome.