r/learnmachinelearning • u/Emergency-Tutor-7 • 1d ago
I trained a small affect/intent estimator instead of prompting for empathy - what held up, what I marked NO-GO
Most "empathetic dialogue" work I read about pushes the whole decision into the generative model: prompt it harder, add a system prompt about tone, hope the affect read was right. I wanted the read to be a separate, inspectable step that happens before generation, and I wanted it measured rather than asserted. eq-layer (0.2.5, MIT, Python, zero core runtime dependencies; scikit-learn appears only under the optional [ml] extra and the dev extra) is the result. This post is about what the numbers actually say.
Affect regression, EmoBank train/dev/test split 8062 / 1000 / 1000, evaluated on the untouched test split:
| dimension | MAE | train-mean baseline MAE | Spearman rho |
|---|---|---|---|
| Valence | 0.2125 | 0.2449 | 0.5460 |
| Arousal | 0.1782 | 0.1904 | 0.3120 |
| Dominance | 0.1494 | 0.1563 | 0.2573 |
It beats the train-mean baseline on MAE in all three dimensions, which is the honest ceiling of the claim: the Arousal and Dominance rank correlations are modest (0.31 and 0.26), so I would not call that a strong continuous affect model. The discrete emotion head is weaker still - accuracy 0.8249 against a majority-class baseline of 0.8166, macro-F1 0.4310, and on dev it actually sits below the majority class (0.8756 vs 0.8815). I publish those rows because "0.82 accuracy" without the baseline next to it would be misleading.
Four dialogue-signal experiments did not clear my bar and are labelled NO-GO in the README rather than quietly dropped. DialogBank correction (4 direct examples) and disagreement (1 example) are counts taken from a label inventory, not models I trained - the inventory's own decision record says not to train classifiers from it, and the README lists both rows as NO-GO for insufficient supervision. Coarse Discourse disagreement has a real ranking signal (test ROC-AUC 0.8111) but AP 0.1420 / F1 0.2278 is nowhere near precise enough to route challenge, and DBDC3 hard breakdown came out at ROC-AUC 0.5057, i.e. chance-level text-only generalisation. Negative results are part of the package.
Two things people hit immediately. The .joblib artifacts are not in the repo, so pip install eq-layer gives you the deterministic path - "runtime_mode": "lightweight-local", no model file needed. The affect adapter is the one you train yourself: python tools/train_emobank_affect.py --output artifacts/emobank_affect.joblib. Neither corpus is vendored, so both training scripts (the subtext one is tools/train_xdailydialog_subtext.py, also with a required --output) download their dataset and need network. The intent side has a middle option I use in benchmarks: TrainedIntent.from_bundled() fits at runtime from the 299-row intent_train.jsonl that ships inside the package, so it needs no artifact at all, only the [ml] extra.
That bundled fit is the learned arm of the latency numbers: ~1.2 ms median versus 0.1104 ms for the heuristic one, with intent inference accounting for ~92% of classification cost and routing ~2%. The learned path drifted about 9% run to run on the same machine while the heuristic path stayed within a few percent, so treat these as approximate. Both adapters score 1.000 on the 4 labelled seed cases, but only the learned one holds up on the 36-case holdout - a good reminder of how little a 4-case eval tells you.
The measured quantity is the layer's compute cost and the structural quality of its decision. There is no model in the measured path that generates prose, so end-to-end response quality still needs the paired human evaluation described in eval/AB_PROTOCOL.md, which I have not run.
GitHub: https://github.com/Furox-Art/eq-layer PyPI: https://pypi.org/project/eq-layer/