diff --git a/src/config/zod-schema.ts b/src/config/zod-schema.ts index 6ea3bd00287..7725e64569b 100644 --- a/src/config/zod-schema.ts +++ b/src/config/zod-schema.ts @@ -103,6 +103,7 @@ const MemoryQmdSchema = z update: MemoryQmdUpdateSchema.optional(), limits: MemoryQmdLimitsSchema.optional(), scope: SessionSendPolicySchema.optional(), + weights: z.record(z.string(), z.number().positive()).optional(), }) .strict(); diff --git a/src/memory/qmd-manager.ts b/src/memory/qmd-manager.ts index 700bbe7bc10..2e93ce0b528 100644 --- a/src/memory/qmd-manager.ts +++ b/src/memory/qmd-manager.ts @@ -633,6 +633,8 @@ export class QmdMemoryManager implements MemorySearchManager { } const qmdSearchCommand = this.qmd.searchMode; const mcporterEnabled = this.qmd.mcporter.enabled; + // When weights are enabled, defer minScore filtering until after re-ranking + const upstreamMinScore = hasWeights ? 0 : (opts?.minScore ?? 0); const runSearchAttempt = async ( allowMissingCollectionRepair: boolean, ): Promise => { @@ -644,13 +646,12 @@ export class QmdMemoryManager implements MemorySearchManager { : qmdSearchCommand === "vsearch" ? "vector_search" : "deep_search"; - const minScore = opts?.minScore ?? 0; if (collectionNames.length > 1) { return await this.runMcporterAcrossCollections({ tool, query: trimmed, limit: fetchLimit, - minScore, + minScore: upstreamMinScore, collectionNames, }); } @@ -659,7 +660,7 @@ export class QmdMemoryManager implements MemorySearchManager { tool, query: trimmed, limit: fetchLimit, - minScore, + minScore: upstreamMinScore, collection: collectionNames[0], timeoutMs: this.qmd.limits.timeoutMs, }); @@ -740,11 +741,12 @@ export class QmdMemoryManager implements MemorySearchManager { const lines = this.extractSnippetLines(snippet); let score = typeof entry.score === "number" ? entry.score : 0; - // Apply weights + // Apply weights (first matching pattern wins) if (hasWeights) { for (const [pattern, weight] of Object.entries(weights)) { if (this.matchesPath(doc.rel, pattern)) { score *= weight; + break; } } }