t183:語意搜尋補 min_score=0.75——濾掉低分雜訊

leo 實撞:搜「火星座標」20 筆只有前 8 筆相關,後面全是 n8n 版本比較表、Leo 填答。
kbdb 早支援 min_score(embed.ts:225 / issue #67),portal 從來沒傳 ⇒ 等同無門檻,
Vectorize 硬湊滿 topK 就把低分尾巴全端上來。

0.75 取自實測分數分布(youlin 實例,非猜測):
  0.908…0.787 全是火星座標(真相關)
  ── 斷崖 ──
  0.742 姨媽說故事/0.740 ax-academy/0.739×8 n8n版本比較表(雜訊)
與 leo 實測「前 8 個相關」完全吻合。

前端可傳 min_score 覆寫,但不收 0/負數(那等於關掉閾值=本次要修的病本身)。

⚠️ 這治不了『同一份檔案重複灌 N 次』(那些分數 0.91 比正解還高)——另立 issue #14。
This commit is contained in:
uncle6me-web
2026-08-04 19:07:41 +08:00
parent a7d54751fb
commit b3a57d95f6
+20 -1
View File
@@ -225,7 +225,26 @@ portalDataRouter.get('/portal/data/search', (c) =>
if (!libraries.includes('*')) params.set('library', libraries.join(','));
// 透傳的只有「在權限範圍內再收窄」的 filterowner_id/library 上面已由 server 定死,
// caller 傳什麼都不看(URLSearchParams 是新建的,蓋不掉)。
if (c.req.query('mode') === 'semantic') params.set('mode', 'semantic');
if (c.req.query('mode') === 'semantic') {
params.set('mode', 'semantic');
// 🔴 t183leo 08-04 實撞:「語義搜尋搜到一大堆不相關的內容」
// ——搜「火星座標」卻跑出 n8n 版本比較表、Leo 填答):
// Vectorize 會**硬湊滿 topK 筆**,湊不到就把低分的塞進來 ⇒ 尾巴全是無關內容。
// kbdb 早就支援 min_score`kbdb/src/embed.ts:225`issue #67),
// 但 portal **從來沒傳** ⇒ 等同沒有閾值,低分尾全端到用戶面前。
//
// 0.75 怎麼來的(**實測分數分布,不是猜的**;youlin 實例搜「火星座標 奧林帕斯山」):
// 0.908 / 0.881 / 0.881 / 0.880 / 0.870 / 0.815 / 0.798 / 0.787 ← 全是火星座標,真相關
// ─────────────────────── 斷崖 ───────────────────────
// 0.742 姨媽說故事 0.740 ax-academy 0.739×8 n8n 版本比較表 ← 全是雜訊
// 斷崖落在 0.787 與 0.742 之間 ⇒ 取 0.75:相關的全留、雜訊全砍。
//
// 允許前端覆寫(想放寬看更多可傳 min_score),但**不接受 0/負數**
// ——那等於關掉閾值,正是這次要修的病本身。
const msRaw = Number(c.req.query('min_score'));
const minScore = Number.isFinite(msRaw) && msRaw > 0 && msRaw < 1 ? msRaw : 0.75;
params.set('min_score', String(minScore));
}
const entryType = c.req.query('entry_type');
if (entryType) params.set('entry_type', entryType);
const limit = c.req.query('limit');