32B · Qwen2.5-Coder-32B-Instruct
ALLM.H-SQL
Medical NL2SQL System for AI-native EMR
의료 자연어를 SQL로 변환하는 스키마 비종속 시스템. EHRSQL 2024 RS@0 88.48 (LG-KAIST 88.17 능가). Claude Sonnet 4(52.62), GPT-4.1(50.64) 대비 36%p 압도. 2-Model Pipeline(v1 Gate + Bv1 Enriched SQL) + Verifier 앙상블.
Model Card
Base Model
Qwen2.5-Coder-32B-Instruct
Parameters
32B
License
Apache 2.0 + Acryl Research License
Languages
Korean, English
Modalities
Text
Hardware
8× NVIDIA B200 192GB HBM3e (AWS p6-b200.48xlarge)
Training Pipeline
Base Model
Qwen2.5-Coder-32B-Instruct (BF16)
v1 SFT (Plain Schema)
17K samples — Gate + SQL 생성 (RS@0 88.48)
Bv1 SFT (Enriched Schema)
17K samples — Schema-Aware SQL (테이블 혼동 해결)
2-Model Pipeline
v1 Gate(plain) + Bv1 SQL(enriched) + SC k=5 + Verifier
What Makes This Different
| 기존 연구 | 우리 차별점 |
|---|---|
| Claude Sonnet 4 (RS@0=52.62) | RS@0 88.48 — 상용 모델 대비 36%p 압도 |
| LG-KAIST (RS@0=88.17) | RS@0 88.48 — EHRSQL 2024 역대 최고 |
| 단일 모델 NL2SQL | 2-Model Pipeline (Gate 전문 + SQL 전문) + Verifier 앙상블 |
| 스키마 종속 시스템 | 스키마 비종속 설계 — 배포 시 DB 스캔으로 자동 적응 |
Paper Contributions
- EHRSQL 2024 RS@0 88.48 (LG-KAIST 88.17 능가)
- 2-Model Pipeline: Gate 전문 모델 + Schema-Aware SQL 모델 분리
- Enriched Schema SFT: CREATE TABLE 주석으로 schema awareness 향상
- Claude/GPT 대비 36%p 압도 — 특화 오픈소스의 가치 입증
Benchmarks
| Benchmark | Score | Baseline / SOTA | Metric |
|---|---|---|---|
| EHRSQL RS@0 | 88.48 | LG-KAIST 88.17, Claude 52.62, GPT 50.64 | Reliability Score |
| EHRSQL RS@10 (+ Verifier) | 73.34 | LG-KAIST 81.32 | Reliability Score |
Training Data
- V117,137 samples (MIMIC-IV 5,124 + Korean EMR 12,013)
- BV117,137 samples (Enriched Schema — column values + FK + table descriptions)
Quick Start
# pip install transformers torch from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("Acryl-aLLM/ALLM.H-SQL") tokenizer = AutoTokenizer.from_pretrained("Acryl-aLLM/ALLM.H-SQL") messages = [ {"role": "user", "content": "65세 남성, 갑작스런 흉통과 호흡곤란. 감별 진단은?"} ] text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) inputs = tokenizer(text, return_tensors="pt").to(model.device) output = model.generate(**inputs, max_new_tokens=1024) print(tokenizer.decode(output[0], skip_special_tokens=True))