Vibe Check β a 7-emotion Transformer trained from scratch π
π Try the live app - chat with Buddy & Wit and run a Vibe Check, nothing to install: https://civilaakash.github.io/buddymini/
Vibe Check is a compact (~8.3M parameter) Transformer text classifier that reads the
emotional tone of a sentence or a short conversation across 7 classes:
sadness Β· joy Β· love Β· anger Β· fear Β· surprise Β· neutral.
It was built entirely from scratch as a hands-on learning project β my own word tokenizer, my own model architecture, trained from random initialization (no pretrained weights, no fine-tuning of a large model) on public data only.
Not a fine-tune
Unlike most models on the Hub, this is not a fine-tune of a large pretrained model. Every weight was learned from zero on public data. The tokenizer, architecture, training config, and inference code are all included in this repo.
Architecture
- Word-level tokenizer (regex
[a-z']+), vocab 20,002 - Token embedding + learned positional embedding (max length 64)
- 4 Transformer encoder layers Β· embedding dim 256 Β· 8 heads Β· FF 1024 Β· GELU
- Padding-masked mean pooling β linear classification head
- 8,297,735 parameters Β· runs on CPU in milliseconds
Performance (measured, honest)
- ~88% accuracy on the dair-ai/emotion validation split (2,000 held-out tweets, 7-way argmax).
- It is strong when emotion is stated in words:
Input Prediction "I'm terrified of the interview tomorrow" fear (97%) "I love spending time with my family" love (96%) "This is amazing news" joy (94%)
β οΈ Known limitation β implied emotion reads as neutral
This is a tiny model, and it keys off explicit emotional language. When a feeling is only implied by a factual statement (no emotion words), it tends to fall back to neutral:
| Input | Prediction | What a human would say |
|---|---|---|
| "My dog passed away" | neutral (46%) | sadness |
| "I got promoted today!" | neutral (75%) | joy |
So it works best as a conversation-tone reader (see analyze_day below), where it aggregates
emotion across many messages and skips the neutral filler β not as a single-sentence oracle.
Treat it as an educational / entertainment model, not a clinical or production sentiment system.
Usage β PyTorch
# clone/download this repo, then from inside it:
from emotion import predict_emotion, analyze_day
predict_emotion("i feel so happy right now")
# {'label': 'joy', 'confidence': 97.6, 'distribution': {...}, 'words': [...]}
# reads the overall mood across a whole conversation (list of messages):
analyze_day([
"work made me feel sad and invisible today",
"but then my friend called and i felt loved",
])
# {'dominant': 'love', 'valence': 'mixed', 'distribution': {...}, ...}
Usage β ONNX (no PyTorch needed)
import json, re, numpy as np, onnxruntime as ort
vocab = json.load(open("emotion_vocab.json"))
labels = ["sadness","joy","love","anger","fear","surprise","neutral"]
sess = ort.InferenceSession("vibe-int8.onnx")
name = sess.get_inputs()[0].name
ids = [vocab.get(w, 1) for w in re.findall(r"[a-z']+", "i love this so much".lower())][:64]
logits = sess.run(None, {name: np.array([ids], dtype=np.int64)})[0][0]
print(labels[int(logits.argmax())]) # -> love
Training data
- dair-ai/emotion β English tweets, 6 emotions.
- GoEmotions (Google) β Reddit comments; low-signal labels (e.g. curiosity/confusion) mapped to neutral.
- Classes balanced (capped per class) to remove the "everything is joy" bias.
All training data is public β no company data and no personal data of any kind.
License & intent
Model weights and code released under Apache-2.0, for educational and entertainment use. Built by @AakashakaAkku while learning how transformers and LLMs actually work β by building one end to end. Feedback and questions welcome. π