Refactor L0 quality and diffusion graph gating for balanced recall

This commit is contained in:
2026-02-14 17:12:03 +08:00
parent 15640d48f2
commit e8383570e0
3 changed files with 169 additions and 46 deletions

View File

@@ -63,6 +63,8 @@ const SYSTEM_PROMPT = `你是场景摘要器。从一轮对话中提取1-2个场
- 只从正文内容中识别角色名,不要把标签名(如 user、assistant当作角色
- r 使用动作模板短语:“动作+对象/结果”(例:“提出交易条件”、“拒绝对方请求”、“当众揭露秘密”、“安抚对方情绪”)
- r 不要写人名,不要复述整句,不要写心理描写或评价词
- r 正例(合格):提出交易条件、拒绝对方请求、当众揭露秘密、安抚对方情绪、强行打断发言、转移谈话焦点
- r 反例不合格我觉得她现在很害怕、他突然非常生气地大喊起来、user开始说话、assistant解释了很多细节
- 每个锚点 1-3 条
## where
@@ -87,6 +89,46 @@ const JSON_PREFILL = '{"anchors":[';
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
const ACTION_STRIP_WORDS = [
'突然', '非常', '有些', '有点', '轻轻', '悄悄', '缓缓', '立刻',
'马上', '然后', '并且', '而且', '开始', '继续', '再次', '正在',
];
function clamp(v, min, max) {
return Math.max(min, Math.min(max, v));
}
function sanitizeActionPhrase(raw) {
let text = String(raw || '')
.normalize('NFKC')
.replace(/[\u200B-\u200D\uFEFF]/g, '')
.trim();
if (!text) return '';
text = text
.replace(/[,。!?、;:,.!?;:"'“”‘’()[\]{}<>《》]/g, '')
.replace(/\s+/g, '');
for (const word of ACTION_STRIP_WORDS) {
text = text.replaceAll(word, '');
}
text = text.replace(/(地|得|了|着|过)+$/g, '');
if (text.length < 2) return '';
if (text.length > 12) text = text.slice(0, 12);
return text;
}
function calcAtomQuality(scene, edges, where) {
const sceneLen = String(scene || '').length;
const sceneScore = clamp(sceneLen / 80, 0, 1);
const edgeScore = clamp((edges?.length || 0) / 3, 0, 1);
const whereScore = where ? 1 : 0;
const quality = 0.55 * sceneScore + 0.35 * edgeScore + 0.10 * whereScore;
return Number(quality.toFixed(3));
}
// ============================================================================
// 清洗与构建
// ============================================================================
@@ -103,7 +145,7 @@ function sanitizeEdges(raw) {
.map(e => ({
s: String(e.s || '').trim(),
t: String(e.t || '').trim(),
r: String(e.r || '').trim().slice(0, 30),
r: sanitizeActionPhrase(e.r),
}))
.filter(e => e.s && e.t && e.r)
.slice(0, 3);
@@ -127,6 +169,7 @@ function anchorToAtom(anchor, aiFloor, idx) {
if (scene.length < 15) return null;
const edges = sanitizeEdges(anchor.edges);
const where = String(anchor.where || '').trim();
const quality = calcAtomQuality(scene, edges, where);
return {
atomId: `atom-${aiFloor}-${idx}`,
@@ -139,6 +182,7 @@ function anchorToAtom(anchor, aiFloor, idx) {
// ═══ 图结构层(扩散的 key ═══
edges,
where,
quality,
};
}