Text Generation
PEFT
Safetensors
Turkish
English
text-to-sql
turkish
banking
risk-management
lora
distillation
small-language-model
slm-rd
Eval Results (legacy)
Instructions to use eqlx-ai/tr-risk-sql-gemma-e4b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use eqlx-ai/tr-risk-sql-gemma-e4b with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("google/gemma-4-E4B-it") model = PeftModel.from_pretrained(base_model, "eqlx-ai/tr-risk-sql-gemma-e4b") - Notebooks
- Google Colab
- Kaggle
File size: 18,462 Bytes
ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a 4e15ffe ae943b1 4e15ffe 023d74b 4e15ffe 8352ba5 4e15ffe 8352ba5 4e15ffe 8352ba5 4e15ffe 8352ba5 4e15ffe d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 d92cf3a ae943b1 8352ba5 ae943b1 8352ba5 ae943b1 8352ba5 ae943b1 8352ba5 d92cf3a | 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 | ---
language: [tr, en]
license: cc-by-nc-4.0
base_model: google/gemma-4-E4B-it
library_name: peft
pipeline_tag: text-generation
tags: [text-to-sql, turkish, banking, risk-management, lora, distillation, small-language-model, slm-rd]
model-index:
- name: tr-risk-sql-gemma-e4b
results:
- task: {type: text-generation, name: Turkish text-to-SQL on bank risk data marts}
dataset: {name: tr-risk-sql (synthetic, execution-verified), type: private}
metrics:
- {type: accuracy, name: 'execution accuracy, development set, with the verify-and-vote loop', value: 0.888}
- {type: accuracy, name: 'execution accuracy, development set, single answer', value: 0.797}
---
# tr-risk-sql-gemma-e4b
**A small model that turns Turkish risk questions into SQL · Türkçe risk sorularını SQL'e çeviren küçük model**
Can Demir · [eqlx.ai](https://eqlx.ai) · 2026-11
> **A 16-dollar R&D study:** an open 8-billion-parameter model that fits on a single GPU was brought close to large
> models on an expert task, bank risk management. On data marts it had never seen, accuracy rose **from 56% to 87%**.
>
> **16 dolarlık bir Ar-Ge çalışması:** tek GPU'ya sığan 8 milyar parametreli açık bir model, bankacılık risk yönetimi
> gibi uzmanlık isteyen bir işte büyük modellere yaklaştırıldı. Hiç görmediği veri ambarlarında doğruluk **%56'dan
> %87'ye** çıktı.
---
## English
### Why this work
In sectors that cannot send data outside the organisation (banking, insurance, healthcare), the common assumption is that
expert tasks need the largest models, and that running them in-house needs a large GPU investment. This work shows the
opposite: **on a narrow, well-defined expert task, a small model can be brought close to large ones with the right
engineering.** The large model is needed once, as a teacher; the model that runs every day can be small.
### What it does
A risk analyst asks a question in Turkish about the bank's risk data mart. The model reads the schema, writes a short plan
and one `SELECT` portable to Oracle and PostgreSQL; a second call summarises the result in Turkish and proposes a chart.
Domains covered include IFRS 9 expected credit loss, liquidity (LCR, HQLA), collateral, market risk (VaR, backtesting),
operational risk, credit portfolio, non-performing loans and counterparty risk.
### Results
A query counts as correct only when it is **executed on three databases** and returns exactly the reference result.
| Model (same 160 questions, 6 risk data marts) | Parameters | Accuracy |
|---|---|---|
| Frontier-class large model (teacher) | – | 99.4% |
| Gemma 4 31B (larger sibling) | 31B | 93.1% |
| **This model + verify-and-vote loop** | **8B** | **88.8%** |
| This model, single answer | 8B | 79.7% |
| Gemma 4 E4B, untuned (start) | 8B | 57.3% |
The small model closed **88%** of the gap to its 4x larger sibling and **75%** of the gap to the frontier model.
**Unseen data marts** (sealed test set: 125 questions, five risk domains absent from training), second-generation
model (v2) with the loop against the untuned model:
| | Untuned | Trained + loop |
|---|---|---|
| Overall accuracy | 56.0% | **86.8%** |
| SQL, plain questions | 53.0% | 91.0% |
| SQL, banking-jargon questions | 44.5% | 81.0% |
| Hard questions | 35.6% | 74.5% |
| Turkish summary | 71.2% | 80.8% |
On a sealed test set of 125 questions over five risk domains absent from training, the second-generation model of this
pipeline (v2) with the loop went from **56.0% to 86.8%** against the untuned model: +30.8 points, 95% confidence interval
+21.6 to +37.2 (bootstrap over schema families). SQL accuracy rose from 53% to 91% on plain questions and from 44.5% to
81% on banking-jargon questions; queries that ran but returned a wrong number fell from 62 cases to 25. The model in this
repository (v3) adds one round of self-distillation on top of v2: single-answer accuracy rose from 77.7% to 79.7% (a
confirmed gain) and general ability stayed at the untuned model's level (85.0% vs 86.7%).
**Total cost: 15.72 USD** (one rented GPU plus teacher API calls), about 14 hours.
### How it was built
1. **Measurement first.** A frozen execution verifier: every query runs on three seeded databases, results are compared
cell by cell regardless of row and column order, and each query is transpiled to Oracle and PostgreSQL. Test sets are
split by schema family; the noise floor (±3 points) and paired confidence intervals decide every comparison.
2. **Synthetic risk worlds.** 53 training and 15 test data marts with Turkish column comments, coded fields and the traps
of real data. No real bank data at any stage.
3. **Cross-verified teacher data.** One large model writes the question and SQL, a second independent model answers from
the schema alone; a pair is kept only when both return the same result on all three databases. Four question styles,
seven query patterns, 2,236 verified pairs, 2,935 training rows.
4. **LoRA fine-tuning** of the text decoder only (rank 64, 139.5M trainable parameters). → 72.2%
5. **Logit distillation** from Gemma 4 31B: the larger sibling's token distributions as a second target (0.5 CE + 0.5 KL,
top-64 plus remainder). → 75.2%
6. **Self-distillation (RFT):** eight sampled answers per training question, executed, the verified ones trained on. → 78.6%
7. **Plan before SQL:** a 3-7 line plan in Turkish precedes every query.
8. **Structural diversity:** separately authored schema shapes (hierarchies, restructuring history, syndication shares,
multi-currency positions) under the same blind verification.
9. **Verify-and-vote loop at inference:** five candidates, executed, failures repaired from the error message, the result
most candidates agree on wins. The largest single gain, with no training. → 86.6%, 88.1% with the second generation
10. **Second self-distillation (this release):** the loop's consistency moved into the weights; a single greedy answer with
repair reaches 86.3% in 1-3 calls. → **88.8%** with the loop
11. **Reinforcement learning study:** GRPO with execution reward, training and rollouts sharing one GPU. Finding: at this
scale, self-distillation on verified answers delivers the same idea at a sixth of the cost with a confirmed gain.
### Usage
**This repository contains the LoRA adapter (558 MB), not a full copy of the base model.** The adapter holds everything
the training added; it is loaded on top of the original Gemma 4 E4B weights, which are downloaded from Google's own
repository. Three steps:
1. Download the base model `google/gemma-4-E4B-it` (about 16 GB, Apache 2.0).
2. Attach this adapter to it.
3. Send the schema and the Turkish question in the prompt format below.
```bash
pip install -U transformers peft accelerate
```
```python
import torch
from huggingface_hub import hf_hub_download
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
BASE = "google/gemma-4-E4B-it" # the original model, from Google's repository
ADAPTER = "eqlx-ai/tr-risk-sql-gemma-e4b" # this repository: the adapter
tok = AutoTokenizer.from_pretrained(BASE)
base = AutoModelForCausalLM.from_pretrained(BASE, torch_dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(base, ADAPTER) # the adapter goes on top of the base
system = open(hf_hub_download(ADAPTER, "code/system_sql.txt"), encoding="utf-8").read()
schema = "CREATE TABLE ecl_result (facility_id INTEGER, reporting_date DATE, stage INTEGER, ead_amount DOUBLE);"
question = "31.12.2025 raporlama döneminde 3. aşamadaki kredilerin toplam EAD tutarı kaç TL?"
messages = [{"role": "system", "content": system},
{"role": "user", "content": f"### Şema\n{schema}\n\n### Soru\n{question}"}]
inputs = tok.apply_chat_template(messages, add_generation_prompt=True, return_dict=True, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=768, do_sample=False)
print(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
```
The model answers with a short numbered plan followed by one SQL query in a ```sql block. Prompt format: the system
message is `code/system_sql.txt`; the user message carries the table definitions (with column comments) under
`### Şema` and the Turkish question under `### Soru`. The model weights take about 16 GB in bf16, so a single GPU is
enough.
**Best accuracy:** run the verify-and-vote loop in `code/infer_loop.py` against your database. It works with any
OpenAI-compatible server (for example vLLM) serving the base model with this adapter.
### Scope and licence
A research release, developed and measured on synthetic data marts, designed as an analyst's assistant: the analyst sees
and approves the query and its result. Base model `google/gemma-4-E4B-it` (Apache 2.0). This adapter: **CC BY-NC 4.0**;
for commercial use contact [eqlx.ai](https://eqlx.ai).
---
## Türkçe
### Neden bu çalışma
Bankacılık, sigorta ve sağlık gibi verisini kurum dışına çıkaramayan sektörlerde yaygın varsayım, uzmanlık isteyen işleri
yalnız en büyük modellerin yapabileceği ve bunları içeride çalıştırmak için büyük GPU yatırımı gerektiğidir. Bu çalışma
tersini gösteriyor: **dar ve iyi tanımlanmış bir uzmanlık işinde küçük bir model, doğru mühendislikle büyük modellere
yakınsatılabilir.** Büyük modele bir kez, öğretmen olarak ihtiyaç vardır; her gün çalışan model küçük olabilir.
### Ne yapar
Bir risk yönetimi analisti, bankanın risk veri ambarı (data mart) hakkında Türkçe soru sorar:
> *"31.12.2025 itibarıyla 3. aşamadaki kredilerin toplam EAD'i ne kadar?"*
Model şemaya bakar, kısa bir çözüm planı yazar ve Oracle ile PostgreSQL'e taşınabilir tek bir `SELECT` sorgusu üretir.
Ayrı bir çağrıda sorgu sonucunu 1-3 cümleyle Türkçe özetler ve bir grafik tarifi (tür, eksenler, başlık) verir. Kapsadığı
alanlar: IFRS 9 beklenen kredi zararı, likidite (LKO, YKLV), teminat, piyasa riski (VaR, backtesting), operasyonel risk,
kredi portföyü, tahsili gecikmiş alacaklar, karşı taraf riski ve daha fazlası.
### Sonuçlar
Ölçüt katıdır: modelin yazdığı sorgu **üç ayrı veritabanında çalıştırılır**; sonuç referans sonuçla birebir aynıysa doğru
sayılır. Metin benzerliği puan getirmez.
**Büyük modellere yakınsama** (aynı 160 soru, 6 risk veri ambarı):
| Model | Parametre | Doğruluk |
|---|---|---|
| Sınır seviyesinde büyük model (öğretmen) | – | %99,4 |
| Gemma 4 31B (büyük kardeş) | 31 milyar | %93,1 |
| **Bu model + doğrula-ve-oyla döngüsü** | **8 milyar** | **%88,8** |
| Bu model, tek cevap | 8 milyar | %79,7 |
| Gemma 4 E4B, eğitimsiz (başlangıç) | 8 milyar | %57,3 |
Küçük model, kendinden 4 kat büyük kardeşiyle arasındaki farkın **%88'ini**, sınır modelle arasındaki farkın **%75'ini**
kapattı.
**Hiç görülmemiş veri ambarları** (mühürlü test seti: 125 soru, eğitimde yer almayan 5 risk alanı). Eğitim hattının
ikinci nesil modeli (v2) ve döngü ile, eğitimsiz modele karşı:
| | Eğitimsiz | Eğitilmiş + döngü |
|---|---|---|
| Genel doğruluk | %56,0 | **%86,8** |
| Düz sorularda SQL | %53,0 | %91,0 |
| Bankacılık jargonuyla sorularda SQL | %44,5 | %81,0 |
| Zor sorular | %35,6 | %74,5 |
| Türkçe özet | %71,2 | %80,8 |
Kazanç **+30,8 puan** (%95 güven aralığı +21,6 ile +37,2; şema ailelerine göre yeniden örnekleme). Çalışıp yanlış sayı
döndüren sorgu vakası 62'den 25'e indi. Bu depodaki model (v3), v2'nin üzerine bir tur öz-damıtma ile eğitildi: tek
cevap doğruluğu %77,7'den %79,7'ye çıktı (kanıtlı kazanç), genel yetenek testi %85,0 ile eğitimsiz modelin (%86,7)
seviyesinde korundu.
**Maliyet:** tamamı **15,72 USD** (kiralık tek GPU + öğretmen model çağrıları), yaklaşık 14 saat.
### Nasıl yapıldı: aşama aşama
**1. Önce ölçüm.** Tek satır eğitimden önce doğrulayıcı yazılıp donduruldu. Her sorgu, farklı tohumlarla üretilmiş üç
veritabanında çalıştırılır; sonuçlar satır ve sütun sırasından bağımsız, hücre hücre karşılaştırılır. Her sorgu ayrıca
Oracle ve PostgreSQL sözdizimine çevrilerek taşınabilirliği denetlenir. Test setleri şema ailesi düzeyinde ayrıldı: test
edilen veri ambarlarının hiçbiri eğitimde yoktur. Gürültü payı ölçüldü (±3 puan) ve her karşılaştırma eşleştirilmiş güven
aralığıyla yapıldı.
**2. Sentetik risk dünyaları.** 53 eğitim ve 15 test veri ambarı üretildi: her biri 5-7 tablo, Türkçe sütun açıklamaları,
kodlu alanlar ve gerçek verinin tuzakları (boş değerler, sınır tarihleri, çocuğu olmayan kayıtlar, aynı varlığın birden çok
dönem görüntüsü). Hiçbir aşamada gerçek banka verisi kullanılmadı; yöntem, veri kurum dışına çıkmadan uygulanabilir.
**3. Çapraz doğrulanmış öğretmen verisi.** Bir büyük model her şema için soru ve SQL yazdı; ikinci, bağımsız bir model
aynı soruyu yalnız şemaya bakarak cevapladı. Çift, ancak iki sorgu üç veritabanında da aynı sonucu verdiyse eğitime
girdi. Sorular dört üslupta yazıldı (düz, bankacılık jargonu, gündelik, kısa not) ve yedi sorgu kalıbını kapsar (iç içe
CTE, pencere fonksiyonuyla sıralama, dönem karşılaştırma, çoklu birleştirme, ağırlıklı oran, anti-join, basit). Sonuç:
2.236 doğrulanmış soru-SQL çifti, toplam 2.935 eğitim satırı.
**4. LoRA ile ince ayar (SFT).** Yalnız metin çözücünün izdüşüm katmanları eğitildi (rank 64, 139,5 milyon eğitilebilir
parametre); görüntü ve ses kuleleri dokunulmadan kaldı. → %72,2
**5. Büyük kardeşten logit damıtma.** Gemma 4 31B'nin her hedef belirteçteki (token) olasılık dağılımı ikinci hedef olarak
eklendi (0,5 çapraz entropi + 0,5 KL, ilk 64 belirteç + kalan kütle). Küçük model yalnız doğru cevabı değil, büyük modelin
seçenekler arasındaki tereddüdünü de öğrendi. → %75,2
**6. Öz-damıtma (RFT).** Model her eğitim sorusunu 8 kez cevapladı, cevaplar veritabanında çalıştırıldı ve
doğrulayıcıdan geçenlerle model yeniden eğitildi. Odak, modelin "bazen doğru bazen yanlış" yaptığı sorulardı. → %78,6
**7. Önce plan, sonra SQL.** Model, sorguyu yazmadan önce 3-7 maddelik Türkçe bir çözüm planı yazacak şekilde eğitildi
(hangi tablolar, hangi filtre, hangi ölçü). Planlar doğrulanmış sorgulardan türetildi.
**8. Yapısal çeşitlilik.** Üretici şablonun çıkaramadığı şema biçimleri (şube hiyerarşileri, yapılandırma geçmişi,
sendikasyon payları, çok para birimli pozisyonlar) ayrıca yazıldı ve aynı kör doğrulamadan geçirildi.
**9. Doğrula-ve-oyla döngüsü.** Çıkarımda model 5 aday sorgu yazar; her biri veritabanında çalıştırılır, hata veren aday
hata mesajıyla düzeltilir, çalışan adaylar arasında en çok adayın verdiği sonuç seçilir. Tek satır eğitim olmadan en büyük
tek kazancı bu adım verdi. → %86,6, ikinci nesil modelle %88,1
**10. İkinci öz-damıtma (bu sürüm).** Döngünün sağladığı tutarlılık modelin içine taşındı: tek cevap doğruluğu arttı,
sıcaklık 0'da tek aday ve onarımla %86,3'e ulaşıldı (soru başına 1-3 çağrı). → döngüyle **%88,8**
**11. Pekiştirmeli öğrenme araştırması.** Çalıştırma sonucunu ödül olarak kullanan GRPO, eğitim ve cevap üretiminin aynı
GPU'yu paylaştığı bir düzende çalıştırıldı. Bulgu: bu ölçekte, doğrulanmış cevaplarla öz-damıtma aynı fikri altıda bir
maliyetle ve kanıtlı kazançla veriyor.
### Kullanım
**Bu depoda LoRA adaptörü (558 MB) bulunur; taban modelin tam kopyası bulunmaz.** Eğitimin kattığı her şey adaptörün
içindedir; adaptör, Google'ın kendi deposundan indirilen özgün Gemma 4 E4B ağırlıklarının üzerine takılır. Üç adım:
1. Taban modeli indirin: `google/gemma-4-E4B-it` (yaklaşık 16 GB, Apache 2.0).
2. Bu adaptörü üzerine takın.
3. Şemayı ve Türkçe soruyu aşağıdaki istem biçimiyle gönderin.
```bash
pip install -U transformers peft accelerate
```
```python
import torch
from huggingface_hub import hf_hub_download
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
BASE = "google/gemma-4-E4B-it" # özgün model, Google'ın deposundan
ADAPTER = "eqlx-ai/tr-risk-sql-gemma-e4b" # bu depo: adaptör
tok = AutoTokenizer.from_pretrained(BASE)
base = AutoModelForCausalLM.from_pretrained(BASE, torch_dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(base, ADAPTER) # adaptör taban modelin üzerine takılır
system = open(hf_hub_download(ADAPTER, "code/system_sql.txt"), encoding="utf-8").read()
schema = "CREATE TABLE ecl_result (facility_id INTEGER, reporting_date DATE, stage INTEGER, ead_amount DOUBLE);"
question = "31.12.2025 raporlama döneminde 3. aşamadaki kredilerin toplam EAD tutarı kaç TL?"
messages = [{"role": "system", "content": system},
{"role": "user", "content": f"### Şema\n{schema}\n\n### Soru\n{question}"}]
inputs = tok.apply_chat_template(messages, add_generation_prompt=True, return_dict=True, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=768, do_sample=False)
print(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
```
Model önce kısa, numaralı bir plan, ardından bir ```sql bloğu içinde tek bir sorgu yazar. İstem biçimi: sistem mesajı
`code/system_sql.txt`; kullanıcı mesajında `### Şema` altında tablo tanımları (sütun açıklamalarıyla) ve `### Soru`
altında Türkçe soru. Model ağırlıkları bf16 biçiminde yaklaşık 16 GB yer tutar; tek bir GPU yeterlidir.
**En yüksek doğruluk için:** `code/infer_loop.py` içindeki doğrula-ve-oyla döngüsünü kendi veritabanınıza bağlayın.
Döngü, taban modeli bu adaptörle sunan OpenAI uyumlu herhangi bir sunucuyla (ör. vLLM) çalışır.
**Kapsam.** Bu sürüm bir araştırma çalışmasıdır ve sentetik veri ambarlarında geliştirilip ölçülmüştür. Analistin
yardımcısı olarak tasarlanmıştır: sorguyu ve sonucu analist görür ve onaylar. Lisans CC BY-NC 4.0'dır; ticari kullanım
için [eqlx.ai](https://eqlx.ai) ile iletişime geçin.
|