End-to-end fine-tuning of bert-base-multilingual-cased on a 500k-document multilingual corpus for real-time sentiment classification. Served via an async FastAPI inference server with sub-80ms latency at P95.
This pipeline fine-tunes bert-base-multilingual-cased (110M parameters) on a 500k-document multilingual dataset spanning six languages for three-class sentiment classification (negative, neutral, positive). The model achieves a 92.1% Macro F1-score — outperforming monolingual baselines such as RoBERTa-base.
The inference server supports both single predictions and async batch processing, with MLflow tracking all experiments. Class imbalance is handled through weighted random sampling rather than post-hoc reweighting.
Tokenization with bert-base-multilingual-cased tokenizer. Max sequence length 128. Weighted random sampling for class balance.
Hugging Face Trainer API. 4 epochs, AdamW with linear warmup (10%) + linear decay. Gradient accumulation ×2.
Macro F1-Score, Accuracy, AUC-ROC, and per-class metrics across all 6 supported languages.
FastAPI server with async batching. Single prediction + batch endpoints. Sub-80ms P95 latency on single GPU.
MLflow for all training runs — metrics, hyperparameters, model artifacts, and comparison across baselines.
Dockerized for reproducibility. Mount model outputs volume to persist fine-tuned checkpoints.
bert-base-multilingual-casedpip install -r requirements.txt
CSV with columns: text, label (0=negative, 1=neutral, 2=positive), language
python src/train.py \
--train_file data/train.csv \
--val_file data/val.csv \
--output_dir outputs/ \
--epochs 4 \
--batch_size 32
python src/evaluate.py \
--model_dir outputs/ \
--test_file data/test.csv
uvicorn src.api:app --host 0.0.0.0 --port 8000
docker build -t bert-sentiment .
docker run -p 8000:8000 -v $(pwd)/outputs:/app/outputs bert-sentiment
import requests
# Single prediction
r = requests.post("http://localhost:8000/predict", json={
"text": "This product exceeded all my expectations!",
"language": "en"
})
print(r.json())
# {"label": "positive", "confidence": 0.9821, "scores": {"negative": 0.007, "neutral": 0.011, "positive": 0.982}}
# Batch prediction
r = requests.post("http://localhost:8000/predict/batch", json={
"texts": ["Great!", "Terrible experience.", "It was okay."]
})