bookworm-smart-assistant/scripts/patches/patch-task3-confidence-cap.js

108 lines
3.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Task3 补丁 — 2026-04-20 路由精准度审查
*
* 问题: 2-3 字短查询token 数 ≤3信息量不足BM25 仍可算出 confidence=1.0
* 导致 100% 置信度过拟合(如"自动修复"→ browser-automation-expert 100%)。
*
* 修复方案: 在 route-engine.js 返回结果前加一层置信度上限:
* 若 queryTokens.length ≤ 3则 confidence = min(confidence, 0.8)
* 并写入调试日志便于后续观察。
*
* 最小侵入: 仅在 return 语句前插入 4 行代码。
*
* 幂等: sentinel = 'CONFIDENCE_CAP_SHORT_QUERY_PATCH_2026_04_20'
*/
'use strict';
const fs = require('fs');
const path = require('path');
const SCRIPTS_DIR = path.join(__dirname, '..');
const TARGET = path.join(SCRIPTS_DIR, 'route-engine.js');
const SENTINEL = 'CONFIDENCE_CAP_SHORT_QUERY_PATCH_2026_04_20';
function main() {
if (!fs.existsSync(TARGET)) {
console.error('[patch-task3] 目标文件不存在:', TARGET);
process.exit(1);
}
const before = fs.readFileSync(TARGET, 'utf8');
// 幂等检查
if (before.includes(SENTINEL)) {
console.log('[patch-task3] 已打过补丁 (发现 sentinel),跳过');
process.exit(0);
}
// 锚点: return 语句前的 confidence 计算行
const anchor =
' const confidence = normalized[0]?.confidence || 0;\n' +
'\n' +
' return {';
if (!before.includes(anchor)) {
console.error('[patch-task3] 找不到 confidence 计算锚点route-engine.js 结构已变更');
process.exit(2);
}
// 注入: confidence 上限 + debug log
const injection =
' const confidence = normalized[0]?.confidence || 0;\n' +
'\n' +
' // ' + SENTINEL + '\n' +
' // 短查询置信度上限: token 数 ≤3 时 confidence 不超过 0.8,防 BM25 过拟合\n' +
' let _finalConfidence = confidence;\n' +
' if (queryTokens.size <= 3 && _finalConfidence > 0.8) {\n' +
' _finalConfidence = 0.8;\n' +
' try {\n' +
' const logLine = JSON.stringify({\n' +
' t: Date.now(), event: \'confidence_cap\',\n' +
' tokens: queryTokens.size, original: confidence, capped: 0.8,\n' +
' primary: normalized[0] && normalized[0].name,\n' +
' }) + \'\\n\';\n' +
' fs.appendFileSync(path.join(DEBUG_DIR, \'confidence-cap.log\'), logLine);\n' +
' } catch {}\n' +
' }\n' +
'\n' +
' return {';
const after = before.replace(anchor, injection);
// 同时将 return 对象中的 confidence 替换为 _finalConfidence
const returnAnchor = ' primary, candidates, confidence, chain, composable,';
if (!after.includes(returnAnchor)) {
console.error('[patch-task3] 找不到 return 对象中的 confidence 字段');
process.exit(3);
}
const finalAfter = after.replace(
returnAnchor,
' primary, candidates, confidence: _finalConfidence, chain, composable,'
);
// ==== 原子写入 (.bak 备份 + tmp 文件) ====
const bakFile = TARGET + '.bak.task3.' + Date.now();
fs.copyFileSync(TARGET, bakFile);
console.log('[patch-task3] 备份已写入:', bakFile);
const tmpFile = TARGET + '.tmp';
fs.writeFileSync(tmpFile, finalAfter, 'utf8');
fs.renameSync(tmpFile, TARGET);
console.log('[patch-task3] 补丁已应用到:', TARGET);
// 验证
const verify = fs.readFileSync(TARGET, 'utf8');
if (!verify.includes(SENTINEL)) {
console.error('[patch-task3] 验证失败: sentinel 未找到!');
process.exit(4);
}
if (!verify.includes('_finalConfidence')) {
console.error('[patch-task3] 验证失败: _finalConfidence 未注入!');
process.exit(5);
}
console.log('[patch-task3] PASS — sentinel + _finalConfidence 验证通过');
}
main();