mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-06-13 18:31:16 +08:00
refactor(recall): extract persisted reuse helpers
This commit is contained in:
@@ -91,40 +91,81 @@ function buildPersistedRecallReuseResult(record = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function resolveReusablePersistedRecallRecord(chat, recallInput, runtime) {
|
||||
const generationType = String(recallInput?.generationType || "normal").trim() || "normal";
|
||||
export function normalizeRecallGenerationType(value = "normal") {
|
||||
return String(value || "normal").trim() || "normal";
|
||||
}
|
||||
|
||||
let targetUserMessageIndex = Number.isFinite(recallInput?.targetUserMessageIndex)
|
||||
? Math.floor(Number(recallInput.targetUserMessageIndex))
|
||||
: null;
|
||||
export function normalizeRecallTargetUserMessageIndex(value) {
|
||||
return Number.isFinite(value) ? Math.floor(Number(value)) : null;
|
||||
}
|
||||
|
||||
const readPersistedRecallFromUserMessage = runtime.readPersistedRecallFromUserMessage;
|
||||
if (typeof readPersistedRecallFromUserMessage !== "function") return null;
|
||||
export function normalizeRecallTextForRuntime(runtime, value = "") {
|
||||
return typeof runtime?.normalizeRecallInputText === "function"
|
||||
? runtime.normalizeRecallInputText(value)
|
||||
: String(value ?? "")
|
||||
.replace(/\r\n/g, "\n")
|
||||
.trim();
|
||||
}
|
||||
|
||||
const normalizeText = (value = "") =>
|
||||
typeof runtime.normalizeRecallInputText === "function"
|
||||
? runtime.normalizeRecallInputText(value)
|
||||
: String(value ?? "")
|
||||
.replace(/\r\n/g, "\n")
|
||||
.trim();
|
||||
const currentRecallInputText = normalizeText(recallInput?.userMessage || "");
|
||||
const recallSource = String(recallInput?.source || "").trim();
|
||||
const activeInputSources = new Set([
|
||||
export function isActiveRecallInputSource(source = "") {
|
||||
return new Set([
|
||||
"send-intent",
|
||||
"generation-started-send-intent",
|
||||
"generation-started-textarea",
|
||||
"host-generation-lifecycle",
|
||||
"textarea-live",
|
||||
"planner-handoff",
|
||||
]);
|
||||
const isActiveInputSource = activeInputSources.has(recallSource);
|
||||
const noNewUserGenerationTypes = new Set([
|
||||
"swipe",
|
||||
"regenerate",
|
||||
"continue",
|
||||
"history",
|
||||
]);
|
||||
const isNoNewUserGeneration = noNewUserGenerationTypes.has(generationType);
|
||||
]).has(String(source || "").trim());
|
||||
}
|
||||
|
||||
export function isNoNewUserGenerationType(generationType = "normal") {
|
||||
return new Set(["swipe", "regenerate", "continue", "history"]).has(
|
||||
normalizeRecallGenerationType(generationType),
|
||||
);
|
||||
}
|
||||
|
||||
export function isTrustedUserFloorRecallSource(source = "") {
|
||||
return new Set([
|
||||
"chat-last-user",
|
||||
"chat-latest-user",
|
||||
"chat-tail-user",
|
||||
"message-sent",
|
||||
"persisted-user-floor",
|
||||
]).has(String(source || "").trim());
|
||||
}
|
||||
|
||||
export function buildPersistedReuseRecallInput(recallInput = {}, record = {}, runtime) {
|
||||
const boundUserFloorText = normalizeRecallTextForRuntime(
|
||||
runtime,
|
||||
record.boundUserFloorText || recallInput.boundUserFloorText || "",
|
||||
);
|
||||
return {
|
||||
...recallInput,
|
||||
source: "persisted-user-floor",
|
||||
sourceLabel: "复用用户楼层召回",
|
||||
reason: "persisted-user-floor-reuse",
|
||||
authoritativeInputUsed: Boolean(
|
||||
record.authoritativeInputUsed || recallInput.authoritativeInputUsed,
|
||||
),
|
||||
boundUserFloorText,
|
||||
};
|
||||
}
|
||||
|
||||
function resolveReusablePersistedRecallRecord(chat, recallInput, runtime) {
|
||||
const generationType = normalizeRecallGenerationType(recallInput?.generationType);
|
||||
|
||||
let targetUserMessageIndex = normalizeRecallTargetUserMessageIndex(
|
||||
recallInput?.targetUserMessageIndex,
|
||||
);
|
||||
|
||||
const readPersistedRecallFromUserMessage = runtime.readPersistedRecallFromUserMessage;
|
||||
if (typeof readPersistedRecallFromUserMessage !== "function") return null;
|
||||
|
||||
const normalizeText = (value = "") => normalizeRecallTextForRuntime(runtime, value);
|
||||
const currentRecallInputText = normalizeText(recallInput?.userMessage || "");
|
||||
const recallSource = String(recallInput?.source || "").trim();
|
||||
const isActiveInputSource = isActiveRecallInputSource(recallSource);
|
||||
const isNoNewUserGeneration = isNoNewUserGenerationType(generationType);
|
||||
if (isActiveInputSource && !isNoNewUserGeneration) {
|
||||
return null;
|
||||
}
|
||||
@@ -213,18 +254,11 @@ function resolveReusablePersistedRecallRecord(chat, recallInput, runtime) {
|
||||
!isActiveInputSource &&
|
||||
String(record?.injectionText || "").trim(),
|
||||
);
|
||||
const userFloorSources = new Set([
|
||||
"chat-last-user",
|
||||
"chat-latest-user",
|
||||
"chat-tail-user",
|
||||
"message-sent",
|
||||
"persisted-user-floor",
|
||||
]);
|
||||
const canTrustUserFloorRecord = Boolean(
|
||||
(!isActiveInputSource || isNoNewUserGeneration) &&
|
||||
!boundUserFloorText &&
|
||||
!recordRecallInputMismatch &&
|
||||
(generationType !== "normal" || userFloorSources.has(recallSource)),
|
||||
(generationType !== "normal" || isTrustedUserFloorRecallSource(recallSource)),
|
||||
);
|
||||
|
||||
if (
|
||||
@@ -618,31 +652,11 @@ export async function runRecallController(runtime, options = {}) {
|
||||
runtime,
|
||||
);
|
||||
if (earlyPersistedReuse) {
|
||||
const normalizedBoundUserFloorText =
|
||||
typeof runtime.normalizeRecallInputText === "function"
|
||||
? runtime.normalizeRecallInputText(
|
||||
earlyPersistedReuse.record.boundUserFloorText ||
|
||||
recallInput.boundUserFloorText ||
|
||||
"",
|
||||
)
|
||||
: String(
|
||||
earlyPersistedReuse.record.boundUserFloorText ||
|
||||
recallInput.boundUserFloorText ||
|
||||
"",
|
||||
)
|
||||
.replace(/\r\n/g, "\n")
|
||||
.trim();
|
||||
const effectiveRecallInput = {
|
||||
...recallInput,
|
||||
source: "persisted-user-floor",
|
||||
sourceLabel: "复用用户楼层召回",
|
||||
reason: "persisted-user-floor-reuse",
|
||||
authoritativeInputUsed: Boolean(
|
||||
earlyPersistedReuse.record.authoritativeInputUsed ||
|
||||
recallInput.authoritativeInputUsed,
|
||||
),
|
||||
boundUserFloorText: normalizedBoundUserFloorText,
|
||||
};
|
||||
const effectiveRecallInput = buildPersistedReuseRecallInput(
|
||||
recallInput,
|
||||
earlyPersistedReuse.record,
|
||||
runtime,
|
||||
);
|
||||
const reusedResult = buildPersistedRecallReuseResult(earlyPersistedReuse.record);
|
||||
const applied = runtime.applyRecallInjection(
|
||||
settings,
|
||||
|
||||
89
tests/recall-controller-helpers.mjs
Normal file
89
tests/recall-controller-helpers.mjs
Normal file
@@ -0,0 +1,89 @@
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
import {
|
||||
buildPersistedReuseRecallInput,
|
||||
isActiveRecallInputSource,
|
||||
isNoNewUserGenerationType,
|
||||
isTrustedUserFloorRecallSource,
|
||||
normalizeRecallGenerationType,
|
||||
normalizeRecallTargetUserMessageIndex,
|
||||
normalizeRecallTextForRuntime,
|
||||
} from '../retrieval/recall-controller.js';
|
||||
|
||||
assert.equal(normalizeRecallGenerationType(' regenerate '), 'regenerate');
|
||||
assert.equal(normalizeRecallGenerationType(''), 'normal');
|
||||
assert.equal(normalizeRecallGenerationType(null), 'normal');
|
||||
|
||||
assert.equal(normalizeRecallTargetUserMessageIndex(3.9), 3);
|
||||
assert.equal(normalizeRecallTargetUserMessageIndex(Number.NaN), null);
|
||||
assert.equal(normalizeRecallTargetUserMessageIndex('3'), null);
|
||||
|
||||
assert.equal(normalizeRecallTextForRuntime(null, ' a\r\nb '), 'a\nb');
|
||||
assert.equal(
|
||||
normalizeRecallTextForRuntime({ normalizeRecallInputText: (value) => `x:${String(value).trim()}` }, ' a '),
|
||||
'x:a',
|
||||
);
|
||||
|
||||
for (const source of [
|
||||
'send-intent',
|
||||
'generation-started-send-intent',
|
||||
'generation-started-textarea',
|
||||
'host-generation-lifecycle',
|
||||
'textarea-live',
|
||||
'planner-handoff',
|
||||
]) {
|
||||
assert.equal(isActiveRecallInputSource(source), true, source);
|
||||
}
|
||||
assert.equal(isActiveRecallInputSource('chat-last-user'), false);
|
||||
|
||||
for (const generationType of ['swipe', 'regenerate', 'continue', 'history']) {
|
||||
assert.equal(isNoNewUserGenerationType(generationType), true, generationType);
|
||||
}
|
||||
assert.equal(isNoNewUserGenerationType('normal'), false);
|
||||
|
||||
for (const source of [
|
||||
'chat-last-user',
|
||||
'chat-latest-user',
|
||||
'chat-tail-user',
|
||||
'message-sent',
|
||||
'persisted-user-floor',
|
||||
]) {
|
||||
assert.equal(isTrustedUserFloorRecallSource(source), true, source);
|
||||
}
|
||||
assert.equal(isTrustedUserFloorRecallSource('textarea-live'), false);
|
||||
|
||||
{
|
||||
const recallInput = {
|
||||
source: 'chat-last-user',
|
||||
sourceLabel: '历史最后用户楼层',
|
||||
reason: 'chat-tail-fallback',
|
||||
authoritativeInputUsed: false,
|
||||
boundUserFloorText: ' fallback floor ',
|
||||
deliveryMode: 'deferred',
|
||||
};
|
||||
const record = {
|
||||
authoritativeInputUsed: true,
|
||||
boundUserFloorText: ' persisted floor ',
|
||||
};
|
||||
const result = buildPersistedReuseRecallInput(recallInput, record, {
|
||||
normalizeRecallInputText: (value) => String(value || '').trim().toUpperCase(),
|
||||
});
|
||||
assert.equal(result.source, 'persisted-user-floor');
|
||||
assert.equal(result.sourceLabel, '复用用户楼层召回');
|
||||
assert.equal(result.reason, 'persisted-user-floor-reuse');
|
||||
assert.equal(result.authoritativeInputUsed, true);
|
||||
assert.equal(result.boundUserFloorText, 'PERSISTED FLOOR');
|
||||
assert.equal(result.deliveryMode, 'deferred');
|
||||
}
|
||||
|
||||
{
|
||||
const result = buildPersistedReuseRecallInput(
|
||||
{ authoritativeInputUsed: true, boundUserFloorText: 'input\r\ntext' },
|
||||
{},
|
||||
null,
|
||||
);
|
||||
assert.equal(result.authoritativeInputUsed, true);
|
||||
assert.equal(result.boundUserFloorText, 'input\ntext');
|
||||
}
|
||||
|
||||
console.log('recall-controller-helpers tests passed');
|
||||
Reference in New Issue
Block a user