How to use from the
Use from the
Transformers library
# Gated model: Login with a HF token with gated access permission
hf auth login
# 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]:]))
Quick Links

You need to agree to share your contact information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

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.

Log in or Sign Up to review the conditions and access this model content.

BharatSQL-4B

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.

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.

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

-- 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

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

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

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; 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.

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) and, where marked, NITI Aayog's National Data and Analytics Platform (NDAP), under the 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.

Citation

@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}}
}

License

CC 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.

Downloads last month
-
Safetensors
Model size
4B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for judicialmind/BharatSQL-4B

Finetuned
(2544)
this model

Dataset used to train judicialmind/BharatSQL-4B

Collection including judicialmind/BharatSQL-4B