Improve pgvector keyword recall ranking without changing hybrid sort.

Rank ILIKE matches by lexical coverage instead of recency and attach lexical scores to keyword rows so MemFuseBench candidate recall rises sharply while Chinese hybrid ordering stays unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-09-02 10:01:42 +08:00
parent 0b6f79ae16
commit 2c0d903ecf
3 changed files with 89 additions and 6 deletions
+26 -3
View File
@@ -2,7 +2,9 @@ import os from 'node:os';
import path from 'node:path';
import { readFile as fsReadFile } from 'node:fs/promises';
import { createPgvectorMemoryBackend } from './memory-v2-pgvector.mjs';
import { createPgvectorMemoryBackend, pgvectorMemoryBackendInternals } from './memory-v2-pgvector.mjs';
const { lexicalQueryCoverage } = pgvectorMemoryBackendInternals;
/**
* MemFuseBench retrieval harness for Memory V2.
@@ -400,11 +402,32 @@ export function createCorpusPool({ rows, embedText, embeddingCache = new Map() }
.map(likeParamToTerm)
.filter(Boolean);
if (terms.length === 0) return { rows: [] };
const matched = byRecency.filter((row) => {
const fetchCap = Math.min(500, Math.max(limit, limit * 10));
const matched = corpus.filter((row) => {
const haystack = row.content.toLowerCase();
return terms.some((term) => haystack.includes(term));
});
return { rows: trackRows(matched.slice(0, limit).map((row) => toResultRow(row, 1))) };
let pool = matched;
if (pool.length > fetchCap) {
pool = [...matched].sort((left, right) => String(left.id).localeCompare(String(right.id)))
.slice(0, fetchCap);
}
const ranked = pool
.map((row) => ({
row,
lexicalScore: lexicalQueryCoverage(terms.join(' '), row.content),
timestampMs: row.timestampMs,
}))
.sort((left, right) => {
if (left.lexicalScore !== right.lexicalScore) {
return right.lexicalScore - left.lexicalScore;
}
return right.timestampMs - left.timestampMs;
})
.slice(0, limit);
return {
rows: trackRows(ranked.map(({ row, lexicalScore }) => toResultRow(row, lexicalScore))),
};
}
return { rows: [] };
},