story-summary: facts migration + recall enhancements
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
import { getContext } from "../../../../../../extensions.js";
|
||||
import { xbLog } from "../../../core/debug-core.js";
|
||||
import { getSummaryStore } from "../data/store.js";
|
||||
import { getSummaryStore, getFacts, isRelationFact } from "../data/store.js";
|
||||
import { getVectorConfig, getSummaryPanelConfig, getSettings } from "../data/config.js";
|
||||
import { recallMemory, buildQueryText } from "../vector/recall.js";
|
||||
import { getChunksByFloors, getAllChunkVectors, getAllEventVectors, getMeta } from "../vector/chunk-store.js";
|
||||
@@ -111,10 +111,18 @@ function buildPostscript() {
|
||||
// 格式化函数
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
function formatWorldLines(world) {
|
||||
return [...(world || [])]
|
||||
.sort((a, b) => (b.floor || 0) - (a.floor || 0))
|
||||
.map(w => `- ${w.topic}:${w.content}`);
|
||||
function formatFactsForInjection(facts) {
|
||||
const activeFacts = (facts || []).filter(f => !f.retracted);
|
||||
if (!activeFacts.length) return [];
|
||||
return activeFacts
|
||||
.sort((a, b) => (b.since || 0) - (a.since || 0))
|
||||
.map(f => {
|
||||
const since = f.since ? ` (#${f.since + 1})` : '';
|
||||
if (isRelationFact(f) && f.trend) {
|
||||
return `- ${f.s} ${f.p}: ${f.o} [${f.trend}]${since}`;
|
||||
}
|
||||
return `- ${f.s}的${f.p}: ${f.o}${since}`;
|
||||
});
|
||||
}
|
||||
|
||||
function formatArcLine(a) {
|
||||
@@ -189,7 +197,7 @@ function formatInjectionLog(stats, details, recentOrphanStats = null) {
|
||||
|
||||
// [1] 世界约束
|
||||
lines.push(` [1] 世界约束 (上限 2000)`);
|
||||
lines.push(` 选入: ${stats.world.count} 条 | 消耗: ${stats.world.tokens} tokens`);
|
||||
lines.push(` 选入: ${stats.facts.count} 条 | 消耗: ${stats.facts.tokens} tokens`);
|
||||
lines.push('');
|
||||
|
||||
// [2] 核心经历 + 过往背景
|
||||
@@ -229,7 +237,7 @@ function formatInjectionLog(stats, details, recentOrphanStats = null) {
|
||||
const pctStr = pct(tokens, total) + '%';
|
||||
return ` ${label.padEnd(6)} ${'█'.repeat(width).padEnd(30)} ${String(tokens).padStart(5)} (${pctStr})`;
|
||||
};
|
||||
lines.push(bar(stats.world.tokens, '约束'));
|
||||
lines.push(bar(stats.facts.tokens, '约束'));
|
||||
lines.push(bar(stats.events.tokens + stats.evidence.tokens, '经历'));
|
||||
lines.push(bar(stats.orphans.tokens, '远期'));
|
||||
lines.push(bar(recentOrphanStats?.tokens || 0, '待整理'));
|
||||
@@ -263,9 +271,9 @@ function buildNonVectorPrompt(store) {
|
||||
const data = store.json || {};
|
||||
const sections = [];
|
||||
|
||||
if (data.world?.length) {
|
||||
const lines = formatWorldLines(data.world);
|
||||
sections.push(`[世界约束] 已确立的事实\n${lines.join("\n")}`);
|
||||
const factLines = formatFactsForInjection(getFacts(store));
|
||||
if (factLines.length) {
|
||||
sections.push(`[定了的事] 已确立的事实\n${factLines.join("\n")}`);
|
||||
}
|
||||
|
||||
if (data.events?.length) {
|
||||
@@ -330,7 +338,7 @@ async function buildVectorPrompt(store, recallResult, causalById, queryEntities
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
const assembled = {
|
||||
world: { lines: [], tokens: 0 },
|
||||
facts: { lines: [], tokens: 0 },
|
||||
arcs: { lines: [], tokens: 0 },
|
||||
events: { direct: [], similar: [] },
|
||||
orphans: { lines: [], tokens: 0 },
|
||||
@@ -339,7 +347,7 @@ async function buildVectorPrompt(store, recallResult, causalById, queryEntities
|
||||
|
||||
const injectionStats = {
|
||||
budget: { max: TOTAL_BUDGET_MAX, used: 0 },
|
||||
world: { count: 0, tokens: 0 },
|
||||
facts: { count: 0, tokens: 0 },
|
||||
arcs: { count: 0, tokens: 0 },
|
||||
events: { selected: 0, tokens: 0 },
|
||||
evidence: { attached: 0, tokens: 0 },
|
||||
@@ -360,16 +368,16 @@ async function buildVectorPrompt(store, recallResult, causalById, queryEntities
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// [优先级 1] 世界约束 - 最高优先级
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
const worldLines = formatWorldLines(data.world);
|
||||
if (worldLines.length) {
|
||||
const factLines = formatFactsForInjection(getFacts(store));
|
||||
if (factLines.length) {
|
||||
const l3Budget = { used: 0, max: Math.min(L3_MAX, total.max - total.used) };
|
||||
for (const line of worldLines) {
|
||||
if (!pushWithBudget(assembled.world.lines, line, l3Budget)) break;
|
||||
for (const line of factLines) {
|
||||
if (!pushWithBudget(assembled.facts.lines, line, l3Budget)) break;
|
||||
}
|
||||
assembled.world.tokens = l3Budget.used;
|
||||
assembled.facts.tokens = l3Budget.used;
|
||||
total.used += l3Budget.used;
|
||||
injectionStats.world.count = assembled.world.lines.length;
|
||||
injectionStats.world.tokens = l3Budget.used;
|
||||
injectionStats.facts.count = assembled.facts.lines.length;
|
||||
injectionStats.facts.tokens = l3Budget.used;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
@@ -599,8 +607,8 @@ async function buildVectorPrompt(store, recallResult, causalById, queryEntities
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
const sections = [];
|
||||
// 1. 世界约束 → 定了的事
|
||||
if (assembled.world.lines.length) {
|
||||
sections.push(`[定了的事] 已确立的事实\n${assembled.world.lines.join("\n")}`);
|
||||
if (assembled.facts.lines.length) {
|
||||
sections.push(`[定了的事] 已确立的事实\n${assembled.facts.lines.join("\n")}`);
|
||||
}
|
||||
// 2. 核心经历 → 印象深的事
|
||||
if (assembled.events.direct.length) {
|
||||
@@ -632,6 +640,8 @@ if (!sections.length) {
|
||||
`<剧情记忆>\n\n${sections.join("\n\n")}\n\n</剧情记忆>\n` +
|
||||
`${buildPostscript()}`;
|
||||
|
||||
// ★ 修复:先写回预算统计,再生成日志
|
||||
injectionStats.budget.used = total.used + (assembled.recentOrphans.tokens || 0);
|
||||
const injectionLogText = formatInjectionLog(injectionStats, details, recentOrphanStats);
|
||||
|
||||
return { promptText, injectionLogText, injectionStats };
|
||||
@@ -835,4 +845,4 @@ export async function buildVectorPromptText(excludeLastAi = false, hooks = {}) {
|
||||
}
|
||||
|
||||
return { text: finalText, logText: (recallResult.logText || "") + (injectionLogText || "") };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user