File size: 7,208 Bytes
bc630c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b02c3d
bc630c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b02c3d
bc630c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b02c3d
bc630c6
 
 
 
 
 
 
 
 
8b02c3d
bc630c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b02c3d
bc630c6
 
 
 
 
 
8b02c3d
 
bc630c6
 
 
 
 
 
8b02c3d
bc630c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b02c3d
 
 
 
bc630c6
 
 
 
 
 
8b02c3d
bc630c6
 
8b02c3d
 
 
 
 
 
 
 
 
 
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# Text-to-SQL Post-Training

# Text-to-SQL Post-Training

> A multi-week campaign to post-train a small open model into a strong text-to-SQL generator, scored by **execution accuracy** (run gold vs predicted SQL against a real SQLite DB). Click an experiment to open its page.

## Experiments

| Status | Experiment | Owner |
| --- | --- | --- |
| **Week 1 — Foundations & baselines** | | |
| done | [Build execution-accuracy eval harness](#/build-execution-accuracy-eval-harness) | Ana |
| done | [Zero-shot baselines across open models](#/zero-shot-baselines-across-open-models) | Ana |
| done | [Clean data: dedup + dialect filtering](#/clean-data-dedup-dialect-filtering) | Ana |
| done | [QLoRA SFT baseline](#/qlora-sft-baseline) | Ravi |
| in-progress | [LR & LoRA-rank sweep](#/lr-lora-rank-sweep) | Ravi |
| planned | [Prompt format ablation (chat vs completion)](#/prompt-format-ablation-chat-vs-completion) | to assign |
| **Week 2 — Scaling & data** | | |
| in-progress | [Synthetic data augmentation (self-instruct)](#/synthetic-data-augmentation-self-instruct) | Ravi |
| planned | [Add Spider + WikiSQL to the eval suite](#/add-spider-wikisql-to-the-eval-suite) | Ana |
| planned | [Curriculum: order by join complexity](#/curriculum-order-by-join-complexity) | to assign |
| planned | [Distill from a larger open model](#/distill-from-a-larger-open-model) | Ravi |
| blocked | [Long-context schema eval @32k](#/long-context-schema-eval-32k) | to assign |
| **Week 3 — Hardening & release** | | |
| planned | [Full fine-tune vs LoRA comparison](#/full-fine-tune-vs-lora-comparison) | Ravi |
| planned | [Error taxonomy & failure analysis](#/error-taxonomy-failure-analysis) | Ana |
| planned | [CPU latency & throughput](#/cpu-latency-throughput) | to assign |
| planned | [Final model card + release](#/final-model-card-release) | Ana |

# Build execution-accuracy eval harness

---

### Harness: execution accuracy over SQLite

`Jul 02, 2026 · 06:24 UTC`

Execution accuracy is the right metric: exact string match is near-zero because the model writes semantically-equivalent but syntactically-varied SQL. The harness builds an in-memory SQLite DB from each example's schema, runs gold and predicted queries, and compares result sets (order-aware only when the gold has ORDER BY).


````python title=eval.py
import sqlite3
from datasets import load_dataset

def execution_accuracy(preds, golds, schemas):
    """Build an in-memory SQLite DB per example, run gold vs pred, compare result sets."""
    correct = 0
    for pred, gold, schema in zip(preds, golds, schemas):
        con = sqlite3.connect(":memory:")
        con.executescript(schema)
        try:
            got = con.execute(pred).fetchall()
            want = con.execute(gold).fetchall()
            correct += set(map(tuple, got)) == set(map(tuple, want))
        except sqlite3.Error:
            pass
    return correct / len(preds)

````

- https://github.com/huggingface/trl

# Zero-shot baselines across open models

---

### Baselines: 28.9% best zero-shot

`Jul 02, 2026 · 06:24 UTC`

Zero-shot execution accuracy on the 800-example held-out set. Instruct variants lead; the 1.5B instruct model is the best base to fine-tune from.

| Model | Exec. accuracy | Exact match |
| --- | --- | --- |
| google/gemma-3-270m | 12.1% | 0.1% |
| meta-llama/Llama-3.2-1B-Instruct | 21.7% | 3.2% |
| Qwen/Qwen2.5-1.5B-Instruct | **28.9%** | 4.4% |

Target to beat with SFT: **28.9%**.

- https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct
- https://huggingface.co/meta-llama/Llama-3.2-1B-Instruct
- https://huggingface.co/datasets/gretelai/synthetic_text_to_sql

# Clean data: dedup + dialect filtering

---

### Data: 42k clean SQLite-executable examples

`Jul 02, 2026 · 06:24 UTC`

Filtered the training set to examples whose gold query executes cleanly in SQLite (~78% do; the rest use non-SQLite dialects), then deduped against the eval prompts. Final training set: 42k examples.

# QLoRA SFT baseline

---

### QLoRA baseline: 51.3% exec acc

`Jul 02, 2026 · 06:24 UTC`

First SFT pass: QLoRA (r=16) on Qwen2.5-1.5B-Instruct, 3 epochs, completion-only loss. Execution accuracy 28.9% → **51.3%**. Live metrics on the Trackio dashboard.


````python title=train.py
import trackio
from datasets import load_dataset
from trl import SFTConfig, SFTTrainer
from peft import LoraConfig

def main(model="Qwen/Qwen2.5-1.5B-Instruct", r=16, lr=2e-4):
    ds = load_dataset("gretelai/synthetic_text_to_sql", split="train")
    trackio.init(project="text2sql", config={"model": model, "r": r, "lr": lr})
    cfg = SFTConfig(learning_rate=lr, num_train_epochs=3,
                    per_device_train_batch_size=16, report_to="trackio")
    peft = LoraConfig(r=r, lora_alpha=2 * r, task_type="CAUSAL_LM")
    SFTTrainer(model, args=cfg, train_dataset=ds, peft_config=peft).train()

if __name__ == "__main__":
    main()

````

- https://huggingface.co/spaces/abidlabs/gemma-text2sql-trackio

# LR & LoRA-rank sweep

---

### Sweep: r=16, lr=5e-4 wins

`Jul 02, 2026 · 06:24 UTC`

Swept learning rate {1e-4, 2e-4, 5e-4} × rank {8, 16, 32}. r=16 / lr=5e-4 is the clear winner; r=8 underfits and lr>5e-4 destabilizes late in training.

- media/lr_rank_sweep.png
- https://huggingface.co/spaces/abidlabs/gemma-text2sql-trackio

# Prompt format ablation (chat vs completion)

# Synthetic data augmentation (self-instruct)

---

### Synth data: +3.1% exec acc (early)

`Jul 02, 2026 · 06:24 UTC`

Generating extra (question, SQL) pairs by prompting a larger open model on real schemas, keeping only pairs whose SQL executes. Running as an HF Job; outputs land in a bucket. Early signal: +3.1% exec acc when mixed 1:4 with real data.


````python title=gen_synth.py
"""Self-instruct augmentation: sample real schemas, prompt a teacher model for
new (question, SQL) pairs, then keep only pairs whose SQL executes."""
import json, sqlite3, random
from huggingface_hub import InferenceClient

client = InferenceClient()

def augment(schemas, n_per_schema=8):
    out = []
    for schema in schemas:
        prompt = f"Given this schema, write {n_per_schema} diverse NL questions "\
                 f"and their SQLite queries as JSONL.\n{schema}"
        for line in client.text_generation(prompt, max_new_tokens=1024).splitlines():
            try:
                ex = json.loads(line)
                sqlite3.connect(":memory:").executescript(schema).execute(ex["sql"])
                out.append({**ex, "schema": schema})
            except Exception:
                continue
    return out

````

- https://huggingface.co/jobs/abidlabs/6a45b02733c08a2c0dae0348
- https://huggingface.co/buckets/abidlabs/jobs-artifacts

# Add Spider + WikiSQL to the eval suite

# Curriculum: order by join complexity

# Distill from a larger open model

---

### Plan & hypothesis

`Jul 02, 2026 · 06:24 UTC`

Plan: use the best open model as a teacher (rationale + SQL), distill into the 1.5B student. Hypothesis: closes most of the gap to the teacher at a fraction of the cost.

# Long-context schema eval @32k

# Full fine-tune vs LoRA comparison

# Error taxonomy & failure analysis

# CPU latency & throughput

# Final model card + release