Downloads · 30 days
11
10% of all-time downloads
lennarddaw/howzer-risk-scorer
howzer-risk-scorer is a tabular classification model from lennarddaw. Use it for the tabular classification task on the model card, and read the license before you ship it in a product. It is set up for onnxruntime. The card lists the license as apache-2.0.
A lightweight MLP model (80K parameters) that scores customer feedback risk across multiple dimensions. Designed for German-language customer service contexts (e.g., automobile clubs, insurance).
Downloads · 30 days
11
10% of all-time downloads
All-time downloads
114
Public
Parameters
80.9K
665 KB on disk
Likes
2
Public
Click a slice to open those files.
.onnx338 KB · 49%
From the Hugging Face model README
A lightweight MLP model (80K parameters) that scores customer feedback risk across multiple dimensions. Designed for German-language customer service contexts (e.g., automobile clubs, insurance).
HowzerRiskScorer replaces a 2,000-line rule-based risk engine with a learned model that takes pre-computed NLP pipeline features and outputs multi-dimensional risk scores.
Architecture: MLP with BatchNorm + GELU + Dropout (256 → 128 → 64) with multi-head outputs.
| Property | Value |
|---|---|
| Parameters | 79,978 |
| Input | 120-dim feature vector |
| Training data | 4,351 German customer feedback samples |
| Training framework | PyTorch (manual loop) |
| Export formats | ONNX, SafeTensors |
The model expects a pre-computed feature vector from an upstream NLP pipeline:
| Group | Dims | Source |
|---|---|---|
| Sentiment scores + confidence | 4 | Sentiment classifier (e.g., german-sentiment-bert) |
| Emotion scores (27 GoEmotions) | 27 | Emotion classifier (e.g., mDeBERTa) |
| Root cause (top-5 scores + one-hot) | 35 | Root cause analyzer (e.g., E5 embeddings) |
| Customer history | 10 | CRM system |
| Channel (one-hot) | 9 | Input metadata |
| Text metadata | 6 | Text statistics |
| Derived interaction features | 29 | Computed from above |
| Output | Shape | Range | Description |
|---|---|---|---|
global_risk | (1,) | 0.0-1.0 | Overall risk score |
tier_logits | (4,) | logits | Risk tier: low/medium/high/critical |
escalation | (1,) | 0.0-1.0 | Escalation likelihood |
churn | (1,) | 0.0-1.0 | Customer churn risk |
brand | (1,) | 0.0-1.0 | Brand/reputation risk |
revenue | (1,) | 0.0-1.0 | Financial/revenue risk |
confidence | (1,) | 0.0-1.0 | Calibrated prediction confidence |
Tier thresholds: critical ≥ 0.88, high ≥ 0.72, medium ≥ 0.38, low < 0.38
Evaluated on a held-out test set (437 samples) of German customer feedback:
| Metric | MLP v0.4 | XGBoost | Target |
|---|---|---|---|
| Tier F1 (weighted) | 0.850 | 0.860 | > 0.80 ✅ |
| Tier F1 (critical) | 0.250 | 0.222 | > 0.70 ❌ |
| Score MAE | 0.078 | 0.082 | < 0.08 ✅ |
| Score MSE | 0.023 | 0.021 | < 0.02 ❌ |
| Calibration ECE | 0.020 | 0.051 | < 0.05 ✅ |
| Tier | F1 Score | Test Samples |
|---|---|---|
| Low | 0.923 | 365 |
| Medium | 0.174 | 19 |
| High | 0.649 | 45 |
| Critical | 0.250 | 8 |
import numpy as np
import onnxruntime as ort
session = ort.InferenceSession("howzer_risk_scorer.onnx")
features = np.random.randn(1, 120).astype(np.float32) # your feature vector
outputs = session.run(None, {"features": features})
escalation, churn, brand, revenue, global_risk, tier_logits, confidence = outputs
tier_names = ["low", "medium", "high", "critical"]
predicted_tier = tier_names[tier_logits[0].argmax()]
print(f"Risk: {global_risk[0,0]:.3f}, Tier: {predicted_tier}")
from inference import RiskScorer
scorer = RiskScorer.from_onnx("howzer_risk_scorer.onnx")
result = scorer.predict(features) # returns RiskAssessment dataclass
print(f"Global risk: {result.global_risk:.3f}")
print(f"Tier: {result.tier} (confidence: {result.confidence:.3f})")
print(f"Components: esc={result.escalation:.3f}, churn={result.churn:.3f}")
import torch
from src.model.risk_scorer import HowzerRiskScorer
model = HowzerRiskScorer(input_dim=120, hidden_dims=(256, 128, 64))
model.load_state_dict(torch.load("model.safetensors"))
model.eval()
with torch.no_grad():
preds = model(torch.randn(1, 120))
print(f"Risk: {preds['global_risk'].item():.3f}")
We compared the 80K-parameter MLP against general-purpose LLMs on the same risk scoring task. LLMs received the raw German feedback text and were prompted to produce structured risk assessments.
| Model | Params | F1 (weighted) | Accuracy | Score MAE | Latency/sample |
|---|---|---|---|---|---|
| MLP v0.4 | 80K | 0.843 | 0.880 | 0.084 | ~0.001s |
| XGBoost | - | 0.852 | 0.880 | 0.082 | ~0.01s |
| qwen2.5:7b | 7B | 0.083 | 0.080 | 0.614 | 27s |
| llama3-german-instruct | 8B | 0.136 | 0.140 | 0.568 | 35s |
Key findings:
Benchmark on 50 German customer feedback samples. LLMs were prompted with text only; MLP used pre-computed pipeline features.
| File | Size | Description |
|---|---|---|
howzer_risk_scorer.onnx | 330 KB | ONNX model (opset 17) |
model.safetensors | 319 KB | PyTorch weights |
config.json | 1 KB | Model configuration |
inference.py | 4 KB | Python inference helper |
@misc{howzer-risk-scorer-2026,
title={HowzerRiskScorer: Learned Customer Feedback Risk Assessment},
year={2026},
publisher={Hugging Face},
}