feat(compression): relevance extractive engine — roadmap #7 (#5289)

* test(compression): failing tests for relevance engine scorer + apply

* feat(compression): relevance extractive engine — scores sentences against last user query

* test(compression): regression tests for relevance engine review fixes (threshold/multimodal/force-preserve/whitespace/query)

* fix(compression): relevance engine hardening from core review

- overlapThreshold was dead config (|| kept<budget made it unreachable) → real threshold gate
- multimodal: only compress when exactly one text block (was stamping joined text into every block)
- force-preserve sentences are now 'free' (don't consume budget) so they can't starve top-relevance
- preserve inter-sentence whitespace (\n\n survives) instead of flattening to single spaces
- ROOT-CAUSE: stop gating preserve on ultraHeuristic FORCE_PRESERVE_RE — it matches the period
  ending every sentence, so it force-preserved everything (no-op). New SENTENCE_PRESERVE_RE anchors
  on real signals (digits/URL/Error:/code/at-frame/path/key=value), mirroring #17's UNIT_PRESERVE_RE
- core-review suggestion to skip the query message: rejected (self-overlap already protects it;
  skipping would no-op the single-message RAG case) — documented + test updated

* docs(changelog): restore relevance engine bullet (#7, eaten by rebase)
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-29 01:25:41 -03:00
committed by GitHub
parent fa94f38de5
commit 21c1f540b3
9 changed files with 782 additions and 0 deletions

View File

@@ -14,6 +14,7 @@ _In development — bullets added per PR; finalized at release._
### ✨ New Features
- **feat(compression): relevance extractive engine** — a new opt-in compression engine that scores each sentence by term-overlap (Jaccard) with the user's last query minus a length/boilerplate penalty, greedily keeps the most relevant within a budget, and reconstructs the original order. Pure-string, deterministic, ReDoS-safe (char-code tokenization, no `RegExp` over user input), fail-open, default off. Ideal for trimming long pasted RAG context / tool output to what's relevant. Sentences carrying real signal (digits/URLs/errors/code/paths) are never dropped; `overlapThreshold`/`budgetPercent`/`boilerplateWeight` are configurable. Tier-2 item of the compression feature-extraction roadmap (#7).
- **feat(compression): hard-budget mode — compress to ≤ N tokens** — a deterministic post-pass (`targetTokens` / `targetRatio`, default unset → no-op) that trims a body to a token budget. It ranks sentences/lines by average `scoreToken` ascending and drops the lowest-saliency ones until the body fits (measured by the exact cl100k `countTextTokens`), preserving original order. Lines carrying real signal (digits, URLs, `Error:`-family, code fences, stack `at`-frames, multi-segment paths, `key=value`) are never dropped; the budget is distributed proportionally across messages so the total stays ≤ target; an unreachable target (all-preserved) surfaces a `validationWarnings` note instead of failing silently. Does NOT touch the `estimateCompressionTokens` budget-gate estimator. Tier-3 item of the compression feature-extraction roadmap (#17).
- **feat(compression): result memoization for deterministic engines (opt-in)** — caches `(input, config) → result` for provably pure, stateless modes (`lite`/`standard`/`rtk` and stacked pipelines of `{lite,caveman,rtk}`) to skip recompute on the hot path. Opt-in via `memoizeCompressionResults` (default off → zero behavior change). Conservative opt-in whitelist (stateful `ccr`/`session-dedup` — which write the cross-request CCR store — and model-backed `ultra`/`aggressive`/`llmlingua` are never cached), principal-scoped (skipped without a principal, so no cross-principal body leak), and clone-on-store + clone-on-read. Tier-3 item of the compression feature-extraction roadmap (#21).
- **feat(compression): inline transparency annotation** — surfaces `tokens=847→312; rules: filler×8, dedup×2` derived from existing compression stats. The `X-OmniRoute-Compression` response header is extended **append-only** (the `mode; source=X` prefix stays byte-identical, so existing header parsers don't break) and the compression studio cockpit shows a matching badge. Zero new computation — it aggregates the `rulesApplied`/`techniquesUsed` already on the stats. Tier-3 item of the compression feature-extraction roadmap (#18).

View File

@@ -44,6 +44,13 @@ export const ENGINE_CATALOG: Record<string, EngineMeta> = {
isSingleMode: false,
description: "Tabular JSON compaction.",
},
relevance: {
id: "relevance",
label: "Relevance",
stackPriority: 18,
isSingleMode: true,
description: "Extractive sentence scoring against the last user query.",
},
caveman: {
id: "caveman",
label: "Caveman",

View File

@@ -6,6 +6,7 @@ import { headroomEngine } from "./headroom/index.ts";
import { ccrEngine } from "./ccr/index.ts";
import { llmlinguaEngine } from "./llmlingua/index.ts";
import { ionizerEngine } from "./ionizer/index.ts";
import { relevanceEngine } from "./relevance/index.ts";
let registered = false;
@@ -28,6 +29,7 @@ export function registerBuiltinCompressionEngines(): void {
{ id: "ccr", engine: ccrEngine },
{ id: "llmlingua", engine: llmlinguaEngine },
{ id: "ionizer", engine: ionizerEngine },
{ id: "relevance", engine: relevanceEngine },
];
for (const { id, engine } of engines) {

View File

@@ -0,0 +1,63 @@
import type { EngineConfigField, EngineValidationResult } from "../types.ts";
import type { RelevanceConfig } from "../../types.ts";
export const RELEVANCE_SCHEMA: EngineConfigField[] = [
{
key: "enabled",
type: "boolean",
label: "Enabled",
defaultValue: false,
},
{
key: "overlapThreshold",
type: "number",
label: "Overlap threshold",
description: "Sentences with Jaccard overlap below this are candidates for removal.",
defaultValue: 0.1,
min: 0,
max: 1,
},
{
key: "budgetPercent",
type: "number",
label: "Budget percent",
description: "Target fraction of original character count to retain (01).",
defaultValue: 0.5,
min: 0.1,
max: 1,
},
{
key: "boilerplateWeight",
type: "number",
label: "Boilerplate weight",
description: "Weight applied to boilerplate penalty when scoring sentences.",
defaultValue: 0.5,
min: 0,
max: 1,
},
];
export function validateRelevanceConfig(config: Record<string, unknown>): EngineValidationResult {
const errors: string[] = [];
if (config.enabled !== undefined && typeof config.enabled !== "boolean") {
errors.push("enabled must be a boolean");
}
for (const key of ["overlapThreshold", "budgetPercent", "boilerplateWeight"]) {
if (config[key] !== undefined) {
const v = config[key];
if (typeof v !== "number" || v < 0 || v > 1) {
errors.push(`${key} must be a number between 0 and 1`);
}
}
}
return { valid: errors.length === 0, errors };
}
export function resolveRelevanceConfig(stepConfig: Record<string, unknown>): RelevanceConfig {
return {
enabled: typeof stepConfig.enabled === "boolean" ? stepConfig.enabled : false,
overlapThreshold: typeof stepConfig.overlapThreshold === "number" ? stepConfig.overlapThreshold : 0.1,
budgetPercent: typeof stepConfig.budgetPercent === "number" ? stepConfig.budgetPercent : 0.5,
boilerplateWeight: typeof stepConfig.boilerplateWeight === "number" ? stepConfig.boilerplateWeight : 0.5,
};
}

View File

@@ -0,0 +1,185 @@
import { createCompressionStats } from "../../stats.ts";
import type { CompressionResult } from "../../types.ts";
import type { CompressionEngine } from "../types.ts";
import { RELEVANCE_SCHEMA, validateRelevanceConfig, resolveRelevanceConfig } from "./configSchema.ts";
import { scoreSentences } from "./scorer.ts";
// Sentence-level "never drop" guard. We canNOT reuse ultraHeuristic's FORCE_PRESERVE_RE
// here: that token-level pattern includes `[._/\\]`, which matches the period ending EVERY
// prose sentence — gating on it would force-preserve everything and make the engine a
// permanent no-op (the same trap #17's UNIT_PRESERVE_RE avoids). Anchor on real signals:
// digits, URLs, error prefixes, code fences, stack `at`-frames, multi-segment paths, key=value.
const SENTENCE_PRESERVE_RE =
/\d|https?:\/\/|(?:Error|Exception|TypeError|RangeError|SyntaxError|ReferenceError|Traceback):|```|^\s*at\s|\/[\w.-]+\/|\w+=\S/i;
// Split AFTER the sentence-final punctuation + its trailing whitespace, keeping that
// whitespace attached to the preceding sentence so a rejoin with "" preserves the
// original paragraph/line structure (e.g. `\n\n` between sentences survives).
const SENTENCE_SPLIT_RE = /(?<=[.!?]\s)/;
function extractText(content: unknown): string {
if (typeof content === "string") return content;
if (Array.isArray(content)) {
return content
.map((block) => {
if (block && typeof block === "object" && "text" in block) {
return String((block as { text: unknown }).text);
}
return "";
})
.join(" ");
}
return "";
}
function splitSentences(text: string): string[] {
return text.split(SENTENCE_SPLIT_RE).filter((s) => s.trim().length > 0);
}
function applyRelevanceToText(
text: string,
query: string,
cfg: ReturnType<typeof resolveRelevanceConfig>
): { result: string; changed: boolean } {
const sentences = splitSentences(text);
if (sentences.length <= 1) return { result: text, changed: false };
const scores = scoreSentences(sentences, query, cfg);
const totalChars = text.length;
const budget = Math.floor(totalChars * cfg.budgetPercent);
const indexed = sentences.map((s, i) => ({ s, i, score: scores[i] }));
const sorted = [...indexed].sort((a, b) => b.score - a.score);
const keepSet = new Set<number>();
// 1) Force-preserved sentences (errors / code / numbers / URLs) are kept unconditionally
// and are "free" — they do NOT consume the budget, so they cannot starve the
// highest-relevance content (core-review issue: force-preserve starvation).
for (const { s, i } of indexed) {
if (SENTENCE_PRESERVE_RE.test(s)) keepSet.add(i);
}
// 2) Greedily admit non-force sentences by score desc, gated by overlapThreshold, until
// the budget fills. The array is sorted desc, so once below budget we can break.
// (Previously the threshold was dead code behind `|| kept < budget`.)
let kept = 0;
for (const { s, i, score } of sorted) {
if (keepSet.has(i)) continue;
if (kept >= budget) break;
if (score >= cfg.overlapThreshold) {
keepSet.add(i);
kept += s.length + 1;
}
}
// 3) Never drop everything: keep at least the single highest-scoring sentence.
if (keepSet.size === 0 && sorted.length > 0) keepSet.add(sorted[0].i);
if (keepSet.size === sentences.length) return { result: text, changed: false };
const ordered = indexed.filter(({ i }) => keepSet.has(i)).sort((a, b) => a.i - b.i);
const result = ordered.map(({ s }) => s).join("");
return { result, changed: result !== text };
}
export const relevanceEngine: CompressionEngine = {
id: "relevance",
name: "Relevance",
description: "Extractive sentence scoring against the last user query.",
icon: "target",
targets: ["messages"],
stackable: true,
stackPriority: 18,
metadata: {
id: "relevance",
name: "Relevance",
description: "Extractive sentence scoring against the last user query.",
inputScope: "messages",
targetLatencyMs: 2,
supportsPreview: true,
stable: true,
},
apply(body, options): CompressionResult {
try {
const messages = body.messages;
if (!Array.isArray(messages)) return { body, compressed: false, stats: null };
const cfg = resolveRelevanceConfig((options?.stepConfig as Record<string, unknown>) ?? {});
let query = "";
for (let i = messages.length - 1; i >= 0; i--) {
const msg = messages[i] as Record<string, unknown>;
if (msg.role === "user") {
query = extractText(msg.content).trim();
break;
}
}
if (!query) return { body, compressed: false, stats: null };
// Note: the query is a string snapshot taken BEFORE compression, so compressing the
// last user message against it is NOT circular — and that message commonly carries
// the pasted context the feature is meant to trim ("docs longos colados"). So we do
// NOT skip it (a core-review suggestion to skip the query message was rejected: it
// would no-op the dominant single-message RAG use case).
let anyChanged = false;
const newMessages = messages.map((msg) => {
const m = msg as Record<string, unknown>;
if (m.role !== "user") return msg;
// String content: compress in place.
if (typeof m.content === "string") {
const { result, changed } = applyRelevanceToText(m.content, query, cfg);
if (!changed) return msg;
anyChanged = true;
return { ...m, content: result };
}
// Array/multimodal content: only safe when there is EXACTLY ONE text block.
// Joining all text blocks and stamping the result into each would duplicate and
// scramble per-block content (core-review issue: multimodal corruption).
if (Array.isArray(m.content)) {
const textBlocks = m.content.filter(
(b) => b && typeof b === "object" && "text" in b
);
if (textBlocks.length !== 1) return msg; // 0 or ≥2 text blocks ⇒ no-op
const { result, changed } = applyRelevanceToText(
String((textBlocks[0] as { text: unknown }).text),
query,
cfg
);
if (!changed) return msg;
anyChanged = true;
const newContent = m.content.map((block) =>
block === textBlocks[0]
? { ...(block as object), text: result }
: block
);
return { ...m, content: newContent };
}
return msg;
});
if (!anyChanged) return { body, compressed: false, stats: null };
const newBody = { ...body, messages: newMessages };
const stats = createCompressionStats(body, newBody, "stacked", ["relevance-extract"]);
return { body: newBody, compressed: true, stats };
} catch {
return { body, compressed: false, stats: null };
}
},
compress(body, config) {
return this.apply(body, { stepConfig: config });
},
getConfigSchema() {
return RELEVANCE_SCHEMA;
},
validateConfig(config) {
return validateRelevanceConfig(config);
},
};

View File

@@ -0,0 +1,85 @@
import type { RelevanceConfig } from "../../types.ts";
const BOILERPLATE_TOKENS = new Set([
"please",
"note",
"important",
"indeed",
"certainly",
"basically",
"essentially",
"obviously",
"clearly",
"simply",
"just",
"really",
"actually",
"honestly",
"conclusion",
"summary",
"hope",
"understand",
"thing",
"things",
"something",
]);
function tokenize(text: string): string[] {
const lower = text.toLowerCase();
const tokens: string[] = [];
let start = -1;
for (let i = 0; i <= lower.length; i++) {
const ch = i < lower.length ? lower.charCodeAt(i) : -1;
const isAlnum =
ch !== -1 &&
((ch >= 97 && ch <= 122) || (ch >= 48 && ch <= 57));
if (isAlnum) {
if (start === -1) start = i;
} else {
if (start !== -1) {
tokens.push(lower.slice(start, i));
start = -1;
}
}
}
return tokens;
}
function jaccard(setA: Set<string>, setB: Set<string>): number {
if (setA.size === 0 || setB.size === 0) return 0;
let intersection = 0;
for (const t of setA) {
if (setB.has(t)) intersection++;
}
const union = setA.size + setB.size - intersection;
return union === 0 ? 0 : intersection / union;
}
function boilerplateScore(tokens: string[]): number {
if (tokens.length === 0) return 0;
let count = 0;
for (const t of tokens) {
if (BOILERPLATE_TOKENS.has(t)) count++;
}
return count / tokens.length;
}
export function scoreSentences(
sentences: string[],
query: string,
cfg: RelevanceConfig
): number[] {
if (sentences.length === 0) return [];
if (!query || query.trim().length === 0) return sentences.map(() => 0);
const queryTokens = new Set(tokenize(query));
return sentences.map((sentence) => {
const sentTokens = tokenize(sentence);
if (sentTokens.length === 0) return 0;
const sentSet = new Set(sentTokens);
const overlap = jaccard(sentSet, queryTokens);
const boilerplate = boilerplateScore(sentTokens) * cfg.boilerplateWeight;
return Math.max(0, overlap - boilerplate);
});
}

View File

@@ -110,6 +110,13 @@ export interface RtkConfig {
renderers?: string[];
}
export interface RelevanceConfig {
enabled: boolean;
overlapThreshold: number;
budgetPercent: number;
boilerplateWeight: number;
}
export interface CompressionLanguageConfig {
enabled: boolean;
defaultLanguage: string;
@@ -160,6 +167,7 @@ export interface CompressionConfig {
/** Phase 4A: selected output styles (supersedes cavemanOutputMode via a back-compat shim). */
outputStyles?: OutputStyleSelectionEntry[];
rtkConfig?: RtkConfig;
relevanceConfig?: RelevanceConfig;
languageConfig?: CompressionLanguageConfig;
aggressive?: AggressiveConfig;
ultra?: UltraConfig;

View File

@@ -0,0 +1,361 @@
import test from "node:test";
import assert from "node:assert/strict";
import { relevanceEngine } from "../../../open-sse/services/compression/engines/relevance/index.ts";
function makeBody(userContent: string, priorContent?: string): Record<string, unknown> {
const messages: Array<{ role: string; content: string }> = [];
if (priorContent) {
messages.push({ role: "assistant", content: priorContent });
}
messages.push({ role: "user", content: userContent });
return { messages };
}
const LONG_CONTENT =
"Please note that I want to say something. " +
"The database connection requires a host parameter and a port number. " +
"Indeed it is very important to understand this. " +
"The port defaults to 5432 for PostgreSQL. " +
"In conclusion I hope this helps you.";
test("apply keeps relevant sentences and drops irrelevant prose", () => {
const body = {
messages: [
{ role: "user", content: "How do I configure the PostgreSQL database connection?" },
{ role: "assistant", content: LONG_CONTENT },
{
role: "user",
content:
"What is the port? " +
"Also tell me about host parameters. " +
"Unrelated: what color is the sky? " +
"PostgreSQL port is 5432. " +
"The sky is blue on a clear day. " +
"Connection requires host and port settings.",
},
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.5, overlapThreshold: 0.05 },
});
assert.equal(result.compressed, true);
const messages = result.body.messages as Array<{ content: string }>;
const lastContent = messages[messages.length - 1].content;
assert.match(lastContent, /port/i);
});
test("no-op when there is no user message in messages", () => {
const body = {
messages: [{ role: "assistant", content: "Some long assistant reply here with many words." }],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.5 },
});
assert.equal(result.compressed, false);
assert.deepEqual(result.body, body);
});
test("no-op when last user message has only one sentence", () => {
const body = {
messages: [
{ role: "user", content: "Just one sentence here." },
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.5 },
});
assert.equal(result.compressed, false);
});
test("fail-open on malformed input — returns original body", () => {
const body = { messages: "not an array" };
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true },
});
assert.equal(result.compressed, false);
assert.deepEqual(result.body, body);
});
test("determinism: same input produces same output", () => {
const body = {
messages: [
{ role: "user", content: "How does the retry mechanism work for failed requests?" },
{
role: "user",
content:
"The retry mechanism triggers after a timeout. " +
"Exponential backoff is applied between retries. " +
"Please note this is very important. " +
"The maximum retry count is configurable. " +
"Indeed this is something to consider carefully.",
},
],
};
const opts = { stepConfig: { enabled: true, budgetPercent: 0.5, overlapThreshold: 0.05 } };
const r1 = relevanceEngine.apply(body, opts);
const r2 = relevanceEngine.apply(body, opts);
assert.deepEqual(r1.body, r2.body);
assert.equal(r1.compressed, r2.compressed);
});
test("sentences matching FORCE_PRESERVE_RE are never dropped", () => {
const body = {
messages: [
{ role: "user", content: "What happened?" },
{
role: "user",
content:
"This sentence is completely unrelated to the query. " +
"Error: connection refused at port 5432. " +
"Another unrelated sentence about random things. " +
"Yet another irrelevant sentence with no matching tokens.",
},
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.3, overlapThreshold: 0.0 },
});
if (result.compressed) {
const messages = result.body.messages as Array<{ content: string }>;
const lastContent = messages[messages.length - 1].content;
assert.match(lastContent, /Error: connection refused/);
}
});
test("techniquesUsed contains relevance-extract when compression occurred", () => {
const body = {
messages: [
{ role: "user", content: "Explain database indexing." },
{
role: "user",
content:
"Database indexes speed up queries on large tables. " +
"Unrelated random words about nothing important here. " +
"Indexes are created with CREATE INDEX in SQL. " +
"Please note that this sentence is filler content only.",
},
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.5, overlapThreshold: 0.05 },
});
if (result.compressed && result.stats) {
assert.ok(
result.stats.techniquesUsed.includes("relevance-extract"),
`expected relevance-extract in techniquesUsed, got: ${result.stats.techniquesUsed}`
);
}
});
test("preserves original sentence order after greedy selection", () => {
const body = {
messages: [
{ role: "user", content: "Tell me about cats and dogs." },
{
role: "user",
content:
"Cats are independent animals. " +
"Completely irrelevant filler sentence here today. " +
"Dogs are loyal companions. " +
"Another filler sentence with random content. " +
"Cats and dogs are popular pets worldwide.",
},
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.6, overlapThreshold: 0.05 },
});
if (result.compressed) {
const messages = result.body.messages as Array<{ content: string }>;
const lastContent = messages[messages.length - 1].content;
const catIdx = lastContent.indexOf("Cats are independent");
const dogIdx = lastContent.indexOf("Dogs are loyal");
if (catIdx !== -1 && dogIdx !== -1) {
assert.ok(catIdx < dogIdx, "original order (cats before dogs) should be preserved");
}
}
});
test("array content (multimodal) is handled without crash", () => {
const body = {
messages: [
{
role: "user",
content: [
{ type: "text", text: "What is the database host?" },
],
},
],
};
assert.doesNotThrow(() => {
relevanceEngine.apply(body, { stepConfig: { enabled: true } });
});
});
test("engine metadata is correct", () => {
assert.equal(relevanceEngine.id, "relevance");
assert.equal(relevanceEngine.stackPriority, 18);
assert.ok(Array.isArray(relevanceEngine.targets));
assert.ok(relevanceEngine.getConfigSchema().length > 0);
});
// ── Issue 1: overlapThreshold must actually drop zero-overlap sentences ──────
test("zero-overlap sentences below overlapThreshold are dropped even with budget room", () => {
// Context user message with 5 relevant + 5 zero-overlap sentences. Generous
// budget (0.9) so budget alone would keep everything; overlapThreshold must
// still drop the zero-overlap ones.
const relevant = "alpha beta gamma delta epsilon configuration database query.";
const zero = "zzqqxx vvbbnn mmllkk poiuyt qwerty.";
const context =
`${relevant} ${zero} ${relevant} ${zero} ${relevant} ` +
`${zero} ${relevant} ${zero} ${relevant} ${zero}`;
const body = {
messages: [
{ role: "user", content: context },
{ role: "user", content: "alpha beta gamma delta epsilon configuration database query" },
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.9, overlapThreshold: 0.1 },
});
assert.equal(result.compressed, true);
const messages = result.body.messages as Array<{ content: string }>;
// The dropped message is the CONTEXT (index 0), not the query (Issue 5).
const compressed = messages[0].content;
assert.ok(
!compressed.includes("zzqqxx"),
`zero-overlap sentence should be dropped, got: ${compressed}`
);
assert.ok(compressed.includes("alpha beta gamma"), "relevant sentence should survive");
});
// ── Issue 2: multimodal with multiple text blocks must not be corrupted ──────
test("multimodal content with multiple text blocks is returned unchanged", () => {
const body = {
messages: [
{
role: "user",
content: [
{ type: "text", text: "Sentence A about cats. Another A sentence here." },
{ type: "image_url", image_url: { url: "data:image/png;base64,xxx" } },
{ type: "text", text: "Sentence B about dogs. Another B sentence here." },
],
},
{ role: "user", content: "cats dogs animals query text" },
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.2, overlapThreshold: 0.0 },
});
const messages = result.body.messages as Array<{
content: Array<{ type: string; text?: string }>;
}>;
const blocks = messages[0].content;
// Neither text block may be overwritten with the other's (joined) content.
assert.equal(blocks[0].text, "Sentence A about cats. Another A sentence here.");
assert.equal(blocks[2].text, "Sentence B about dogs. Another B sentence here.");
});
test("multimodal content with a single text block compresses that block in place", () => {
const body = {
messages: [
{
role: "user",
content: [
{
type: "text",
text:
"The database host is configured in settings. " +
"Completely unrelated filler about random topics here. " +
"The database port defaults to five four three two.",
},
],
},
{ role: "user", content: "database host port configuration settings" },
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.6, overlapThreshold: 0.05 },
});
if (result.compressed) {
const messages = result.body.messages as Array<{
content: Array<{ type: string; text?: string }>;
}>;
const text = messages[0].content[0].text ?? "";
assert.match(text, /database/i);
}
});
// ── Issue 3: force-preserved content must not starve high-relevance sentences ─
test("force-preserved sentences are free and do not starve top-relevance sentence", () => {
// Many force-preserved sentences (contain digits/Error: → FORCE_PRESERVE_RE)
// would fill a tiny budget; the single highest-relevance non-force sentence
// must still be kept.
const forced =
"Error: code 100. Error: code 200. Error: code 300. Error: code 400. Error: code 500.";
const relevant = "The quantum entanglement relevance signal token here.";
const filler = "Totally unrelated padding sentence with nothing useful.";
const context = `${forced} ${relevant} ${filler}`;
const body = {
messages: [
{ role: "user", content: context },
{ role: "user", content: "quantum entanglement relevance signal token" },
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.05, overlapThreshold: 0.01 },
});
assert.equal(result.compressed, true);
const messages = result.body.messages as Array<{ content: string }>;
const compressed = messages[0].content;
assert.ok(
compressed.includes("quantum entanglement relevance signal"),
`top-relevance sentence must survive despite forced content, got: ${compressed}`
);
// Forced content also survives.
assert.ok(compressed.includes("Error: code 100"));
});
// ── Issue 4: whitespace / paragraph breaks must be preserved ─────────────────
test("paragraph breaks (double newline) survive between kept sentences", () => {
const context =
"The database connection requires a host parameter.\n\n" +
"Unrelated filler sentence about random nothing.\n\n" +
"The connection also requires a port number setting.";
const body = {
messages: [
{ role: "user", content: context },
{ role: "user", content: "database connection host port setting" },
],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.7, overlapThreshold: 0.05 },
});
if (result.compressed) {
const messages = result.body.messages as Array<{ content: string }>;
const compressed = messages[0].content;
assert.match(compressed, /\n\n/, `expected paragraph break to survive, got: ${compressed}`);
}
});
// ── Issue 5 (REJECTED after review): we deliberately do NOT skip the query message.
// The query is a string snapshot taken before compression, so compressing the last user
// message against it is not circular; and that message commonly carries the pasted context
// the engine is meant to trim ("docs longos colados"). When the query IS the whole message,
// every sentence overlaps it fully → high score → kept → a natural no-op, so no special-case
// is needed. This test asserts the last user message is NOT force-skipped: a context-only
// last message with a distinct prior query message is still eligible for compression.
test("the last/only user message is NOT special-cased / skipped (eligible for compression)", () => {
// A single user message (it IS the query). With a tight budget it must still be processed
// and trimmed — proving there is no index-based early-skip of the query message.
const sentence = "alpha beta gamma delta epsilon configuration database query parameters here.";
const body = {
messages: [{ role: "user", content: Array(8).fill(sentence).join(" ") }],
};
const result = relevanceEngine.apply(body, {
stepConfig: { enabled: true, budgetPercent: 0.3, overlapThreshold: 0.0 },
});
assert.equal(result.compressed, true, "the last/only user message must be eligible for compression");
const out = (result.body.messages as Array<{ content: string }>)[0].content;
assert.ok(out.length < Array(8).fill(sentence).join(" ").length, "tight budget trims the message");
});

View File

@@ -0,0 +1,70 @@
import test from "node:test";
import assert from "node:assert/strict";
import { scoreSentences } from "../../../open-sse/services/compression/engines/relevance/scorer.ts";
const DEFAULT_CFG = {
enabled: false,
overlapThreshold: 0.1,
budgetPercent: 0.5,
boilerplateWeight: 0.5,
};
test("relevant sentence scores higher than irrelevant sentence", () => {
const sentences = [
"The quick brown fox jumps over the lazy dog",
"How do I configure the database connection?",
];
const query = "configure database connection settings";
const scores = scoreSentences(sentences, query, DEFAULT_CFG);
assert.equal(scores.length, 2);
assert.ok(scores[1] > scores[0], `expected scores[1]=${scores[1]} > scores[0]=${scores[0]}`);
});
test("boilerplate sentences are penalized relative to content sentences", () => {
const sentences = [
"Please note that this is very important information.",
"Use db.connect() with host and port parameters.",
];
const query = "connect database host port";
const scores = scoreSentences(sentences, query, DEFAULT_CFG);
assert.equal(scores.length, 2);
assert.ok(
scores[1] > scores[0],
`content sentence (${scores[1]}) should score higher than boilerplate (${scores[0]})`
);
});
test("ReDoS-safe: query with special regex characters does not throw", () => {
const sentences = ["Some normal sentence here.", "Another sentence with content."];
const maliciousQuery = "((a+)+)$ [.*+?^=!:${}()|[\\]/\\\\] test+++";
assert.doesNotThrow(() => {
const scores = scoreSentences(sentences, maliciousQuery, DEFAULT_CFG);
assert.equal(scores.length, 2);
});
});
test("empty query returns array of zeros with same length as sentences", () => {
const sentences = ["First sentence.", "Second sentence.", "Third sentence."];
const scores = scoreSentences(sentences, "", DEFAULT_CFG);
assert.equal(scores.length, 3);
assert.ok(scores.every((s) => s === 0), `all scores should be 0, got: ${scores}`);
});
test("empty sentences array returns empty array", () => {
const scores = scoreSentences([], "some query", DEFAULT_CFG);
assert.deepEqual(scores, []);
});
test("single sentence returns array of length 1", () => {
const scores = scoreSentences(["Only one sentence."], "query text", DEFAULT_CFG);
assert.equal(scores.length, 1);
assert.ok(typeof scores[0] === "number");
});
test("identical query and sentence tokens produce high score", () => {
const sentences = ["configure database connection", "unrelated random words"];
const query = "configure database connection";
const scores = scoreSentences(sentences, query, DEFAULT_CFG);
assert.ok(scores[0] > 0.5, `exact match should score above 0.5, got ${scores[0]}`);
assert.ok(scores[0] > scores[1]);
});