text2sql-demo / src /app /inference.py
minimew's picture
Upload src/app/inference.py with huggingface_hub
09d1572 verified
Raw
History Blame Contribute Delete
10.6 kB
"""
Inference module -- load checkpoint tu HuggingFace va generate SQL tu model
input string. Ho tro day du catalog checkpoint cua du an (4 stage x 3
architecture = 12 model), nguoi dung TU CHON qua dropdown UI bang 1 model_id
duy nhat (xem MODEL_CATALOG) -- khong con phu thuoc cung mode du lieu dang
active (fixed/uploaded), vi cac checkpoint Stage 2/3 da verify hoat dong tot
tren CA HAI dang schema (Spider-style co PK/FK VA WikiSQL-style khong PK/FK,
xem ghi chu duoi).
model_id format: "{terminal_dataset}_stage{n}_{architecture}"
- terminal_dataset: dataset CUOI CUNG model duoc fine-tune tren (quyet dinh
quy uoc sinh SQL ma model da hoc, KHONG can trung voi schema dang dung).
- stage: 1 (train rieng le) | 2 (WikiSQL->Spider) | 3 (WikiSQL->Spider->BIRD)
Da verify thuc nghiem (2026-06-26): checkpoint Stage 2/3 (da tiep xuc Spider/
BIRD multi-column SELECT + GROUP BY) VAN sinh dung multi-column SELECT ngay ca
khi duoc dua schema dang WikiSQL (khong PK/FK, vd CSV upload) -- vd
"SELECT store_name, revenue FROM data_table". Day la ly do chinh de mo rong
catalog nay: checkpoint Stage 1 WikiSQL (terminal_dataset=wikisql) KHONG BAO
GIO sinh duoc 2 cot (gioi han cau truc cua chinh grammar WikiSQL, xem
visualizer.py/CLAUDE.md) -> khong the ra chart; Stage 2/3 thi co the, doi lai
do chinh xac cho cau don gian (SELECT 1 cot, WHERE) co the thap hon mot chut
so voi Stage 1 WikiSQL thuan (xem EM/EX tung checkpoint trong label).
Luu y dinh dang tokenizer KHONG nhat quan giua cac checkpoint trong du an nay
(mot so luu san tokenizer.json FAST, mot so chi co vocab.json/merges.txt SLOW)
-- PHAI tu phat hien dinh dang co san (_has_fast_tokenizer_file) thay vi
hardcode use_fast=True/False.
"""
import os
import torch
from huggingface_hub import snapshot_download
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
NUM_BEAMS = 4
ARCHITECTURE_NAMES = {"t5": "T5-base", "codet5": "CodeT5-base", "bart": "BART-base"}
# Moi entry: repo, ckpt, max_input/output_length, label (hien thi dropdown),
# stage (1/2/3), terminal_dataset ("wikisql"|"spider"|"bird" -- dataset CUOI
# CUNG model fine-tune tren, quyet dinh quy uoc quote khi post-process).
MODEL_CATALOG = {
# ---- Stage 1: train rieng le tren WikiSQL (EM greedy, in-training) ----
"wikisql_stage1_t5": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "wikisql/t5-base/run_6/epoch-12-em0_6918",
"max_input_length": 384, "max_output_length": 64,
"architecture": "t5", "stage": 1, "terminal_dataset": "wikisql",
"label": "T5-base 路 Stage 1 (WikiSQL)",
},
"wikisql_stage1_codet5": {
"repo": "minimew/text2sql-checkpoint-2",
"ckpt": "wikisql/codet5-base/run_1/epoch-08-em0_7688",
"max_input_length": 384, "max_output_length": 64,
"architecture": "codet5", "stage": 1, "terminal_dataset": "wikisql",
"label": "CodeT5-base 路 Stage 1 (WikiSQL)",
},
"wikisql_stage1_bart": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "wikisql/bart-base/run_1/epoch-05-em0_7228",
"max_input_length": 384, "max_output_length": 64,
"architecture": "bart", "stage": 1, "terminal_dataset": "wikisql",
"label": "BART-base 路 Stage 1 (WikiSQL)",
},
# ---- Stage 1: train rieng le tren Spider (EM/EX final eval, beam=4) ----
"spider_stage1_t5": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "spider/t5-base/run_5/epoch-07-em0_3956",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "t5", "stage": 1, "terminal_dataset": "spider",
"label": "T5-base 路 Stage 1 (Spider)",
},
"spider_stage1_codet5": {
"repo": "minimew/text2sql-checkpoint-2",
"ckpt": "spider/codet5-base/run_1/epoch-07-em0_4391",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "codet5", "stage": 1, "terminal_dataset": "spider",
"label": "CodeT5-base 路 Stage 1 (Spider)",
},
"spider_stage1_bart": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "spider/bart-base/run_1/epoch-08-em0_2940",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "bart", "stage": 1, "terminal_dataset": "spider",
"label": "BART-base 路 Stage 1 (Spider)",
},
# ---- Stage 2: WikiSQL -> Spider (EM/EX final eval, beam=4) ----
# Da verify: van sinh dung multi-column SELECT tren schema kieu WikiSQL
# (CSV upload) -- lua chon tot nhat neu can chart tu CSV.
"spider_stage2_t5": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "stage2/spider/t5-base/run_1/epoch-08-em0_3752",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "t5", "stage": 2, "terminal_dataset": "spider",
"label": "T5-base 路 Stage 2 (WikiSQL鈫扴pider)",
},
"spider_stage2_codet5": {
"repo": "minimew/text2sql-checkpoint-2",
"ckpt": "stage2/spider/codet5-base/run_1/epoch-07-em0_4275",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "codet5", "stage": 2, "terminal_dataset": "spider",
"label": "CodeT5-base 路 Stage 2 (WikiSQL鈫扴pider)",
},
"spider_stage2_bart": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "stage2/spider/bart-base/run_1/epoch-07-em0_3037",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "bart", "stage": 2, "terminal_dataset": "spider",
"label": "BART-base 路 Stage 2 (WikiSQL鈫扴pider)",
},
# ---- Stage 3: WikiSQL -> Spider -> BIRD (EX tren BIRD dev, final eval) ----
# Da verify: van sinh SQL hop le tren CA schema Spider va WikiSQL (khong
# can field "evidence:" -- demo nay khong co BIRD DB thuc/evidence injection).
"bird_stage3_t5": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "stage3/bird/t5-base/run_1/epoch-12-em0_0495",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "t5", "stage": 3, "terminal_dataset": "bird",
"label": "T5-base 路 Stage 3 (鈫払IRD)",
},
"bird_stage3_codet5": {
"repo": "minimew/text2sql-checkpoint-2",
"ckpt": "stage3/bird/codet5-base/run_1/epoch-11-em0_1037",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "codet5", "stage": 3, "terminal_dataset": "bird",
"label": "CodeT5-base 路 Stage 3 (鈫払IRD)",
},
"bird_stage3_bart": {
"repo": "minimew/text2sql-checkpoints",
"ckpt": "stage3/bird/bart-base/run_1/epoch-12-em0_0443",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "bart", "stage": 3, "terminal_dataset": "bird",
"label": "BART-base 路 Stage 3 (鈫払IRD)",
},
# ---- Joint: train dong thoi WikiSQL + Spider + BIRD (40/40/20 mix) ----
# CodeT5 only (RQ5). Spider EX 60.74% / WikiSQL EX 81.89% / BIRD EX 23.08%.
# terminal_dataset="spider": 60% du lieu la Spider+BIRD dung single-quote
# cho string value -- ap dung quote normalization nhu cac checkpoint Spider.
"joint_codet5": {
"repo": "minimew/text2sql-checkpoint-2",
"ckpt": "joint/codet5-base/run_1/epoch-12-emavg0_4333",
"max_input_length": 1024, "max_output_length": 128,
"architecture": "codet5", "stage": "joint", "terminal_dataset": "spider",
"label": "CodeT5-base 路 Joint (WikiSQL + Spider + BIRD)",
},
}
DEFAULT_MODEL_ID_FOR_MODE = {
"fixed": "spider_stage1_codet5",
"uploaded": "wikisql_stage1_codet5",
}
_state = {}
def _has_fast_tokenizer_file(ckpt_path: str) -> bool:
return os.path.exists(os.path.join(ckpt_path, "tokenizer.json"))
def get_checkpoint_config(model_id: str) -> dict:
return MODEL_CATALOG[model_id]
def load_model(model_id: str):
"""Load model + tokenizer cho 1 checkpoint, cache rieng theo model_id.
Goi lai voi cung model_id se tra ve doi tuong da cache."""
if model_id in _state:
return _state[model_id]["model"], _state[model_id]["tokenizer"], _state[model_id]["device"]
cfg = get_checkpoint_config(model_id)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# local_dir_use_symlinks=False: tranh OSError WinError 1314 tren Windows
# khi Developer Mode chua kich hoat (huggingface_hub mac dinh dung symlink
# de cache, can quyen dac biet de tao symlink tren Windows).
local_dir = snapshot_download(
repo_id=cfg["repo"], allow_patterns=[f"{cfg['ckpt']}/*"], local_dir_use_symlinks=False
)
ckpt_path = os.path.join(local_dir, cfg["ckpt"])
use_fast = _has_fast_tokenizer_file(ckpt_path)
tokenizer = AutoTokenizer.from_pretrained(ckpt_path, use_fast=use_fast)
model = AutoModelForSeq2SeqLM.from_pretrained(ckpt_path).to(device)
model.eval()
_state[model_id] = {"model": model, "tokenizer": tokenizer, "device": device}
return model, tokenizer, device
def generate_sql(model_input: str, model_id: str) -> str:
"""model_input: full string 'question: ... | schema: ...'."""
model, tokenizer, device = load_model(model_id)
cfg = get_checkpoint_config(model_id)
inputs = tokenizer(
model_input,
return_tensors="pt",
truncation=True,
max_length=cfg["max_input_length"],
).to(device)
with torch.no_grad():
outputs = model.generate(
**inputs,
num_beams=NUM_BEAMS,
max_length=cfg["max_output_length"],
early_stopping=True,
)
sql = tokenizer.decode(outputs[0], skip_special_tokens=True).strip()
# Dong bo voi normalize convention da dung luc eval CHO SPIDER/BIRD: model
# doi khi sinh double-quote cho STRING VALUE ("France") nhung gold dung
# single-quote ('France') -- doi sang single-quote de tang ty le execute
# thanh cong. KHONG ap dung cho checkpoint terminal_dataset=wikisql: o
# format WikiSQL, double-quote dung de quote TEN COT (xem quote_column()
# trong process_wikisql.py), con string value 膽a dung single-quote san --
# thay the se bien ten cot co quote thanh string literal sai (vd
# "product name" -> 'product name' bi SQLite hieu thanh chuoi hang so
# thay vi tham chieu cot).
if cfg["terminal_dataset"] != "wikisql":
sql = sql.replace('"', "'")
return sql