mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
323 lines
9.5 KiB
JavaScript
323 lines
9.5 KiB
JavaScript
import {
|
||
createDefaultGlobalTaskRegex,
|
||
createDefaultTaskProfiles,
|
||
} from "../prompting/prompt-profiles.js";
|
||
|
||
function clampIntValue(value, fallback = 0, min = 0, max = 9999) {
|
||
const numeric = Number(value);
|
||
if (!Number.isFinite(numeric)) return fallback;
|
||
return Math.min(max, Math.max(min, Math.trunc(numeric)));
|
||
}
|
||
|
||
const NATIVE_ROLLOUT_VERSION = 2;
|
||
const LEGACY_NATIVE_HYDRATE_THRESHOLD_RECORDS = 12000;
|
||
const DEFAULT_NATIVE_HYDRATE_THRESHOLD_RECORDS = 30000;
|
||
|
||
export const defaultSettings = {
|
||
enabled: true,
|
||
debugLoggingEnabled: false,
|
||
timeoutMs: 300000,
|
||
hideOldMessagesEnabled: false,
|
||
hideOldMessagesKeepLastN: 12,
|
||
hideOldMessagesRenderLimitEnabled: true,
|
||
hideOldMessagesRenderLimit: 10,
|
||
|
||
// 提取设置
|
||
extractEvery: 1,
|
||
extractContextTurns: 2,
|
||
extractAutoDelayLatestAssistant: false,
|
||
extractAssistantExtractTags: "",
|
||
extractAssistantExcludeTags: "think,analysis,reasoning",
|
||
extractAssistantExtractRules: [],
|
||
extractAssistantExcludeRules: [],
|
||
extractRecentMessageCap: 0,
|
||
extractPromptStructuredMode: "both",
|
||
extractWorldbookMode: "active",
|
||
extractIncludeStoryTime: true,
|
||
extractIncludeSummaries: true,
|
||
extractActionMode: "pending",
|
||
|
||
// 召回设置
|
||
recallEnabled: true,
|
||
recallCardUserInputDisplayMode: "beautify_only",
|
||
worldInfoFilterMode: "default",
|
||
worldInfoFilterCustomKeywords: "",
|
||
recallTopK: 20,
|
||
recallMaxNodes: 12,
|
||
recallEnableLLM: true,
|
||
recallEnableVectorPrefilter: true,
|
||
recallEnableGraphDiffusion: true,
|
||
recallDiffusionTopK: 100,
|
||
recallLlmCandidatePool: 30,
|
||
recallLlmContextMessages: 4,
|
||
recallUseAuthoritativeGenerationInput: false,
|
||
recallEnableMultiIntent: true,
|
||
recallMultiIntentMaxSegments: 4,
|
||
recallEnableContextQueryBlend: true,
|
||
recallContextAssistantWeight: 0.2,
|
||
recallContextPreviousUserWeight: 0.1,
|
||
recallEnableLexicalBoost: true,
|
||
recallLexicalWeight: 0.18,
|
||
recallTeleportAlpha: 0.15,
|
||
recallEnableTemporalLinks: true,
|
||
recallTemporalLinkStrength: 0.2,
|
||
recallEnableDiversitySampling: true,
|
||
recallDppCandidateMultiplier: 3,
|
||
recallDppQualityWeight: 1.0,
|
||
recallEnableCooccurrenceBoost: false,
|
||
recallCooccurrenceScale: 0.1,
|
||
recallCooccurrenceMaxNeighbors: 10,
|
||
recallEnableResidualRecall: false,
|
||
recallResidualBasisMaxNodes: 24,
|
||
recallNmfTopics: 15,
|
||
recallNmfNoveltyThreshold: 0.4,
|
||
recallResidualThreshold: 0.3,
|
||
recallResidualTopK: 5,
|
||
enableScopedMemory: true,
|
||
enablePovMemory: true,
|
||
enableRegionScopedObjective: true,
|
||
enableCognitiveMemory: true,
|
||
enableSpatialAdjacency: true,
|
||
injectLowConfidenceObjectiveMemory: false,
|
||
enableStoryTimeline: true,
|
||
injectStoryTimeLabel: true,
|
||
storyTimeSoftDirecting: true,
|
||
recallCharacterPovWeight: 1.25,
|
||
recallUserPovWeight: 1.05,
|
||
recallObjectiveCurrentRegionWeight: 1.15,
|
||
recallObjectiveAdjacentRegionWeight: 0.9,
|
||
recallObjectiveGlobalWeight: 0.75,
|
||
injectUserPovMemory: true,
|
||
injectObjectiveGlobalMemory: true,
|
||
|
||
// 注入设置
|
||
injectPosition: "atDepth",
|
||
injectDepth: 9999,
|
||
injectRole: 0,
|
||
|
||
// 混合评分权重
|
||
graphWeight: 0.6,
|
||
vectorWeight: 0.3,
|
||
importanceWeight: 0.1,
|
||
|
||
// 记忆 LLM(留空时复用当前酒馆模型)
|
||
llmApiUrl: "",
|
||
llmApiKey: "",
|
||
llmModel: "",
|
||
llmPresets: {},
|
||
llmActivePreset: "",
|
||
|
||
// Embedding API 配置
|
||
embeddingApiUrl: "",
|
||
embeddingApiKey: "",
|
||
embeddingModel: "text-embedding-3-small",
|
||
embeddingTransportMode: "direct",
|
||
embeddingBackendSource: "openai",
|
||
embeddingBackendModel: "text-embedding-3-small",
|
||
embeddingBackendApiUrl: "",
|
||
embeddingAutoSuffix: true,
|
||
|
||
authorityEnabled: "auto",
|
||
authorityBaseUrl: "/api/plugins/authority",
|
||
authorityPrimaryWhenAvailable: true,
|
||
authorityStorageMode: "auto-server-primary",
|
||
authorityVectorMode: "auto-primary",
|
||
authoritySqlPrimary: true,
|
||
authorityTriviumPrimary: true,
|
||
authorityGraphQueryEnabled: true,
|
||
authorityJobsEnabled: true,
|
||
authorityBlobCheckpointEnabled: true,
|
||
authorityBrowserCacheMode: "minimal",
|
||
authorityOfflineWritePolicy: "queue-local-dirty",
|
||
authorityOfflineQueueMaxBytes: 1048576,
|
||
authorityOfflineQueueMaxItems: 128,
|
||
authorityOfflineQueueMaxAgeMs: 3600000,
|
||
authorityVectorSyncChunkSize: 1000,
|
||
authorityVectorFailOpen: true,
|
||
authorityDiagnosticsEnabled: true,
|
||
authorityProbeIntervalMs: 60000,
|
||
|
||
// Native 性能加速(灰度)
|
||
graphUseNativeLayout: true,
|
||
graphNativeLayoutThresholdNodes: 280,
|
||
graphNativeLayoutThresholdEdges: 1600,
|
||
graphNativeLayoutWorkerTimeoutMs: 260,
|
||
persistUseNativeDelta: true,
|
||
persistNativeDeltaThresholdRecords: 20000,
|
||
persistNativeDeltaThresholdStructuralDelta: 600,
|
||
persistNativeDeltaThresholdSerializedChars: 4000000,
|
||
persistNativeDeltaBridgeMode: "json",
|
||
loadUseNativeHydrate: true,
|
||
loadNativeHydrateThresholdRecords: DEFAULT_NATIVE_HYDRATE_THRESHOLD_RECORDS,
|
||
nativeRolloutVersion: NATIVE_ROLLOUT_VERSION,
|
||
nativeEngineFailOpen: true,
|
||
graphNativeForceDisable: false,
|
||
|
||
// Schema
|
||
nodeTypeSchema: null,
|
||
|
||
// 自定义提示词
|
||
extractPrompt: "",
|
||
recallPrompt: "",
|
||
consolidationPrompt: "",
|
||
compressPrompt: "",
|
||
synopsisPrompt: "",
|
||
summaryRollupPrompt: "",
|
||
reflectionPrompt: "",
|
||
taskProfilesVersion: 3,
|
||
taskProfiles: createDefaultTaskProfiles(),
|
||
globalTaskRegex: createDefaultGlobalTaskRegex(),
|
||
|
||
// ====== v2 增强设置 ======
|
||
enableConsolidation: true,
|
||
consolidationNeighborCount: 5,
|
||
consolidationThreshold: 0.85,
|
||
enableSynopsis: true,
|
||
synopsisEveryN: 5,
|
||
enableHierarchicalSummary: true,
|
||
smallSummaryEveryNExtractions: 3,
|
||
summaryRollupFanIn: 3,
|
||
enableVisibility: true,
|
||
enableCrossRecall: true,
|
||
enableSmartTrigger: false,
|
||
triggerPatterns: "",
|
||
smartTriggerThreshold: 2,
|
||
enableSleepCycle: false,
|
||
forgetThreshold: 0.5,
|
||
sleepEveryN: 10,
|
||
enableProbRecall: false,
|
||
probRecallChance: 0.15,
|
||
enableReflection: true,
|
||
reflectEveryN: 10,
|
||
consolidationAutoMinNewNodes: 2,
|
||
enableAutoCompression: true,
|
||
compressionEveryN: 10,
|
||
|
||
// UI 面板
|
||
noticeDisplayMode: "normal",
|
||
panelTheme: "crimson",
|
||
graphLocalStorageMode: "auto",
|
||
cloudStorageMode: "automatic",
|
||
};
|
||
|
||
const DEFAULT_SETTING_KEYS = Object.freeze(Object.keys(defaultSettings));
|
||
|
||
export function migrateLegacyAutoMaintenanceSettings(loaded = {}) {
|
||
if (!loaded || typeof loaded !== "object" || Array.isArray(loaded)) {
|
||
return {};
|
||
}
|
||
|
||
const migrated = { ...loaded };
|
||
if (
|
||
!Object.prototype.hasOwnProperty.call(
|
||
migrated,
|
||
"consolidationAutoMinNewNodes",
|
||
) &&
|
||
Object.prototype.hasOwnProperty.call(migrated, "maintenanceAutoMinNewNodes")
|
||
) {
|
||
migrated.consolidationAutoMinNewNodes = clampIntValue(
|
||
migrated.maintenanceAutoMinNewNodes,
|
||
defaultSettings.consolidationAutoMinNewNodes,
|
||
1,
|
||
50,
|
||
);
|
||
}
|
||
if (!Object.prototype.hasOwnProperty.call(migrated, "enableAutoCompression")) {
|
||
const parsedEveryN = Math.floor(Number(migrated.compressionEveryN));
|
||
migrated.enableAutoCompression = !(
|
||
Number.isFinite(parsedEveryN) && parsedEveryN <= 0
|
||
);
|
||
}
|
||
if (
|
||
Object.prototype.hasOwnProperty.call(migrated, "compressionEveryN") &&
|
||
Math.floor(Number(migrated.compressionEveryN)) <= 0
|
||
) {
|
||
migrated.compressionEveryN = defaultSettings.compressionEveryN;
|
||
}
|
||
if (
|
||
!Object.prototype.hasOwnProperty.call(migrated, "enableHierarchicalSummary") &&
|
||
Object.prototype.hasOwnProperty.call(migrated, "enableSynopsis")
|
||
) {
|
||
migrated.enableHierarchicalSummary = Boolean(migrated.enableSynopsis);
|
||
}
|
||
if (
|
||
!Object.prototype.hasOwnProperty.call(
|
||
migrated,
|
||
"smallSummaryEveryNExtractions",
|
||
) &&
|
||
Object.prototype.hasOwnProperty.call(migrated, "synopsisEveryN")
|
||
) {
|
||
migrated.smallSummaryEveryNExtractions = clampIntValue(
|
||
migrated.synopsisEveryN,
|
||
defaultSettings.smallSummaryEveryNExtractions,
|
||
1,
|
||
100,
|
||
);
|
||
}
|
||
if (
|
||
!Object.prototype.hasOwnProperty.call(migrated, "summaryRollupFanIn")
|
||
) {
|
||
migrated.summaryRollupFanIn = defaultSettings.summaryRollupFanIn;
|
||
}
|
||
delete migrated.maintenanceAutoMinNewNodes;
|
||
return migrated;
|
||
}
|
||
|
||
export function migrateNativeRolloutSettings(loaded = {}) {
|
||
if (!loaded || typeof loaded !== "object" || Array.isArray(loaded)) {
|
||
return {};
|
||
}
|
||
|
||
const migrated = { ...loaded };
|
||
const rolloutVersion = clampIntValue(
|
||
migrated.nativeRolloutVersion,
|
||
0,
|
||
0,
|
||
NATIVE_ROLLOUT_VERSION,
|
||
);
|
||
if (rolloutVersion < 1) {
|
||
migrated.graphUseNativeLayout = defaultSettings.graphUseNativeLayout;
|
||
migrated.persistUseNativeDelta = defaultSettings.persistUseNativeDelta;
|
||
migrated.loadUseNativeHydrate = defaultSettings.loadUseNativeHydrate;
|
||
}
|
||
if (
|
||
rolloutVersion < 2 &&
|
||
(!Object.prototype.hasOwnProperty.call(
|
||
migrated,
|
||
"loadNativeHydrateThresholdRecords",
|
||
) ||
|
||
clampIntValue(
|
||
migrated.loadNativeHydrateThresholdRecords,
|
||
LEGACY_NATIVE_HYDRATE_THRESHOLD_RECORDS,
|
||
0,
|
||
1000000,
|
||
) === LEGACY_NATIVE_HYDRATE_THRESHOLD_RECORDS)
|
||
) {
|
||
migrated.loadNativeHydrateThresholdRecords =
|
||
defaultSettings.loadNativeHydrateThresholdRecords;
|
||
}
|
||
migrated.nativeRolloutVersion = NATIVE_ROLLOUT_VERSION;
|
||
return migrated;
|
||
}
|
||
|
||
export function mergePersistedSettings(loaded = {}) {
|
||
const compatibleLoaded = migrateNativeRolloutSettings(
|
||
migrateLegacyAutoMaintenanceSettings(loaded),
|
||
);
|
||
const merged = { ...defaultSettings };
|
||
for (const key of DEFAULT_SETTING_KEYS) {
|
||
if (Object.prototype.hasOwnProperty.call(compatibleLoaded, key)) {
|
||
merged[key] = compatibleLoaded[key];
|
||
}
|
||
}
|
||
return merged;
|
||
}
|
||
|
||
export function getPersistedSettingsSnapshot(settings = defaultSettings) {
|
||
const persisted = {};
|
||
for (const key of DEFAULT_SETTING_KEYS) {
|
||
persisted[key] = settings[key];
|
||
}
|
||
return persisted;
|
||
}
|