Views
No views yet
| Metric | Base Mistral-7B | This Adapter (v3) | Delta |
|---|---|---|---|
| Execution Accuracy | 57.5% | 94.0% | +36.5pp |
| Exact Match | 1.0% | 74.0% | +73pp |
| Avg BLEU | 0.428 | 0.923 | +0.495 |
| Valid SQL Rate | 100.0% | 100.0% | ±0 |
1import torch
2from peft import PeftModel
3from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
4
5base_model = "mistralai/Mistral-7B-v0.3"
6adapter = "visheshgupta29/mistral-7b-text2sql-qlora"
7
8# Load quantized base model
9bnb_config = BitsAndBytesConfig(
10 load_in_4bit=True,
11 bnb_4bit_quant_type="nf4",
12 bnb_4bit_compute_dtype=torch.float16,
13 bnb_4bit_use_double_quant=True,
14)
15model = AutoModelForCausalLM.from_pretrained(
16 base_model, quantization_config=bnb_config, device_map="auto"
17)
18model = PeftModel.from_pretrained(model, adapter)
19model.eval()
20
21tokenizer = AutoTokenizer.from_pretrained(adapter)
22
23# Build prompt
24prompt = """### Task: Generate a single SQL query to answer the following question.
25Do not repeat any conditions or output multiple queries.
26
27### Database Schema:
28CREATE TABLE employees (id INT, name TEXT, department TEXT, salary REAL);
29
30### Question:
31What is the average salary per department?
32
33### SQL Query:
34"""
35
36inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
37
38# Find all ';' token variants for stop condition
39semicolon_ids = set(tokenizer.encode(";", add_special_tokens=False))
40for tok_str, tok_id in tokenizer.get_vocab().items():
41 if tok_str.replace("\u2581", "").strip() == ";":
42 semicolon_ids.add(tok_id)
43stop_ids = list({tokenizer.eos_token_id} | semicolon_ids)
44
45with torch.inference_mode():
46 output = model.generate(
47 **inputs,
48 max_new_tokens=128,
49 do_sample=False,
50 repetition_penalty=1.1,
51 eos_token_id=stop_ids,
52 )
53
54generated = output[0][inputs["input_ids"].shape[1]:]
55sql = tokenizer.decode(generated, skip_special_tokens=True).strip()
56if ";" in sql:
57 sql = sql.split(";")[0].strip()
58print(sql)
59# SELECT department, AVG(salary) FROM employees GROUP BY departmentSQLPredictor class:1from src.inference.predict import SQLPredictor
2
3predictor = SQLPredictor(adapter_path="visheshgupta29/mistral-7b-text2sql-qlora")
4sql = predictor.predict(
5 question="What is the average salary per department?",
6 schema="CREATE TABLE employees (id INT, name TEXT, department TEXT, salary REAL);"
7)| Parameter | Value |
|---|---|
| Base model | Mistral-7B-v0.3 |
| Method | QLoRA (4-bit NF4 + LoRA) |
| LoRA rank | 16 |
| LoRA alpha | 32 |
| Target modules | q, k, v, o, gate, up, down proj |
| Trainable params | 42M (1.1% of 3.8B) |
| Dataset | sql-create-context (20K train) |
| Epochs | 1 |
| Batch size | 2 (effective 16 via grad accum) |
| Optimizer | Paged AdamW 8-bit |
| LR | 2e-4, cosine schedule |
| Train loss | 0.038 |
| Eval loss | 0.025 |
| Training time | 4h 45min on Kaggle T4 |
| Peak VRAM | 5.37 GB |
; so the model learns to stop generating. Without this, the model repeats conditions endlessly.tokenizer.encode(";") returns ▁; but the model generates bare ; (different token ID). We scan get_vocab() for all variants.repetition_penalty=1.1 — Higher values (1.3, 1.5) cause gibberish on SQL because they penalize tokens from the prompt that must be reused.no_repeat_ngram_size — SQL has valid repeated n-grams like = "val" AND that this constraint blocks.