diff --git a/src/modules/doantu/README.md b/src/modules/doantu/README.md index b6d55a2..58eb3c7 100644 --- a/src/modules/doantu/README.md +++ b/src/modules/doantu/README.md @@ -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 `
` 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
diff --git a/src/modules/doantu/format.js b/src/modules/doantu/format.js
index 5476146..fd8e534 100644
--- a/src/modules/doantu/format.js
+++ b/src/modules/doantu/format.js
@@ -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] */