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

108 lines
3.7 KiB
JavaScript
Raw Permalink Normal View History

#!/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();