Text Generation
PEFT
Safetensors
English
lora
qlora
sft
trl
text-to-sql
sql
conversational
Eval Results (legacy)
Instructions to use SASVAAI/GLM-4.7-Flash-sql-create-context with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use SASVAAI/GLM-4.7-Flash-sql-create-context with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("zai-org/GLM-4.7-Flash") model = PeftModel.from_pretrained(base_model, "SASVAAI/GLM-4.7-Flash-sql-create-context") - Notebooks
- Google Colab
- Kaggle
File size: 16,701 Bytes
5fe5cb5 54af938 5fe5cb5 54af938 | 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 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | ---
# ---- Identity -------------------------------------------------------------
base_model: zai-org/GLM-4.7-Flash
base_model_relation: adapter
library_name: peft
pipeline_tag: text-generation
language:
- en
license: mit # verified via the Hub API: zai-org/GLM-4.7-Flash reports `mit`.
# The training data is CC-BY-4.0 — see Licence below.
# ---- Discovery ------------------------------------------------------------
tags:
- lora
- qlora
- peft
- sft
- trl
- text-to-sql
- sql
datasets:
- b-mc2/sql-create-context
metrics:
- exact_match
- bleu
- rouge
# ---- Structured evaluation ------------------------------------------------
model-index:
- name: glm-4.7-flash-sql-create-context-lora
results:
- task:
type: text-generation
name: Text-to-SQL (natural language + CREATE TABLE schema -> SQL)
dataset:
type: sql-create-context-val
name: sql-create-context derived validation split (400 pairs)
split: validation
metrics:
- type: exact_match
name: Exact match
value: 0.805
- type: bleu
name: BLEU
value: 0.940082
- type: rouge
name: ROUGE-L
value: 0.986055
args:
rouge_type: rougeL
---
# GLM-4.7-Flash Text-to-SQL (LoRA)
Given a natural-language question and a `CREATE TABLE` schema, emits exactly one
SQL query answering that question against that schema. For natural-language
query interfaces over a known relational schema.
This is a **LoRA adapter for**
[zai-org/GLM-4.7-Flash](https://huggingface.co/zai-org/GLM-4.7-Flash), trained
with **QLoRA (4-bit NF4 base, bf16 compute)** via
[TRL](https://github.com/huggingface/trl) SFT.
## Model details
| | |
|---|---|
| Developed by | SASVA AI Model Cognition Labs (MCL) Team |
| Base model | [`zai-org/GLM-4.7-Flash`](https://huggingface.co/zai-org/GLM-4.7-Flash) |
| Base parameters | 30B total / 3B active (MoE) — 29,943,396,864 in the merged bf16 build |
| Architecture family | `glm4_moe_lite` (`Glm4MoeLiteForCausalLM`), 47 layers, hidden size 2048, vocab 154,880 |
| Adaptation | LoRA (`r=64`, `alpha=128`, `dropout=0.05`) |
| Trainable modules | `q_a_proj`, `q_b_proj`, `kv_a_proj_with_mqa`, `kv_b_proj`, `o_proj`, `gate_proj`, `up_proj`, `down_proj` |
| Training method | `qlora` (4-bit NF4, double quant, bf16 compute) |
| Refinement | none |
| Language | English (questions) / SQL (outputs) |
| License | MIT (inherited from the base model) |
Trainable parameters: **118,140,928** — **0.3945%** of the base. The adapter file
is 472,671,000 bytes (752 fp32 tensors: a `lora_A` + `lora_B` pair for each of
the 8 target modules across all 47 layers).
GLM-4.7-Flash uses Multi-head Latent Attention, so the attention target modules
are the MLA projections (`q_a_proj`/`q_b_proj`/`kv_a_proj_with_mqa`/`kv_b_proj`),
not `q_proj`/`k_proj`/`v_proj`. Targeting the conventional names would silently
adapt nothing.
## Intended use
**Direct use.** Translate one English question plus one `CREATE TABLE` schema
into one SQL query. The model was trained on a specific prompt shape and that
shape is part of the contract:
- System prompt (verbatim): *"You are a text-to-SQL engine. Given a
natural-language question and a CREATE TABLE schema, output exactly one SQL
query that answers the question against the provided schema. Output only the
raw SQL query on a single line with no explanation, no markdown formatting,
and no additional text."*
- User turn: the question, a blank line, then the schema inside a fenced code
block.
- Applied through the tokenizer's chat template (`chat_template.jinja`, shipped
in this repo) with `enable_thinking=False`. Do not concatenate strings by hand.
- The query is the **first line** of the generation; discard anything after it.
**Out of scope.**
- **Not validated against a live database.** The model is scored on string
similarity to a reference query, never on execution. A syntactically perfect
query can still be semantically wrong. Parse and, where you can, dry-run
against the real schema before trusting output.
- **Never interpolate output into a privileged connection.** Treat generated SQL
as untrusted input: run it read-only, with least privilege, on a connection
that cannot write or drop.
- Multi-table joins, CTEs, window functions, subqueries, and DDL/DML are largely
out of distribution — the training data is dominated by single-table
`SELECT`s. Measured join accuracy is poor (see Limitations).
- Dialect is not controllable. The model reproduces the source corpus's
conventions (double-quoted string literals, lower-cased comparison values),
which are not portable to every engine.
- Not a general-purpose assistant. It emits a bare query, never prose.
## How to get started
```python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import PeftModel
BASE = "zai-org/GLM-4.7-Flash"
ADAPTER = "SASVAAI/GLM-4.7-Flash-sql-create-context"
# 4-bit NF4 matches the numerics the adapter was trained against. A bf16 base
# also works and scores the same (see Merged-weights equivalence) but needs
# ~60 GB rather than ~22 GB.
bnb = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.bfloat16,
bnb_4bit_use_double_quant=True,
)
tokenizer = AutoTokenizer.from_pretrained(ADAPTER)
model = AutoModelForCausalLM.from_pretrained(
BASE, quantization_config=bnb, dtype=torch.bfloat16, device_map="auto"
)
model = PeftModel.from_pretrained(model, ADAPTER)
model.eval()
SYSTEM = (
"You are a text-to-SQL engine. Given a natural-language question and a "
"CREATE TABLE schema, output exactly one SQL query that answers the question "
"against the provided schema. Output only the raw SQL query on a single line "
"with no explanation, no markdown formatting, and no additional text."
)
question = "Which kingdom has Suin as its capital?"
schema = "CREATE TABLE table_name_65 (name_of_kingdom VARCHAR, capital VARCHAR)"
messages = [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": f"{question}\n\n```\n{schema}\n```"},
]
prompt = tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True, enable_thinking=False
)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=128, do_sample=False)
text = tokenizer.decode(out[0][inputs.input_ids.shape[-1]:], skip_special_tokens=True)
print(text.strip().splitlines()[0])
# -> SELECT name_of_kingdom FROM table_name_65 WHERE capital = "suin"
```
The base model is ~59 GB in bfloat16, or ~22 GB per GPU under 4-bit NF4.
> Decoding matters. This model was evaluated with greedy decoding
> (`do_sample=False`, `max_new_tokens=128`). Sampling will not reproduce the
> reported numbers.
**Serving note.** These adapter weights do **not** load as a vLLM LoRA on this
architecture — vLLM's MLA path asserts inside
`DeepSeekV2FusedQkvAProjLinear` because `q_a_proj` and `kv_a_proj_with_mqa` are
fused into one module that a LoRA cannot be attached to. A merged build of these
weights serves under vLLM without complaint. For vLLM deployment, merge first
(`peft.merge_and_unload()`).
## Training details
**Data.** A 4,000-pair subset of
[`b-mc2/sql-create-context`](https://huggingface.co/datasets/b-mc2/sql-create-context)
(78,577 pairs, itself derived from WikiSQL and Spider), split 90/10 by this
project's data-generation stage. Each record is
`{"instruction": <question>, "input": <CREATE TABLE ...>, "output": <SQL>}`.
The subset selection is a generated artifact, not a published split — the
`id`/`instruction`/`input`/`gold` tuples in `predictions.jsonl` are the
authoritative record of what was evaluated.
| | |
|---|---|
| Train samples | 3,600 |
| Validation samples | 400 |
| Prompt format | chat template + system prompt (see Intended use) |
### Method
| | |
|---|---|
| SFT method | `qlora` |
| Base quantisation during training | 4-bit NF4, double quant, bf16 compute |
| Refinement stage | none |
| Hardware | 4x NVIDIA H200 (141 GB), `torchrun --nproc_per_node=4` |
`qlora` is one of three methods considered for this model, alongside 8-bit LoRA
and attention-only 4-bit LoRA. All three were tried; `qlora` scored highest
every time it was compared against the other two on the same data.
No refinement stage ran; the published weights are the SFT adapter.
### Final hyperparameters
| Hyperparameter | Value | Source |
|---|---|---|
| `learning_rate` | 0.0002 | `training_args.bin` |
| `lr_scheduler_type` | cosine | `training_args.bin` |
| `num_train_epochs` | 3 | `training_args.bin` |
| `per_device_train_batch_size` | 1 | `training_args.bin` |
| `gradient_accumulation_steps` | 4 | `training_args.bin` |
| `max_length` | 2048 | `training_args.bin` |
| `warmup_ratio` | 0.05 | `training_args.bin` |
| `weight_decay` | 0.01 | `training_args.bin` |
| `optim` / `max_grad_norm` / `seed` | `adamw_torch` / 1.0 / 42 | `training_args.bin` |
| `bf16` / `gradient_checkpointing` | true / true (`use_reentrant=False`) | `training_args.bin` |
| `neftune_noise_alpha` / `packing` | None / false | `training_args.bin` |
| `lora_r` / `lora_alpha` / `lora_dropout` | 64 / 128 / 0.05 | `adapter_config.json` |
| `target_modules` | the 8 listed in Model details | `adapter_config.json` |
**Effective batch size: 16** (`1 x 4 x 4`). Optimizer steps: 675.
KD parameters are omitted deliberately — this is a `qlora` run, not
`bf16_lora_kd`, so `KD_ALPHA`/`KD_BETA`/`KD_TEMPERATURE` carry inert defaults
that would imply distillation that did not happen.
This configuration is **not a unique optimum**. Other configurations reached the
same `exact_match`; this one was published for being the simplest and cheapest
of them — fewest epochs, shortest training time — and because it scored
marginally higher on BLEU and ROUGE-L. Treat the values as a good working point,
not a tuned maximum.
**Observed training metrics.**
| | |
|---|---|
| Final train loss | 0.4594 |
| Mean train loss | 0.5646523337894016 |
| Train runtime | 6392.6844s |
| Total FLOPs | 2.3441226939026637e+17 |
| Throughput | 1.689 samples/s, 0.106 steps/s |
No eval loss was computed during training; the loop scores on generation, not
perplexity. Loss falls from 2.3882 at step 10 to 1.1077 at step 20 and 0.5940 by
step 170, then improves slowly to ~0.45 by step 660. The task is essentially
learned within the first quarter of epoch 1; epochs 2 and 3 together buy roughly
0.14 of training loss.
## Evaluation
**Protocol.** All 400 validation pairs, no sampling. Predictions generated
greedily (`do_sample=False`, `max_new_tokens=128`) through the same chat template
used in training, against a 4-bit NF4 base to match training numerics. The
predicted query is the **first line** of the generation, stripped. No constrained
decoding and no SQL grammar were applied. Exact match is byte equality against
the reference query; BLEU and ROUGE-L are computed over the same strings.
| Metric | Value |
|---|---|
| Exact match | 0.805000 (322 / 400) |
| BLEU | 0.940082 |
| ROUGE-L | 0.986055 |
| Samples | 400 |
**Baseline for comparison.** **Not measured.** The untuned
`zai-org/GLM-4.7-Flash` was never scored on this split, so these numbers
quantify the fine-tuned model's performance but do not establish how much of it
the fine-tuning is responsible for.
**This is a validation split, not a held-out test set.** Hyperparameters were
selected against it, so expect optimistic bias. A clean estimate needs a third
split that was never used for selection.
## Limitations and bias
**Exact match understates the model; BLEU and ROUGE-L overstate it.** The
0.805 / 0.940 / 0.986 spread is the story of this model. Exact match is byte
equality, so a semantically identical query loses the point on quoting or a
missing `DISTINCT`:
```
question: Find the states where have some college students in tryout and their decisions are yes.
schema: CREATE TABLE tryout (cName VARCHAR, decision VARCHAR);
CREATE TABLE college (state VARCHAR, cName VARCHAR)
gold: SELECT DISTINCT T1.state FROM college AS T1 JOIN tryout AS T2 ON T1.cName = T2.cName WHERE T2.decision = 'yes'
pred: SELECT T1.state FROM college AS T1 JOIN tryout AS T2 ON T1.cName = T2.cName WHERE T2.decision = "yes"
```
Relaxing to case- and whitespace-insensitive comparison moves exact match from
0.805 to **0.8125** (325/400) — so only 3 of the 78 misses are pure formatting.
The other 75 are real semantic or structural errors. ROUGE-L at 0.986 mostly
measures that both strings are short SQL over the same table names; it is not
evidence of correctness.
**Output is never degenerate.** All 400 golds and all 400 predictions begin with
`SELECT`; the model never emitted prose, markdown, or an empty string. Format
compliance is not the failure mode.
**Joins are the failure mode.** Miss rate by gold-query feature:
| Gold query contains | n | misses | miss rate |
|---|---|---|---|
| `JOIN` | 13 | 10 | **76.9%** |
| `ORDER BY` | 3 | 1 | 33.3% |
| aggregate (`COUNT`/`SUM`/`AVG`/`MIN`/`MAX`) | 138 | 37 | 26.8% |
| `GROUP BY` | 8 | 2 | 25.0% |
| multi-predicate `WHERE` (`AND`/`OR`) | 123 | 27 | 22.0% |
| single-predicate `SELECT..WHERE` | 181 | 22 | 12.2% |
The model is reliable on the shape it saw constantly (one table, one predicate)
and unreliable on the shape it barely saw. **Do not deploy this on a
multi-table schema.** Note the join, `ORDER BY`, and `GROUP BY` rows rest on
13, 3, and 8 examples respectively — read them as a strong warning, not a precise
rate.
Complexity tracks length: correct predictions have a mean gold length of 10.6
tokens, misses 12.8.
**Dialect is baked in.** The model emits the source corpus's double-quoted
string literals and lower-cases comparison values. On engines where `"x"` is an
identifier rather than a string (PostgreSQL, ANSI mode), output will not run
unmodified.
**No execution or injection safety.** Correctness is measured only as string
similarity to a reference. Nothing here prevents a generated query from being
expensive, wrong, or destructive against a real database.
**Inherits all biases and limitations of the base model.** This adapter changes
0.3945% of the parameters and was not evaluated for social bias, safety, or
fairness.
## Merged-weights equivalence
A merged build of these weights (base + adapter folded into one standalone bf16
model, `W + (alpha/r) * B @ A`) was evaluated on the identical split:
| Metric | Adapter (4-bit base) | Merged (bf16) | Delta |
|---|---|---|---|
| Exact match | 0.805000 | 0.805000 | 0.000000 |
| BLEU | 0.940082 | 0.942079 | +0.001997 |
| ROUGE-L | 0.986055 | 0.987663 | +0.001608 |
**39 of 400 predictions differ** (9.75%) — far more churn than a bf16-trained
adapter would show, because merging into an unquantised base genuinely changes
the numerics the adapter was fitted against. The changes cancel exactly:
**10 predictions flip correct→incorrect and 10 flip incorrect→correct**, leaving
exact match identical and BLEU/ROUGE-L marginally higher.
So a merged distribution is behaviourally equivalent in aggregate but not
prediction-for-prediction. Merging is also the practical route to vLLM serving
(see Serving note). MIT permits distributing derivative works, so publishing a
merged build is allowed.
## Environmental impact
| | |
|---|---|
| Hardware | 4x NVIDIA H200 (141 GB) |
| Training time | 106.5 minutes (6392.6844s) |
| Cloud provider / region | on-premise |
Covers the training of these published weights only. It excludes the wider
hyperparameter search that selected them, which cost substantially more.
## Framework versions
- PEFT 0.18.1
- TRL: 1.0.0
- Transformers: 5.7.0.dev0
- Pytorch: 2.5.1+cu121
- Datasets: 4.8.4
- Tokenizers: 0.22.2
- bitsandbytes: 0.49.2
`transformers` is a git-main build: GLM-4.7-Flash's `Glm4MoeLite` architecture is
not in the stable PyPI release.
## Licence
Adapter weights: **MIT**, inherited from
[`zai-org/GLM-4.7-Flash`](https://huggingface.co/zai-org/GLM-4.7-Flash)
(verified via the Hub API). Training data:
[`b-mc2/sql-create-context`](https://huggingface.co/datasets/b-mc2/sql-create-context),
licensed **CC-BY-4.0** — downstream use should carry that attribution.
## Citation
```bibtex
@misc{glm47flash_sql_create_context_lora_2026,
title = {GLM-4.7-Flash Text-to-SQL (LoRA)},
author = {{SASVA AI Model Cognition Labs (MCL) Team}},
year = {2026},
url = {https://huggingface.co/SASVAAI/GLM-4.7-Flash-sql-create-context}
}
```
|