Text Generation
PEFT
Safetensors
Indonesian
nl2sql
text-to-sql
indonesian
sql
qlora
unsloth
conversational
Instructions to use qrizan/nl2sql-id-qlora-3b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use qrizan/nl2sql-id-qlora-3b with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("unsloth/qwen2.5-coder-3b-instruct-bnb-4bit") model = PeftModel.from_pretrained(base_model, "qrizan/nl2sql-id-qlora-3b") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- Unsloth Studio
How to use qrizan/nl2sql-id-qlora-3b with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for qrizan/nl2sql-id-qlora-3b to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for qrizan/nl2sql-id-qlora-3b to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for qrizan/nl2sql-id-qlora-3b to start chatting
Load model with FastModel
pip install unsloth from unsloth import FastModel model, tokenizer = FastModel.from_pretrained( model_name="qrizan/nl2sql-id-qlora-3b", max_seq_length=2048, )
| base_model: unsloth/qwen2.5-coder-3b-instruct-bnb-4bit | |
| library_name: peft | |
| license: apache-2.0 | |
| language: | |
| - id | |
| tags: | |
| - nl2sql | |
| - text-to-sql | |
| - indonesian | |
| - sql | |
| - qlora | |
| - unsloth | |
| - peft | |
| pipeline_tag: text-generation | |
| datasets: | |
| - qrizan/nl2sql-id-schema | |
| # NL2SQL-ID QLoRA - Indonesian Text-to-SQL (3B) | |
| Model QLoRA adapter (r=16) hasil fine-tuning **Qwen2.5-Coder-3B-Instruct** untuk menerjemahkan pertanyaan bisnis **Bahasa Indonesia** menjadi SQL. | |
| > **Proyek eksperimen.** Model dilatih khusus untuk satu skema e-commerce 5 tabel (customers, orders, order_items, products, payments). Bisa dipakai di database lain **hanya jika** skemanya persis sama. Untuk skema berbeda, perlu fine-tuning ulang dengan data baru. | |
| --- | |
| ## Hasil | |
| 3-way comparison pada 365 contoh eval_dev (nilai yang belum pernah dilihat model): | |
| | Sistem | Exec Acc | Valid SQL | Error dominan | | |
| |--------|:--------:|:---------:|---------------| | |
| | Base (Qwen2.5-Coder-3B, zero-shot) | 0.27% | 3.0% | `invalid_sql` (354) | | |
| | gpt-4o-mini (zero-shot) | 48.5% | 100% | `wrong_join` (99) | | |
| | **Model ini** | **97.26%** | **100%** | `other` (10) | | |
| Final pada eval_test (365 held-out, tidak pernah disentuh selama pengembangan): | |
| | Metrik | Nilai | | |
| |--------|-------| | |
| | Execution Acc | **91.78%** | | |
| | Valid SQL | 100% | | |
| | Gap vs dev | 5.48pp (generalisasi baik) | | |
| --- | |
| ## Skema Database | |
| Model dilatih dan hanya bekerja untuk skema 5 tabel berikut. Prompt harus selalu menyertakan DDL ini: | |
| | Tabel | Kolom | | |
| |-------|-------| | |
| | `customers` | id, name, city | | |
| | `orders` | id, customer_id, created_at, status | | |
| | `order_items` | id, order_id, product_id, qty, price | | |
| | `products` | id, name, category, price | | |
| | `payments` | id, order_id, amount, paid_at, method | | |
| Query yang didukung: `SELECT`, `JOIN` (max 4 tabel), `WHERE`, `GROUP BY`, `ORDER BY`, `SUM`/`COUNT`/`AVG`, `HAVING`, filter tanggal (`strftime`, `>= AND <`), `LIMIT`. | |
| --- | |
| ## Cara Pakai | |
| ### Load dari HF Hub | |
| ```python | |
| from unsloth import FastLanguageModel | |
| model, tokenizer = FastLanguageModel.from_pretrained( | |
| model_name="qrizan/nl2sql-id-qlora-3b", | |
| max_seq_length=768, | |
| load_in_4bit=True, | |
| ) | |
| FastLanguageModel.for_inference(model) | |
| ``` | |
| ### Inference (self-contained, tanpa dependensi proyek) | |
| ```python | |
| import re | |
| # Salin skema database anda ke sini | |
| SCHEMA_TEXT = """ | |
| customers(id, name, city) | |
| orders(id, customer_id, created_at, status) | |
| order_items(id, order_id, product_id, qty, price) | |
| products(id, name, category, price) | |
| payments(id, order_id, amount, paid_at, method) | |
| """ | |
| pertanyaan = "berapa total penjualan kategori elektronik bulan Januari 2025?" | |
| # System prompt harus persis seperti saat training (src/prompts.py::get_system_prompt) | |
| system = ( | |
| "Anda adalah asisten SQL yang menerjemahkan pertanyaan bisnis " | |
| "Bahasa Indonesia menjadi query SQLite.\n\n" | |
| f"Skema database:\n{SCHEMA_TEXT}\n\n" | |
| "Aturan:\n" | |
| "- Gunakan tabel dan kolom sesuai skema di atas.\n" | |
| "- Tulis reasoning singkat dalam tag <think>...</think>:\n" | |
| " Tabel: (tabel yang dipakai)\n" | |
| " Join: (kondisi join)\n" | |
| " Filter: (kondisi WHERE)\n" | |
| " Agregasi: (fungsi agregasi, atau '-' jika tidak ada)\n" | |
| "- Setelah </think>, tulis SQL tanpa markdown fence.\n" | |
| "- Hanya SELECT, tanpa INSERT/UPDATE/DELETE." | |
| ) | |
| messages = [ | |
| {"role": "system", "content": system}, | |
| {"role": "user", "content": pertanyaan}, | |
| ] | |
| prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) | |
| inputs = tokenizer(prompt, return_tensors="pt").to(model.device) | |
| outputs = model.generate(**inputs, max_new_tokens=512, do_sample=False) | |
| response = tokenizer.decode(outputs[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True) | |
| # Ekstrak SQL setelah </think> | |
| m = re.search(r"</think>\s*(.*)", response, re.DOTALL | re.IGNORECASE) | |
| sql = m.group(1).strip() if m else response.strip() | |
| # Bersihkan markdown fence jika ada | |
| sql = re.sub(r"```(?:sql)?\s*", "", sql, flags=re.IGNORECASE).replace("```", "").strip() | |
| print(sql) | |
| # SELECT SUM(oi.qty * oi.price) FROM order_items oi | |
| # JOIN products p ON oi.product_id = p.id | |
| # JOIN orders o ON oi.order_id = o.id | |
| # WHERE p.category = 'elektronik' | |
| # AND strftime('%Y-%m', o.created_at) = '2025-01' | |
| ``` | |
| ### Format Output | |
| Model menghasilkan reasoning chain diikuti SQL: | |
| ``` | |
| <think> | |
| Tabel: order_items, products, orders | |
| Join: oi.product_id = p.id, oi.order_id = o.id | |
| Filter: p.category = 'elektronik', strftime('%Y-%m', o.created_at) = '2025-01' | |
| Agregasi: SUM(qty * price) | |
| </think> | |
| SELECT SUM(oi.qty * oi.price) ... | |
| ``` | |
| SQL diekstrak setelah `</think>`. Baris `SCHEMA_TEXT` bisa diganti dengan DDL database anda - asal strukturnya sama dengan 5 tabel di atas. | |
| --- | |
| ## Training | |
| | Parameter | Nilai | | |
| |-----------|-------| | |
| | Model base | Qwen2.5-Coder-3B-Instruct (4-bit) | | |
| | Metode | QLoRA (r=16, alpha=16, dropout=0.05) | | |
| | Data train | 820 contoh (pool A: elektronik/fashion/makanan/furnitur, Jan-Jun 2025) | | |
| | Epoch | 5 | | |
| | Learning rate | 2e-4 | | |
| | Batch size | 16 (2 x grad_accum 8) | | |
| | GPU | Colab T4 (~15 menit) | | |
| | Trainable params | 29.9M (0.96%) | | |
| | Adapter size | 115 MB | | |
| Train dan eval menggunakan nilai berbeda (pool A vs pool B: kategori, bulan, kota) untuk menguji generalisasi, bukan hafalan. Hasil dev 97.26%, test held-out 91.78%. | |
| --- | |
| ## Batasan | |
| - **Skema spesifik.** Hanya untuk 5 tabel di atas. Skema berbeda perlu fine-tuning ulang. | |
| - Query `SELECT` saja - tidak mendukung `INSERT`/`UPDATE`/`DELETE` | |
| - Bahasa Indonesia dengan kosakata bisnis, tidak diuji pada bahasa lain | |
| - Maksimum ~768 token input | |
| --- | |
| ## Lisensi | |
| Apache 2.0 - bebas dipakai, dimodifikasi, didistribusikan. | |
| ## Kode Lengkap | |
| Pipeline training, evaluasi, demo: [github.com/qrizan/llm-posttraining-experiments](https://github.com/qrizan/llm-posttraining-experiments) | |