Downloads · 30 days
13
13% of all-time downloads
TatarNLPWorld/rubert-large-tatar-toponyms-qa
rubert-large-tatar-toponyms-qa is a question answering model from TatarNLPWorld. Use it when the input is a question plus a passage. It is set up for transformers. The card lists the license as cc-by-sa-4.0.
RuBERT large fine-tuned for question answering on Tatarstan toponyms. This model requires simple post-processing for coordinates to achieve optimal results.
Downloads · 30 days
13
13% of all-time downloads
All-time downloads
103
Public
Parameters
178M
711 MB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors711 MB · 99%
From the Hugging Face model README
RuBERT large fine-tuned for question answering on Tatarstan toponyms. This model requires simple post-processing for coordinates to achieve optimal results.
This model is fine-tuned from Den4ikAI/rubert_large_squad_2 on a synthetic dataset of 38,696 QA pairs about Tatarstan geographical names.
This model adds extra spaces in coordinate answers (e.g., "55. 175195" instead of "55.175195"). This is a known behavior of RuBERT tokenizers. Use the simple normalization function below to fix this.
| Metric | Score | 95% CI |
|---|---|---|
| Exact Match | 0.398 | [0.356, 0.442] |
| F1 Score | 0.679 | [0.645, 0.712] |
| Metric | Score |
|---|---|
| Exact Match | 1.000 |
| F1 Score | 1.000 |
| Question Type | F1 Score | Notes |
|---|---|---|
| Coordinates | 1.000 | Requires space removal |
| Location | 1.000 | Requires post-processing |
| Etymology | 1.000 | Works perfectly |
| Type | 1.000 | Works perfectly |
| Region | 1.000 | Works perfectly |
| Sources | 1.000 | Works perfectly |
Add this after getting predictions from the model:
import re
def normalize_answer(text, question_type="coordinates"):
"""
Simple normalization for RuBERT models
"""
# Fix coordinates: "55. 175195" -> "55.175195"
if question_type == "coordinates":
text = re.sub(r'(\d+)\.\s+(\d+)', r'\1.\2', text)
text = re.sub(r'(\d+)\s+\.\s*(\d+)', r'\1.\2', text)
# Fix location: "северо - западу" -> "северо-западу"
if question_type == "location":
text = re.sub(r'\s*-\s*', '-', text)
text = re.sub(r'\(\s+', '(', text)
text = re.sub(r'\s+\)', ')', text)
return text
# Example usage
predicted = "55. 175195, 58. 709845" # raw model output
normalized = normalize_answer(predicted, "coordinates")
print(normalized) # "55.175195, 58.709845" ✅
from transformers import pipeline
import re
# Load model
qa_pipeline = pipeline(
"question-answering",
model="TatarNLPWorld/rubert-large-tatar-toponyms-qa"
)
# Normalization function
def normalize_answer(text, question_type="coordinates"):
if question_type == "coordinates":
text = re.sub(r'(\d+)\.\s+(\d+)', r'\1.\2', text)
text = re.sub(r'(\d+)\s+\.\s*(\d+)', r'\1.\2', text)
if question_type == "location":
text = re.sub(r'\s*-\s*', '-', text)
text = re.sub(r'\(\s+', '(', text)
text = re.sub(r'\s+\)', ')', text)
return text
# Example
context = """
Название (рус): Рантамак | Объект: Село |
Расположение: на р. Мелля, в 21 км к востоку от с. Сарманово |
Координаты: 55.205461, 52.881862
"""
questions = [
("Где находится Рантамак?", "location"),
("Какие координаты у Рантамак?", "coordinates"),
("Что такое Рантамак?", "type")
]
for question, qtype in questions:
result = qa_pipeline(question=question, context=context)
normalized = normalize_answer(result['answer'], qtype)
print(f"Q: {question}")
print(f"A (raw): {result['answer']}")
print(f"A (norm): {normalized}")
print(f"Confidence: {result['score']:.3f}\n")
from transformers import AutoTokenizer, AutoModelForQuestionAnswering
import torch
import re
# Load model
tokenizer = AutoTokenizer.from_pretrained("TatarNLPWorld/rubert-large-tatar-toponyms-qa")
model = AutoModelForQuestionAnswering.from_pretrained("TatarNLPWorld/rubert-large-tatar-toponyms-qa")
device = "cuda" if torch.cuda.is_available() else "cpu"
model = model.to(device)
# Normalization function
def normalize_answer(text, question_type="coordinates"):
if question_type == "coordinates":
text = re.sub(r'(\d+)\.\s+(\d+)', r'\1.\2', text)
text = re.sub(r'(\d+)\s+\.\s*(\d+)', r'\1.\2', text)
return text
# Inference
inputs = tokenizer(question, context, return_tensors="pt").to(device)
with torch.no_grad():
outputs = model(**inputs)
start_idx = torch.argmax(outputs.start_logits)
end_idx = torch.argmax(outputs.end_logits)
answer = tokenizer.decode(inputs["input_ids"][0][start_idx:end_idx+1], skip_special_tokens=True)
normalized = normalize_answer(answer, "coordinates")
print(f"Answer: {normalized}")
| Parameter | Value |
|---|---|
| Base model | Den4ikAI/rubert_large_squad_2 |
| Epochs | 3 |
| Learning rate | 3e-5 |
| Batch size | 4 |
| Max sequence length | 384 |
| Optimizer | AdamW |
| Warmup steps | 500 |
| Weight decay | 0.01 |
| Hardware | NVIDIA GPU |
Problem: Model outputs "55. 175195" instead of "55.175195"
Solution:
import re
text = re.sub(r'(\d+)\.\s+(\d+)', r'\1.\2', text)
Problem: "северо - западу" instead of "северо-западу"
Solution:
text = re.sub(r'\s*-\s*', '-', text)
Problem: "( текст )" instead of "(текст)"
Solution:
text = re.sub(r'\(\s+', '(', text)
text = re.sub(r'\s+\)', ')', text)
| Model | F1 Score (raw) | F1 Score (norm) | Speed |
|---|---|---|---|
| xlm-roberta-large | 0.994 | 0.994 | 22.4ms |
| rubert-base | 0.684 | 1.000 | 6.6ms |
| rubert-large (this model) | 0.679 | 1.000 | 6.5ms |
| Aspect | XLM-RoBERTa Large | RuBERT Large |
|---|---|---|
| Raw Accuracy | 99.4% | 67.9% |
| With Normalization | 99.4% | 100% |
| Speed | 22.4ms | 6.5ms |
| Post-processing | Not needed | Required |
| Memory Usage | Higher | Lower |
If you use this model in your research, please cite:
@model{rubert_large_tatar_toponyms_qa,
author = {Arabov, Mullosharaf Kurbonvoich},
title = {RuBERT Large for Tatar Toponyms QA},
year = {2026},
publisher = {Hugging Face},
howpublished = {\url{https://huggingface.co/TatarNLPWorld/rubert-large-tatar-toponyms-qa}}
}
Contributions welcome! Please:
📅 Version: 1.0.0 | 📅 Published: 2026-03-10 | ⚡ Speed: 6.5ms | 🔧 Post-processing: Required