AlioLeuchtmann commited on
Commit
7b5df48
·
verified ·
1 Parent(s): 66a6dc4

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +267 -0
README.md CHANGED
@@ -1,3 +1,270 @@
1
  ---
 
 
 
2
  license: apache-2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ base_model: Qwen/Qwen3.5-2B
3
+ language:
4
+ - en
5
  license: apache-2.0
6
+ pipeline_tag: text-generation
7
+ library_name: transformers
8
+ tags:
9
+ - text-to-sql
10
+ - sql
11
+ - sqlite
12
+ - bird
13
+ - self-verification
14
+ - distillation
15
+ - chain-of-thought
16
+ model-index:
17
+ - name: flash-sqlite
18
+ results:
19
+ - task:
20
+ type: text-to-sql
21
+ name: Text-to-SQL
22
+ dataset:
23
+ type: bird-bench
24
+ name: BIRD (hidden test set)
25
+ metrics:
26
+ - type: execution_accuracy
27
+ value: 73.73
28
+ name: Execution Accuracy (EX)
29
+ - type: soft_f1
30
+ value: 74.63
31
+ name: Soft F1
32
+ - type: r_ves
33
+ value: 67.17
34
+ name: R-VES
35
  ---
36
+
37
+ # flash-sqlite
38
+
39
+ **A 2B text-to-SQL model that writes SQL and checks its own candidates. It scores 73.73 EX on the hidden BIRD test set.**
40
+
41
+ flash-sqlite is [Qwen3.5-2B](https://huggingface.co/Qwen/Qwen3.5-2B), fully fine-tuned for SQLite text-to-SQL. One set of weights does two jobs:
42
+
43
+ - **Generator:** reasons step by step about the schema, then writes the SQL.
44
+ - **Judge:** given the schema, the question, a candidate query and its execution result, answers *Yes* or *No*. The probability of *Yes* is used to pick among the candidates.
45
+
46
+ Both roles use the same checkpoint. There is no auxiliary model, no embedding model and no external API. Under the BIRD organisers' ruling, this qualifies for the **single-model track**.
47
+
48
+ **Key facts**
49
+
50
+ - **No reinforcement learning:**
51
+ - flash-sqlite is trained with supervised fine-tuning only, on execution-verified traces.
52
+ - No RL, GRPO, DPO or reward model is involved.
53
+ - Several strong entries on the leaderboard, such as Arctic-Text2SQL-R1 and Databricks RLVR, are trained with RL.
54
+ - **Reasoning mode disabled:**
55
+ - The model runs in Qwen3.5's non-thinking mode (`enable_thinking=False`), for generation and for judging.
56
+ - It writes a short structured analysis followed by the SQL, with no long hidden reasoning chain.
57
+ - The judge outputs a single token.
58
+ - **One model, one GPU:** the same 2B checkpoint generates and verifies, with no external model or API.
59
+
60
+ ## Official BIRD results (hidden test set)
61
+
62
+ The BIRD team scored the model on the hidden test set: 32 candidates per question plus self-judge, on a single A100 80 GB.
63
+
64
+ | metric | simple | moderate | challenging | **total** |
65
+ |---|---|---|---|---|
66
+ | Execution Accuracy (EX) | 80.19 | 71.53 | 56.49 | **73.73** |
67
+ | Soft F1 | | | | **74.63** |
68
+ | R-VES | | | | **67.17** |
69
+
70
+ ### How it compares
71
+
72
+ **At 2B parameters, flash-sqlite scores higher on the BIRD test set than every frontier LLM baseline on the leaderboard**:
73
+ - GPT-5.5, Claude Opus 4.6, Claude 4.5 Sonnet, Qwen3-Coder-480B, GLM-4.7, DeepSeek-R1 and Kimi-K2-Thinking;
74
+ - and specialised open models up to 32B.
75
+
76
+ On the single-model leaderboard it is ahead of 50 of the 66 other entries. On the overall leaderboard, which includes multi-model pipelines and proprietary systems, it is ahead of more than 90.
77
+
78
+ All scores are **BIRD test-set execution accuracy**. Markers show how many candidates each entry samples per question, using the leaderboard's own categories:
79
+
80
+ - no marker: one candidate;
81
+ - \* **Few:** 2–7 candidates;
82
+ - \*\* **Many:** 8–32 candidates.
83
+
84
+ **Frontier and large general-purpose LLMs** (single-model leaderboard):
85
+
86
+ | model | provider | size | test EX |
87
+ |---|---|---|---|
88
+ | **flash-sqlite (this model)** | — | **2B** | **73.73\*\*** |
89
+ | GPT-5.5-xhigh | OpenAI | proprietary | 72.55 |
90
+ | Claude Opus 4.6 | Anthropic | proprietary | 70.15 |
91
+ | Qwen3-Coder-480B-A35B | Alibaba | 480B MoE | 68.14 |
92
+ | Claude 4.5 Sonnet | Anthropic | proprietary | 66.85 |
93
+ | GLM-4.7 | Zhipu AI | large open-weight | 62.94 |
94
+ | DeepSeek-R1 | DeepSeek | 671B MoE | 60.93 |
95
+ | Kimi-K2-Thinking | Moonshot AI | ~1T MoE | 59.87 |
96
+ | DeepSeek (2024 baseline) | DeepSeek | 236B MoE | 56.68 |
97
+ | Mistral (2024 baseline) | Mistral AI | 123B | 55.84 |
98
+ | GPT-4 | OpenAI | proprietary | 54.89 |
99
+
100
+ **Specialised text-to-SQL models** (single-model leaderboard):
101
+
102
+ | model | size | test EX |
103
+ |---|---|---|
104
+ | Native mini | 4B | 76.86\*\* |
105
+ | Arctic-Text2SQL-R1-32B (Snowflake) | 32B | 73.84\* |
106
+ | **flash-sqlite (this model)** | **2B** | **73.73\*\*** |
107
+ | Databricks RLVR 32B | 32B | 73.56 |
108
+ | Arctic-Text2SQL-R1-14B (Snowflake) | 14B | 72.22\* |
109
+ | Arctic-Text2SQL-R1-7B (Snowflake) | 7B | 70.43\* |
110
+ | XiYanSQL-QwenCoder-32B (Alibaba) | 32B | 69.03\* |
111
+
112
+ flash-sqlite samples 32 candidates and selects one with its own judge (see [How it works](#how-it-works)). All figures are from the public leaderboard at [bird-bench.github.io](https://bird-bench.github.io), taken at the time of writing. The earlier version of this model (2B, majority vote over 7 candidates) scored 68.47\*.
113
+
114
+ ## Speed and efficiency
115
+
116
+ 32 candidates plus a judge sounds expensive. With a 2B model and the right serving setup, it is not.
117
+
118
+ - **One GPU, no API:** the bf16 weights need about 4.5 GB. Everything runs locally on a single GPU: generation, execution and judging. No data leaves the machine.
119
+ - **32 candidates in parallel:**
120
+ - The 32 samples per question come from one request (`n=32`), and vLLM batches them together.
121
+ - With **prefix caching**, the long schema prompt is prefilled once and shared by all 32 samples.
122
+ - The judge prompts of the same question also share their schema prefix.
123
+ - **Throughput:** about **6,400–7,600 output tokens/s** on one 96 GB RTX 6000 MaxQ GPU, which is 8–11 finished candidates per second.
124
+ - **The judge is almost free:**
125
+ - It reads one token (P(Yes)) per result group instead of generating text.
126
+ - On BIRD dev, **38% of questions needed no judge call at all**, because all executable candidates agreed.
127
+ - On average there were **2.45 judge calls per question** (3,763 calls for 949 contested questions).
128
+ - The whole judge pass over BIRD dev took **about 30 seconds**.
129
+ - **End to end:** all 1,534 BIRD dev questions take **about 95 minutes**. That covers 49,000 candidates (about 85 minutes), plus executing them and judging (about 10 minutes), or about 3.7 s per question.
130
+ - **Greedy mode:** for latency-sensitive use, a single greedy answer still reaches 57.05 EX on dev. Majority voting over 32 candidates without the judge reaches 62.92.
131
+
132
+ ## BIRD dev results
133
+
134
+ These come from the dev revision `bird-sql-dev-1106`: 1,532 questions with executable gold SQL, scored by execution accuracy with set comparison. All three rows come from the same generation run.
135
+
136
+ | inference | EX | simple | moderate | challenging |
137
+ |---|---|---|---|---|
138
+ | **32 candidates + self-judge** | **67.49** | 78.11 | 63.66 | 35.22 |
139
+ | 16 candidates + self-judge | 66.91 | 77.65 | 63.21 | 33.91 |
140
+ | majority vote over 32, no judge | 62.92 | 74.27 | 56.88 | 32.17 |
141
+ | greedy, single answer | 57.05 | | | |
142
+
143
+ On dev, the self-judge adds **4.6 EX** over plain majority voting with the same 32 candidates. Its gain grows with the number of candidates.
144
+
145
+ ## How it works
146
+
147
+ For each question:
148
+
149
+ 1. **Generate** 32 candidates at temperature 1.0, top_p 0.95, top_k 20, with a 2,048-token limit and non-thinking mode.
150
+ 2. **Execute** each candidate read-only against the database, with a 30 s timeout.
151
+ - Candidates are grouped by their result set, compared as sets with `1 == 1.0`.
152
+ - Candidates that fail to run are dropped.
153
+ - A group's votes are the number of candidates in it.
154
+ 3. **Self-judge** — only if more than one result group remains.
155
+ - The same model gets one prompt per group: the schema and question, the group's SQL, and a 5-row preview of its result.
156
+ - P(Yes) is read from the first generated token, restricted to *Yes* / *No* and renormalised.
157
+ 4. **Select** the group with the highest **votes × P(Yes)**.
158
+
159
+ ## Usage
160
+
161
+ The model expects the OmniSQL-style prompt shown below and answers with its reasoning followed by a fenced SQL block. Always take the **last** ```sql block. Use **non-thinking mode** (`enable_thinking=False`).
162
+
163
+ ### Prompt format
164
+
165
+ ```text
166
+ Task Overview:
167
+ You are a data science expert. Below, you are provided with a database schema and a natural language question. Your task is to understand the schema and generate a valid SQL query to answer the question.
168
+
169
+ Database Engine:
170
+ SQLite
171
+
172
+ Database Schema:
173
+ {db_details}
174
+ This schema describes the database's structure, including tables, columns, primary keys, foreign keys, and any relevant relationships or constraints.
175
+
176
+ Question:
177
+ {question}
178
+
179
+ Hint: {evidence}
180
+
181
+ Instructions:
182
+ - Make sure you only output the information that is asked in the question. If the question asks for a specific column, make sure to only include that column in the SELECT clause, nothing more.
183
+ - The generated query should return all of the information asked in the question without any missing or extra information.
184
+ - Before generating the final SQL query, please think through the steps of how to write the query.
185
+
186
+ Output Format:
187
+ In your answer, please enclose the generated SQL query in a code block:
188
+ ```sql
189
+ -- Your SQL query
190
+ ```
191
+
192
+ Take a deep breath and think step by step to find the correct SQL query.
193
+ ```
194
+
195
+ `{db_details}` contains, for each table:
196
+ - the `CREATE TABLE` statement;
197
+ - a comment block of column descriptions (where the database ships them);
198
+ - a comment block with 3 example rows.
199
+
200
+ ### Generation (vLLM)
201
+
202
+ ```python
203
+ import re
204
+ from transformers import AutoTokenizer
205
+ from vllm import LLM, SamplingParams
206
+
207
+ model_id = "AlioLeuchtmann/flash-sqlite"
208
+ tok = AutoTokenizer.from_pretrained(model_id)
209
+ llm = LLM(model=model_id, dtype="bfloat16")
210
+
211
+ def chat(prompt):
212
+ return tok.apply_chat_template([{"role": "user", "content": prompt}], tokenize=False,
213
+ add_generation_prompt=True, enable_thinking=False)
214
+
215
+ def last_sql(text):
216
+ blocks = re.findall(r"```sql\s*(.*?)```", text, re.S)
217
+ return blocks[-1].strip() if blocks else ""
218
+
219
+ prompt = ... # the prompt above, filled with the schema, question and hint
220
+
221
+ # a single answer
222
+ greedy = llm.generate([chat(prompt)], SamplingParams(temperature=0.0, max_tokens=2048))
223
+ print(last_sql(greedy[0].outputs[0].text))
224
+
225
+ # 32 candidates for voting + self-judge
226
+ samples = llm.generate([chat(prompt)], SamplingParams(n=32, temperature=1.0, top_p=0.95, top_k=20, max_tokens=2048))
227
+ candidates = [last_sql(o.text) for o in samples[0].outputs]
228
+ ```
229
+
230
+ ### Self-judge
231
+
232
+ Execute the candidates and group them by result set. Then score one representative query per group with the judge prompt below. Use `max_tokens=1`, `allowed_token_ids=[id("Yes"), id("No")]` and `logprobs=2`, and renormalise P(Yes) over the two tokens.
233
+
234
+ ```text
235
+ Task Overview:
236
+ You are a data science expert. Below, you are provided with a database schema, a natural language question, a candidate SQL query and the result of executing it. Your task is to decide whether the candidate SQL query answers the question correctly.
237
+
238
+ Database Engine:
239
+ SQLite
240
+
241
+ {the "Database Schema:" ... "Question:" part of the generation prompt}
242
+
243
+ Candidate SQL:
244
+ ```sql
245
+ {sql}
246
+ ```
247
+
248
+ Execution result ({nrows} rows, first 5 shown):
249
+ {preview}
250
+
251
+ Does the candidate SQL query answer the question correctly, returning exactly the requested information? Answer with one word: Yes or No.
252
+ ```
253
+
254
+ Pick the group with the highest `votes × P(Yes)`. If two groups tie, prefer the one with more votes, then the one that appeared first.
255
+
256
+ ### Tested environment
257
+
258
+ `vllm==0.25.1` and `transformers==5.14.1`, which support the Qwen3.5 hybrid architecture. A 2B model in bf16 needs about 4.5 GB of GPU memory for the weights. All 1,534 BIRD dev questions (49k samples plus judging) take about 95 minutes on a single 96 GB workstation GPU.
259
+
260
+ ## Intended use and limitations
261
+
262
+ - **Built for:** SQLite text-to-SQL on analytical questions in the style of BIRD, in English, optionally with an evidence hint. It is not a general chat model.
263
+ - **The judge needs execution:** it scores a query *together with its result*, so the database has to be available at inference time. It has not been calibrated as a standalone classifier. Use it in the votes × P(Yes) combination it was tuned for.
264
+ - **Dialects:** trained and evaluated only on SQLite. Other dialects, such as PostgreSQL or BigQuery, will need adaptation.
265
+ - **Hard questions:** accuracy on the challenging tier (56.5 EX on test) is still well below the simple tier. Multi-step queries remain the main weakness of a 2B model.
266
+ - **Safety:** generated SQL should run read-only. This model was never trained to avoid writing or destructive statements.
267
+
268
+ ## Acknowledgements
269
+
270
+ Built on Qwen3.5-2B by the Qwen team. Evaluated by the BIRD team ([bird-bench.github.io](https://bird-bench.github.io)). Developed by Alio Leuchtmann.