refactor(recall): extract persisted reuse helpers

This commit is contained in:
youzini
2026-06-09 17:03:48 +00:00
parent 8365d2f7f0
commit 7df1bd8cf5
2 changed files with 161 additions and 58 deletions

View File

@@ -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,

View 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');