What changed in v3
v1 was trained on 15 cities of synthetic geography and failed on real-style addresses (about 58% on a
stress set I wrote by hand). v3 is trained on addresses whose locality, pincode, district and state come
from the real India Post pincode directory (156k localities, Tamil Nadu over-sampled to 44%), so the model
learns real pincode / district / state relationships. The previous version stays in this repo's git history.
Conventions (important)
city = the district name (or the metro name for big cities), e.g. a village in Karur district gets
"city": "Karur". If your application wants the town the customer wrote, post-process or use another model.
area = locality / village / post-office name. flat = the door / house / plot number only.
- Anything not written in the address is an empty string. The model is trained not to guess a city that
is not stated.
Results
Held-out synthetic test (800 addresses). Exact match after lower-casing and removing . and ,.
Table with columns: Slice, Full record match| Slice | Full record match |
|---|
| All (n=800) | 94.4% |
| Locality drawn from the training pool (n=300; most were still never trained on) | 95.0% |
| Localities never seen (n=300) | 94.7% |
| Whole districts never seen (n=200: Ariyalur, Tenkasi, Udupi, Wayanad, Satara, Mathura) | 93.0% |
Table with columns: Field, Accuracy| Field | Accuracy |
|---|
| flat | 100.0% |
| building | 99.9% |
| street | 99.8% |
| landmark | 99.5% |
| area | 96.1% |
| city | 97.0% |
| state | 98.5% |
| pincode | 100% |
| phone | 100% |
| valid JSON | 100% |
Hand-written checks (read the caveats)
Table with columns: Set, Result| Set | Result |
|---|
| 30 Tamil Nadu addresses | 29 / 30 (96.7%); the miss: 15 Gandhi Salai, Tirupur 641601 → flat left empty |
| 36 mixed-India addresses written before v2 (city = the town written) | 80.6% (city 88.9%) |
Caveats. The Tamil Nadu set was written by the model author after designing the generator, using the
same conventions and vocabulary, so it shows the anticipated patterns work; it is not an independent
benchmark. Scores come from the published weights (one training run; a second run of the same recipe
differed by a few tenths of a point). The 36-address set uses the town as city, which differs from v3's district convention, so part
of that gap is the convention. Neither set contains real customer addresses.
Usage
import json, torchfrom transformers import AutoModelForCausalLM, AutoTokenizer repo = "abr-6024/indian-address-parser-1.5B"tok = AutoTokenizer.from_pretrained(repo)model = AutoModelForCausalLM.from_pretrained(repo, dtype=torch.float16, device_map="auto") SYSTEM = ("You are an Indian address parser. Convert the address into JSON with exactly these keys: " "flat, building, street, landmark, area, city, state, pincode, phone. " "Use an empty string for anything missing. Output only JSON.")msgs = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": "Flat 3B, Sri Murugan Apartments, Peelamedu, Coimbatore 641004"}]ids = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device)out = model.generate(ids, max_new_tokens=200, do_sample=False)print(json.loads(tok.decode(out[0][ids.shape[1]:], skip_special_tokens=True)))
Use the exact system prompt above; the model was trained with it. eval.py in this repo reproduces the scores.
Run it on a laptop (no GPU)
Python (3.9+; the first call downloads the 1 GB model once, then it works offline):
pip install india-address-parser
from india_address_parser import parseparse("D.No 14/2, Gandhi Road, Pollachi, Coimbatore - 642001")
Node.js (18+; needs Ollama running, or use the HTTP API below):
npm install india-address-parsernpx india-address-parser --pull # downloads the model into Ollama, oncenpx india-address-parser "Flat 6, Kaveri Residency, Gandhipuram, Coimbatore 641012"
As an HTTP API (any language, no Ollama)
pip install "india-address-parser[server]"ADDRESS_API_KEY=choose-a-secret india-address-parser serve --port 8000curl -X POST http://localhost:8000/parse -H "Authorization: Bearer choose-a-secret" -H "Content-Type: application/json" -d '{"address": "D.No 14/2, Gandhi Road, Pollachi, Coimbatore - 642001"}'
Endpoints: /parse, /parse_batch (up to 100), /health. A Dockerfile is in the
GitHub repo. From Node:
parseAddress(address, { apiUrl: "http://localhost:8000", apiKey: "choose-a-secret" }). About 3 seconds per address on a
laptop CPU, so it suits emails, imports and confirmation steps better than blocking a checkout. You host it yourself;
addresses are personal data, so set an API key before exposing it.
Ollama directly: ollama pull hf.co/abr-6024/indian-address-parser-1.5B-GGUF:Q4_K_M
The quantized files scored the same as these weights within noise on my test sets (details on the GGUF card).
Training
- LoRA (r=16, alpha=32, all linear layers) merged into the base weights; 2 epochs, 9,000 examples,
completion-only loss, fp16 on a free Colab T4.
- Data, generator and cleaning script: abr-6024/indian-address-parsing-synthetic.
Limitations
- Synthetic text over real geography. House numbers, buildings, streets, landmarks and wording are
generated. Accuracy on real customer addresses has not been measured and will likely be lower.
Evaluate on your own data before relying on it.
- Pincodes are extracted, not validated against the locality.
- Localities that are not post-office names (neighbourhoods, apartment complexes) are only as good as the
model's copying; spelling variants of unseen places are not corrected.
- Bare-number addresses (
25 Mount Road) are a known weak spot: in my hand-written check the model dropped the
number from 15 Gandhi Salai, Tirupur 641601. Building names without a common suffix are also not guaranteed.
- English / Latin script only.
Data attribution
Contains information from the All India Pincode Directory, Department of Posts, Government of India,
published on data.gov.in and listed under the Government Open Data License – India (GODL-India). The
directory was obtained through a public GitHub mirror (dropdevrahul/pincodes-india); check the current
terms at data.gov.in before reusing the data.
License and credit
Model weights: Apache-2.0, inherited from Qwen2.5-1.5B-Instruct. Credit to the Qwen team for the base model.