refactor(doantu): drop sigmoid calibration — map raw cosine * 100

Sigmoid was inherited from semantle where bge-m3's narrow cone (unrelated
pairs at 0.40-0.55) needed spreading. phow2sim cosines span 0.0-0.8
naturally, so a linear map is honest and free of magic constants. Kept
the emoji buckets — they already work well against raw percentages.
This commit is contained in:
tiennm99 committed 2026-04-23 12:55:58 +07:00
1 parent 7725f5a3ba
commit 58deb531e8
2 files changed
+10 -26

No files matched your search

+5 -4
View File
@@ -43,10 +43,11 @@ Override the base URL for local dev via `PHOW2SIM_API_URL`.
- `state.js` — KV persistence for game + stats. Same shape as semantle.
- `lookup.js` — guess normalization + shape validation. Accepts Unicode
letters + combining marks + single internal spaces.
- `format.js` — warmth-percent and emoji-bucket formatters. Calibration
constants differ from semantle/format.js: phow2sim (word2vec) has a
wider cosine distribution than bge-m3's narrow transformer cone, so
`FLOOR=0.1`, `CENTER=0.4`, `SCALE=6` here vs 0.4/0.6/8 there.
- `format.js` — warmth-percent + emoji-bucket formatters. Linear
`round(raw * 100)` — phow2sim (word2vec) cosines already span a
game-friendly range (unrelated ~0.0, synonyms 0.6+), so no sigmoid
remap. Contrast with semantle/format.js which needs a sigmoid to
spread bge-m3's narrow transformer cone.
- `render.js` — Telegram HTML `<pre>` monospace board with a 🇻🇳 header.
- `handlers.js` — subject resolution + the three command entry points.
Fast-path dedup (exact text OR prior canonical) skips wasted API calls
+5 -22
View File
@@ -1,32 +1,15 @@
/**
* @file Display formatting helpers for similarity scores.
*
* Tuned for phow2sim (PhoW2V word2vec): its cosine distribution is wider
* than bge-m3's narrow transformer cone that semantle/format.js calibrates
* against. Typical word2vec ranges:
* unrelated pairs: 0.00–0.15
* loosely related: 0.15–0.30
* clearly related: 0.30–0.55
* synonyms/same-topic: 0.55–0.80
* identical: 1.00
* Mapping: raw 0.10 → 0, 0.30 → ~25, 0.40 → ~45, 0.50 → ~60, 0.70 → ~85, 1.00 → 100.
* phow2sim (PhoW2V word2vec) cosines already span a wide, game-friendly
* range — unrelated pairs near 0.0, synonyms 0.6+ — so we map linearly:
* `round(raw * 100)`, clamped to [0, 100]. Negative cosines (antonyms) clamp
* to 0. No sigmoid, no magic constants.
*/
const FLOOR = 0.1;
const CENTER = 0.4;
const SCALE = 6.0;
const sigmoid = (x) => 1 / (1 + Math.exp(-x));
const FLOOR_SIG = sigmoid(SCALE * (FLOOR - CENTER));
const ONE_SIG = sigmoid(SCALE * (1 - CENTER));
const SIG_RANGE = ONE_SIG - FLOOR_SIG;
/** @param {number} rawCosine */
export function calibrate(rawCosine) {
if (rawCosine >= 1) return 100;
if (rawCosine <= FLOOR) return 0;
const s = sigmoid(SCALE * (rawCosine - CENTER));
return Math.max(0, Math.min(100, ((s - FLOOR_SIG) / SIG_RANGE) * 100));
return Math.max(0, Math.min(100, rawCosine * 100));
}
/** @param {number} score — calibrated score in [0, 100] */