Downloads · 30 days
57
5% of all-time downloads
shiprocket-ai/open-modernbert-indian-address-ner
open-modernbert-indian-address-ner is a machine learning model from shiprocket-ai. Use it for the machine learning task on the model card, and read the license before you ship it in a product.
This model is a fine-tuned ModernBERT for Named Entity Recognition (NER) on Indian addresses. It can extract and classify various address components from Indian address text with high accuracy, leveraging ModernBERT's…
Downloads · 30 days
57
5% of all-time downloads
All-time downloads
1.1K
Public
Parameters
150M
3.6 GB on disk
Likes
2
Public
Click a slice to open those files.
.pt1.2 GB · 67%
From the Hugging Face model README
This model is a fine-tuned ModernBERT for Named Entity Recognition (NER) on Indian addresses. It can extract and classify various address components from Indian address text with high accuracy, leveraging ModernBERT's state-of-the-art architecture and improved efficiency.
ModernBERT fine-tuned for Indian address Named Entity Recognition (NER)
import torch
from transformers import AutoTokenizer, AutoModelForTokenClassification
import warnings
warnings.filterwarnings("ignore")
class IndianAddressNER:
def __init__(self):
model_name = "shiprocket-ai/open-modernbert-indian-address-ner"
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModelForTokenClassification.from_pretrained(model_name)
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.model.to(self.device)
self.model.eval()
# Entity mappings
self.id2entity = {
"0": "O",
"1": "B-building_name",
"2": "I-building_name",
"3": "B-city",
"4": "I-city",
"5": "B-country",
"6": "I-country",
"7": "B-floor",
"8": "I-floor",
"9": "B-house_details",
"10": "I-house_details",
"11": "B-locality",
"12": "I-locality",
"13": "B-pincode",
"14": "I-pincode",
"15": "B-road",
"16": "I-road",
"17": "B-state",
"18": "I-state",
"19": "B-sub_locality",
"20": "I-sub_locality",
"21": "B-landmarks",
"22": "I-landmarks"
}
def predict(self, address):
"""Extract entities from an Indian address - FIXED VERSION"""
if not address.strip():
return {}
# Tokenize with offset mapping for better text reconstruction
inputs = self.tokenizer(
address,
return_tensors="pt",
truncation=True,
padding=True,
max_length=128,
return_offsets_mapping=True
)
# Extract offset mapping before moving to device
offset_mapping = inputs.pop("offset_mapping")[0]
inputs = {k: v.to(self.device) for k, v in inputs.items()}
# Predict
with torch.no_grad():
outputs = self.model(**inputs)
predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
predicted_ids = torch.argmax(predictions, dim=-1)
confidence_scores = torch.max(predictions, dim=-1)[0]
# Extract entities using offset mapping
entities = self.extract_entities_with_offsets(
address,
predicted_ids[0],
confidence_scores[0],
offset_mapping
)
return entities
def extract_entities_with_offsets(self, original_text, predicted_ids, confidences, offset_mapping):
"""Extract entities using offset mapping for accurate text reconstruction"""
entities = {}
current_entity = None
for i, (pred_id, conf) in enumerate(zip(predicted_ids, confidences)):
if i >= len(offset_mapping):
break
start, end = offset_mapping[i]
# Skip special tokens (they have (0,0) mapping)
if start == end == 0:
continue
label = self.id2entity.get(str(pred_id.item()), "O")
if label.startswith("B-"):
# Save previous entity
if current_entity:
entity_type = current_entity["type"]
if entity_type not in entities:
entities[entity_type] = []
entities[entity_type].append({
"text": current_entity["text"],
"confidence": current_entity["confidence"]
})
# Start new entity
entity_type = label[2:] # Remove "B-"
current_entity = {
"type": entity_type,
"text": original_text[start:end],
"confidence": conf.item(),
"start": start,
"end": end
}
elif label.startswith("I-") and current_entity:
# Continue current entity
entity_type = label[2:] # Remove "I-"
if entity_type == current_entity["type"]:
# Extend the entity to include this token
current_entity["text"] = original_text[current_entity["start"]:end]
current_entity["confidence"] = (current_entity["confidence"] + conf.item()) / 2
current_entity["end"] = end
elif label == "O" and current_entity:
# End current entity
entity_type = current_entity["type"]
if entity_type not in entities:
entities[entity_type] = []
entities[entity_type].append({
"text": current_entity["text"],
"confidence": current_entity["confidence"]
})
current_entity = None
# Add final entity if exists
if current_entity:
entity_type = current_entity["type"]
if entity_type not in entities:
entities[entity_type] = []
entities[entity_type].append({
"text": current_entity["text"],
"confidence": current_entity["confidence"]
})
return entities
# Usage example
ner = IndianAddressNER()
# Test addresses
test_addresses = [
"Shop No 123, Sunshine Apartments, Andheri West, Mumbai, 400058",
"DLF Cyber City, Sector 25, Gurgaon, Haryana",
"Flat 201, MG Road, Bangalore, Karnataka, 560001",
"Phoenix Mall, Kurla West, Mumbai"
]
print("🏠 INDIAN ADDRESS NER EXAMPLES")
print("=" * 50)
for address in test_addresses:
print(f"\n📍 Address: {address}")
entities = ner.predict(address)
if entities:
for entity_type, entity_list in sorted(entities.items()):
print(f"🏷️ {entity_type.replace('_', ' ').title()}:")
for entity in entity_list:
confidence = entity['confidence']
text = entity['text']
confidence_icon = "🟢" if confidence > 0.8 else "🟡" if confidence > 0.6 else "🔴"
print(f" {confidence_icon} {text} (confidence: {confidence:.3f})")
else:
print("❌ No entities found")
print("-" * 40)
The model can identify and extract the following address components:
The model uses BIO (Begin-Inside-Outside) tagging scheme:
{
"entity2id": {
"O": 0,
"B-building_name": 1,
"I-building_name": 2,
"B-city": 3,
"I-city": 4,
"B-country": 5,
"I-country": 6,
"B-floor": 7,
"I-floor": 8,
"B-house_details": 9,
"I-house_details": 10,
"B-locality": 11,
"I-locality": 12,
"B-pincode": 13,
"I-pincode": 14,
"B-road": 15,
"I-road": 16,
"B-state": 17,
"I-state": 18,
"B-sub_locality": 19,
"I-sub_locality": 20,
"B-landmarks": 21,
"I-landmarks": 22
},
"id2entity": {
"0": "O",
"1": "B-building_name",
"2": "I-building_name",
"3": "B-city",
"4": "I-city",
"5": "B-country",
"6": "I-country",
"7": "B-floor",
"8": "I-floor",
"9": "B-house_details",
"10": "I-house_details",
"11": "B-locality",
"12": "I-locality",
"13": "B-pincode",
"14": "I-pincode",
"15": "B-road",
"16": "I-road",
"17": "B-state",
"18": "I-state",
"19": "B-sub_locality",
"20": "I-sub_locality",
"21": "B-landmarks",
"22": "I-landmarks"
}
}
config.json: Model configuration and hyperparameterspytorch_model.bin / model.safetensors: Model weightstokenizer.json: Tokenizer configurationtokenizer_config.json: Tokenizer settingsvocab.txt: Vocabulary fileentity_mappings.json: Entity type mappingsIf you use this model in your research or applications, please cite:
@misc{open-modernbert-indian-address-ner,
title={ModernBERT Indian Address NER Model},
year={2025},
publisher={Hugging Face},
url={https://huggingface.co/shiprocket-ai/open-modernbert-indian-address-ner}
}
For questions, issues, or feature requests:
This model is released under the Apache 2.0 License. See LICENSE file for details.
Specialized for Indian address entity recognition - Built with ❤️ by shiprocket-ai team using ModernBERT