Text Generation
Transformers
Safetensors
English
Hindi
qwen3
text-to-sql
duckdb
india
open-government-data
conversational
text-generation-inference
Instructions to use judicialmind/BharatSQL-4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use judicialmind/BharatSQL-4B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="judicialmind/BharatSQL-4B") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("judicialmind/BharatSQL-4B") model = AutoModelForCausalLM.from_pretrained("judicialmind/BharatSQL-4B", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use judicialmind/BharatSQL-4B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "judicialmind/BharatSQL-4B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "judicialmind/BharatSQL-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/judicialmind/BharatSQL-4B
- SGLang
How to use judicialmind/BharatSQL-4B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "judicialmind/BharatSQL-4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "judicialmind/BharatSQL-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "judicialmind/BharatSQL-4B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "judicialmind/BharatSQL-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use judicialmind/BharatSQL-4B with Docker Model Runner:
docker model run hf.co/judicialmind/BharatSQL-4B
|
Download README.md from judicialmind/BharatSQL-4B: direct link, hf CLI and curl.
- Browser
- Download file 10.9 kB
-
https://huggingface.co/judicialmind/BharatSQL-4B/resolve/main/README.md
- Command line
-
hf download hf://judicialmind/BharatSQL-4B/README.md
-
curl -L -H "Authorization: Bearer $HF_TOKEN" -o README.md https://huggingface.co/judicialmind/BharatSQL-4B/resolve/main/README.md
10.9 kB
| license: cc-by-nc-sa-4.0 | |
| base_model: Qwen/Qwen3-4B-Instruct-2507 | |
| language: | |
| - en | |
| - hi | |
| library_name: transformers | |
| pipeline_tag: text-generation | |
| tags: | |
| - text-to-sql | |
| - duckdb | |
| - india | |
| - open-government-data | |
| - qwen3 | |
| datasets: | |
| - judicialmind/BharatSQL-Data | |
| extra_gated_prompt: 'This model is released under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 licence (CC | |
| BY-NC-SA 4.0): research, academic, personal and other non-commercial use is permitted with attribution; adaptations must | |
| be shared under the same licence; commercial use is not permitted. The original public source data remains under the Government | |
| Open Data License - India (GODL-India). Commercial use: contact surya@judicialmind.ai or hello@judicialmind.ai.' | |
| extra_gated_fields: | |
| Name: text | |
| Email: text | |
| Organization: text | |
| I accept the CC BY-NC-SA licence terms (research and non-commercial use only): checkbox | |
| extra_gated_button_content: Accept and request access | |
| # BharatSQL-4B | |
| <!-- jm:top --> | |
| Licence: CC BY-NC-SA 4.0 — research and non-commercial use only; derivatives must be shared under the same licence. Commercial use: contact surya@judicialmind.ai or hello@judicialmind.ai | |
| Access is approved automatically when the email you enter matches your Hugging Face account email and belongs to the organisation you name; other requests are reviewed manually. | |
| <!-- /jm:top --> | |
| A 4B text-to-SQL model (full fine-tune of Qwen/Qwen3-4B-Instruct-2507) that writes DuckDB SQL over tables from | |
| India's open government data (data.gov.in and NITI Aayog NDAP). Give it one or two table schemas and a question in | |
| English, Hindi or Hinglish; it replies with one DuckDB `SELECT` in a ```` ```sql ```` block. Run the SQL on the | |
| table to get the answer. | |
| **Headline result:** on the BharatSQL-Data test set (28,943 questions from unseen ministries and | |
| table layouts) BharatSQL-4B reaches **91.3% execution accuracy**, ahead of the 27B teacher Qwen3.8-27B-FP8 (83.9%) | |
| and its base model Qwen3-4B-Instruct-2507 (74.6%), and its SQL runs 99.8% of the time. | |
| ## Quickstart | |
| `infer.py` (in this repo) builds the prompt in the training format, generates greedily and runs the SQL in a | |
| read-only in-memory DuckDB connection. | |
| ```python | |
| import sys | |
| import pandas as pd | |
| from huggingface_hub import snapshot_download | |
| path = snapshot_download("judicialmind/BharatSQL-4B") # accept the terms on the Hub first | |
| sys.path.insert(0, path) | |
| from infer import BharatSQL, schema_ddl, run_sql | |
| # Tamil Nadu, "Classifications of Convicts (Prisons and Convicts) 2014-2015", data.gov.in resource 58261bea-8790-4a9c-ab26-6392a9ab2e09 | |
| df = pd.DataFrame({ | |
| "S.no": ["1", "2", "3", "4", "5", "6", "7", "Total"], | |
| "Classification of Convicts 2014-15": [ | |
| "Below one year", "Above one year and not exceeding two years", | |
| "Above two years and not exceeding five years", "Above five years and not exceeding ten years", | |
| "Exceeding ten years", "Life sentence", "Sentenced to Death", "Total"], | |
| "Male": [487, 195, 221, 683, 429, 2761, 7, 4783], | |
| "Female": [5, 4, 0, 22, 7, 120, 0, 158], | |
| "Total": [492, 199, 221, 705, 436, 2881, 7, 4941], | |
| }) | |
| name = "t_58261bea_8790_4a9c_ab26_6392a9ab2e09" | |
| ddl = schema_ddl(df, name, title="Classifications of Convicts (Prisons and Convicts) 2014-2015", | |
| publisher="Tamil Nadu", source="58261bea-8790-4a9c-ab26-6392a9ab2e09") | |
| print(ddl) | |
| model = BharatSQL(path) # bfloat16; GPU if available | |
| sql = model.generate_sql(ddl, "Tamil Nadu 2014-15 mein 'Below one year' classification ke kitne male convicts the?", | |
| max_new_tokens=128) | |
| print(sql) | |
| print(run_sql(sql, {name: df})) | |
| ``` | |
| Output: the schema prompt printed by `schema_ddl` | |
| ```sql | |
| -- Classifications of Convicts (Prisons and Convicts) 2014-2015 | Tamil Nadu | rows: 8 | source: 58261bea-8790-4a9c-ab26-6392a9ab2e09 | |
| CREATE TABLE t_58261bea_8790_4a9c_ab26_6392a9ab2e09 ( | |
| "S.no" VARCHAR, -- e.g. '1', '2', '3' | |
| "Classification of Convicts 2014-15" VARCHAR, -- e.g. 'Below one year', 'Above one year and not exceeding tw...', 'Above two years and not exceeding fi...' | |
| "Male" BIGINT, -- e.g. 487, 195, 221 | |
| "Female" BIGINT, -- e.g. 5, 4, 0 | |
| "Total" BIGINT -- e.g. 492, 199, 221 | |
| ); | |
| ``` | |
| the generated query | |
| ```sql | |
| SELECT "Male" FROM t_58261bea_8790_4a9c_ab26_6392a9ab2e09 WHERE "Classification of Convicts 2014-15" = 'Below one year' | |
| ``` | |
| and its result: | |
| **Query result** | |
| | Male | | |
| |---:| | |
| | 487 | | |
| CLI: `python infer.py --table my_table.csv --name t_my_table --title "..." --publisher "..." --question "..."`. | |
| ### Prompt format | |
| Two chat messages, applied with the model's chat template (Qwen3 non-thinking format): | |
| - **system**: `You are BharatSQL. Given DuckDB table schemas from India's open government data and a question (English, Hindi or Hinglish), write one DuckDB SELECT query that answers it. Quote column names with double quotes. Reply with the SQL in a ```sql code block and nothing else.` | |
| - **user**: `Tables:\n<schema>\n\nQuestion: <question>` | |
| `<schema>` is one `CREATE TABLE` block per table (two tables are separated by a blank line), as produced by | |
| `infer.schema_ddl`: | |
| ``` | |
| -- <title> | <publisher> | rows: <row count> | source: <resource id> | |
| CREATE TABLE t_<resource id> ( | |
| "<column>" <VARCHAR|BIGINT|DOUBLE|BOOLEAN|DATE|TIMESTAMP>, -- e.g. <up to 3 example values; strings quoted, cut to 40 chars> | |
| ... | |
| ); | |
| ``` | |
| Table names are `t_` + the resource id with non-alphanumerics replaced by `_`; column names are quoted exactly as in | |
| the table. Use 3 example values per column for one table and 2 per table for a two-table question. | |
| **Output**: one fenced block, e.g. ```` ```sql\nSELECT ... \n``` ````. `infer.extract_sql(reply)` returns the SQL. | |
| Decode greedily (temperature 0); the reported numbers use greedy decoding with up to 512 new tokens. | |
| ### transformers only | |
| ```python | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| tok = AutoTokenizer.from_pretrained("judicialmind/BharatSQL-4B") | |
| lm = AutoModelForCausalLM.from_pretrained("judicialmind/BharatSQL-4B", dtype="bfloat16", device_map="auto") | |
| messages = [ | |
| {"role": "system", "content": "You are BharatSQL. Given DuckDB table schemas from India's open government data and a question (English, Hindi or Hinglish), write one DuckDB SELECT query that answers it. Quote column names with double quotes. Reply with the SQL in a ```sql code block and nothing else."}, | |
| {"role": "user", "content": f"Tables:\n{ddl}\n\nQuestion: {question}"}, | |
| ] | |
| enc = tok.apply_chat_template(messages, add_generation_prompt=True, return_tensors="pt", return_dict=True).to(lm.device) | |
| out = lm.generate(**enc, max_new_tokens=512, do_sample=False) | |
| print(tok.decode(out[0, enc["input_ids"].shape[1]:], skip_special_tokens=True)) | |
| ``` | |
| ### vLLM | |
| ```python | |
| from vllm import LLM, SamplingParams | |
| from infer import build_messages, extract_sql | |
| llm = LLM("judicialmind/BharatSQL-4B", max_model_len=8192) | |
| outs = llm.chat([build_messages(ddl, q) for q in questions], SamplingParams(temperature=0.0, max_tokens=512)) | |
| sqls = [extract_sql(o.outputs[0].text) for o in outs] | |
| ``` | |
| OpenAI-compatible server: `vllm serve judicialmind/BharatSQL-4B --max-model-len 8192`, then send the two messages | |
| above to `/v1/chat/completions` with `temperature: 0`. | |
| ## Files | |
| | file | contents | | |
| |---|---| | |
| | `model.safetensors`, `config.json`, `generation_config.json` | weights (bfloat16) and config | | |
| | `tokenizer.json`, `tokenizer_config.json`, `chat_template.jinja` | tokenizer and chat template | | |
| | `infer.py` | prompt builder (`schema_ddl`, `build_messages`), `BharatSQL` generator, `extract_sql`, `run_sql` (DuckDB), CLI | | |
| | `requirements.txt` | pinned runtime dependencies (`vllm` optional) | | |
| ## Results | |
| Execution accuracy on the BharatSQL-Data test set: 28,943 questions from 61 held-out ministries and held-out table | |
| templates (no ministry or table layout in test was seen in training). A prediction is correct when its result | |
| rows equal the gold SQL's result rows (column order ignored). | |
| | model | test set | n | exec acc | SQL runs | | |
| |---|---|---|---|---| | |
| | BharatSQL-4B | test | 28,943 | 91.3% | 99.8% | | |
| | Qwen3.8-27B-FP8 (zero-shot) | test | 28,943 | 83.9% | 99.7% | | |
| | Qwen3-4B-Instruct-2507 (zero-shot) | test | 28,943 | 74.6% | 97.2% | | |
| | BharatSQL-4B by group | n | exec acc | | |
| |---|---|---| | |
| | lookup | 8,918 | 95.8% | | |
| | aggregate | 9,821 | 92.7% | | |
| | multi_step | 10,204 | 86.1% | | |
| | English | 17,876 | 91.4% | | |
| | Hindi | 5,372 | 91.5% | | |
| | Hinglish | 5,695 | 91.1% | | |
| | two-table LGD join | 462 | 42.6% | | |
| The test tables, the predictions of all three models and the scoring script (`evaluate.py`) are in | |
| [judicialmind/BharatSQL-Data](https://huggingface.co/datasets/judicialmind/BharatSQL-Data); `python evaluate.py | |
| --predictions predictions/BharatSQL-4B.parquet` reproduces the 91.3%. | |
| ## Coverage | |
| Trained on the train split of BharatSQL-Data (230,976 execution-checked question/SQL pairs) over data.gov.in and NDAP tables (snapshot May 2026) from | |
| 113 ministries, departments and States; questions in English, Hindi (Devanagari) and Hinglish. Single-table | |
| questions plus two-table joins on LGD district/State codes. | |
| ## Source data | |
| Training tables come from the Open Government Data Platform India (data.gov.in) and NITI Aayog NDAP under the | |
| Government Open Data License - India; per-table attribution is in `judicialmind/BharatSQL-Data`. | |
| <!-- jm:source --> | |
| Original data: published by the ministries, departments and State governments named per table / resource in this release on the Open Government Data Platform India ([data.gov.in](https://data.gov.in)) and, where marked, NITI Aayog's National Data and Analytics Platform ([NDAP](https://ndap.niti.gov.in)), under the [Government Open Data License - India](https://data.gov.in/government-open-data-license-india) (GODL-India). The original public data remains under GODL-India; the CC BY-NC-SA 4.0 licence of this repository covers JudicialMind's compilation, derived fields, annotations, benchmarks and models. | |
| <!-- /jm:source --> | |
| ## Citation | |
| ```bibtex | |
| @misc{judicialmind2026bharatsql4b, | |
| title={BharatSQL-4B: Text-to-SQL over Indian open government data}, | |
| author={JudicialMind}, | |
| year={2026}, | |
| publisher={Hugging Face}, | |
| howpublished={\url{https://huggingface.co/judicialmind/BharatSQL-4B}} | |
| } | |
| ``` | |
| <!-- jm:license --> | |
| ## License | |
| [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) (see `LICENSE`): research, academic, personal and other non-commercial use, with attribution to JudicialMind and to the original data publishers; adaptations must be shared under the same licence. Commercial use requires a separate licence. | |
| Commercial use: contact surya@judicialmind.ai or hello@judicialmind.ai. | |
| Base model(s): `Qwen/Qwen3-4B-Instruct-2507` (apache-2.0). Their licence terms and notices continue to apply to the upstream components; see `THIRD_PARTY_NOTICES.md`. | |
| <!-- /jm:license --> | |