Read between the lines of Japanese business communication.
Japanese business language wraps strong negative feelings in layers of extreme politeness. A flat translation misses what a native reader immediately feels, Keigo Radar quantifies that gap.
Live demo · API on Hugging Face Spaces
| Signal | Method |
|---|---|
| Keigo register (teineigo / kenjougo / sonkeigo / plain) | Rule-based morphological analysis via fugashi + unidic |
| Negative emotional intensity (none / mild / moderate / strong) | BERT fine-tuned on WRIME — 35k social posts |
| Soft refusal patterns — phrases that mean "no" without saying it | Curated phrase list, 20+ patterns |
| Masking gap — high-formality surface hiding real frustration | register ∈ {kenjougo, sonkeigo} AND intensity ≥ moderate |
| Translation + implied meaning | Llama 3.1 8b via Groq (server-side) |
In Japanese business communication, sentences like:
大変申し訳ございませんが、今回のご提案には正直失望しており、再考は難しいと存じます
read literally as a polite apology. A BERT model trained on emotional intensity data reads the same sentence as strong negative tension , the signal you'd expect from an angry social-media post, wrapped in maximum-register keigo.
That disconnect: high formality surface + high negative undertone is the masking gap.
Browser
│
└─► Vercel (Next.js 15)
│
├─ /api/translate ──────────────────► Groq API (server-side, key never exposed)
│ Llama 3.1 8b · translation + subtext note
│
└─ NEXT_PUBLIC_API_URL ─────────────► Hugging Face Spaces (FastAPI + Docker)
├─ Keigo register classifier (rule-based)
├─ BERT negative intensity model
└─ Soft refusal pattern matcher
# Python 3.10+
pip install -r requirements.txt
# Download model weights from HF Model Hub
huggingface-cli download Retrosidd/keigo-radar-classifier \
--local-dir keigo_radar_classifier
uvicorn app:app --reload --port 8000Health check: curl http://localhost:8000/health → {"status":"ok"}
cd keigo-radar
cp .env.local.example .env.local
# Fill in GROQ_API_KEY — free at https://console.groq.com
npm install
npm run devOpen http://localhost:3000.
huggingface-cli upload Retrosidd/keigo-radar-classifier ./keigo_radar_classifierThe backend runs as a Docker Space: RetroSidd/keigo-radar-api.
Push app.py, formality_scorer.py, requirements.txt, and Dockerfile to a new HF Space.
Set Space Secrets:
| Secret | Value |
|---|---|
MODEL_REPO_ID |
Retrosidd/keigo-radar-classifier |
ALLOWED_ORIGIN |
https://your-domain.com |
The container downloads model weights from HF Hub at startup, nothing large is baked into the image.
Import the keigo-radar/ subdirectory as a Vercel project (set root directory to keigo-radar/).
Set Environment Variables:
| Variable | Value |
|---|---|
GROQ_API_KEY |
Your Groq key (server-side only, never exposed to the browser) |
GROQ_MODEL_ID |
llama-3.1-8b-instant |
NEXT_PUBLIC_GROQ_MODEL_ID |
llama-3.1-8b-instant |
NEXT_PUBLIC_API_URL |
Your HF Space URL |
Vercel dashboard → Domains → add your domain → set DNS CNAME to cname.vercel-dns.com.
| Component | Dataset | Metric |
|---|---|---|
| Keigo register classifier | keigo_transfer_task | 83.6% accuracy |
| BERT intensity classifier | WRIME — 35k posts, test split | Macro-F1 0.43 |
The 0.43 macro-F1 is intentionally honest. The architecture compensates: the masking gap collapses the 4-class intensity problem into a binary threshold (≥ moderate), and the AND gate with the high-accuracy register classifier suppresses false positives. Both classifiers must agree before the masking gap fires.
aeio/
├── app.py # FastAPI entry point
├── formality_scorer.py # Rule-based keigo classifier
├── requirements.txt
├── Dockerfile # Hugging Face Spaces config
├── keigo_radar_classifier/ # BERT config + tokenizer (weights on HF Hub)
└── keigo-radar/ # Next.js frontend
├── app/
│ ├── page.tsx # UI — radar chart, glossary, compare mode
│ └── api/translate/ # Server-side Groq proxy route
├── .env.local.example
└── vercel.json # Security headers
| Layer | Technology |
|---|---|
| Frontend | Next.js 15, Recharts, vanilla CSS |
| Backend | FastAPI, PyTorch, Hugging Face Transformers |
| Tokenizer | fugashi + unidic (MeCab-based morphological analysis) |
| Emotion model | cl-tohoku/bert-base-japanese-v3 fine-tuned on WRIME |
| Translation | Llama 3.1 8b via Groq — zero-shot, instant inference |
| Infrastructure | Vercel + Hugging Face Spaces (Docker SDK) |