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:
@@ -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: [] };
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user