bep40 commited on
Commit
fc4900c
·
verified ·
1 Parent(s): a3dab58

fix: src/merge.js

Browse files
Files changed (1) hide show
  1. src/merge.js +24 -3
src/merge.js CHANGED
@@ -249,7 +249,7 @@ export function mergeResults(interiors, products, options = {}) {
249
  // are enlarged and ringed exactly like the newest interiors, so a product
250
  // added on vai-avatar appears in this Space's "mới" front row with a neon
251
  // frame, no query needed.
252
- const RING_LIMIT = options.recentProductRing ?? 6;
253
  const recents = (options.recentProducts ?? [])
254
  .filter(item => item && typeof item === 'object' && item.sku && !seen.has(productKey(item.sku)))
255
  .sort((a, b) => (String(a.addedAt || '') < String(b.addedAt || '') ? 1 : String(a.addedAt || '') > String(b.addedAt || '') ? -1 : 0));
@@ -288,8 +288,24 @@ export function mergeResults(interiors, products, options = {}) {
288
  const showNewRow = String(options.query ?? "").trim().length === 0;
289
  out.unshift(...(showNewRow ? fresh : []));
290
 
 
 
 
 
 
 
 
 
 
 
291
  for (const image of interiors ?? []) {
292
- if (!image?.id || seen.has(interiorKey(image.id))) continue;
 
 
 
 
 
 
293
  seen.add(interiorKey(image.id));
294
  out.push(image);
295
  if (out.length >= interiorLimit) break;
@@ -322,7 +338,12 @@ export function mergeResults(interiors, products, options = {}) {
322
  if (seen.has(key)) continue;
323
  seen.add(key);
324
  const isExact = exact.has(key);
325
- scoredHits.push({ product, src, key, isExact, score: Number.isFinite(item?.score) ? item.score : 0 });
 
 
 
 
 
326
  if (scoredHits.length >= productLimit) break;
327
  }
328
  // Products arrive already ranked by the worker; the score field is the
 
249
  // are enlarged and ringed exactly like the newest interiors, so a product
250
  // added on vai-avatar appears in this Space's "mới" front row with a neon
251
  // frame, no query needed.
252
+ const RING_LIMIT = options.recentProductRing ?? 12;
253
  const recents = (options.recentProducts ?? [])
254
  .filter(item => item && typeof item === 'object' && item.sku && !seen.has(productKey(item.sku)))
255
  .sort((a, b) => (String(a.addedAt || '') < String(b.addedAt || '') ? 1 : String(a.addedAt || '') > String(b.addedAt || '') ? -1 : 0));
 
288
  const showNewRow = String(options.query ?? "").trim().length === 0;
289
  out.unshift(...(showNewRow ? fresh : []));
290
 
291
+ // A relevance floor, so a search never paints tiles that only look like the
292
+ // query by chance. CLIP cosine answers "how close in meaning", and the lowest
293
+ // results in a top-60 pull are semantically unrelated to anything typed. The
294
+ // floor is RELATIVE to the query's own top match, so it adapts to however
295
+ // decisive the query is: "bếp đá" finds a clear winner and keeps nothing
296
+ // below half its strength, while a fuzzy query keeps a slightly broader tail.
297
+ // Tiles without a score (browse mode) are unaffected.
298
+ const cosineFloor = options.cosFloor ?? 0.18;
299
+ const cosineRel = options.cosRel ?? 0.45;
300
+ let topCosine = 0;
301
  for (const image of interiors ?? []) {
302
+ if (Number.isFinite(image?.score) && image.score > topCosine) topCosine = image.score;
303
+ }
304
+ const effectiveFloor = Math.max(cosineFloor, topCosine * cosineRel);
305
+ for (const image of interiors ?? []) {
306
+ const score = image?.score;
307
+ const filteredScore = score === undefined || !Number.isFinite(score) || score >= effectiveFloor;
308
+ if (!image?.id || !filteredScore || seen.has(interiorKey(image.id))) continue;
309
  seen.add(interiorKey(image.id));
310
  out.push(image);
311
  if (out.length >= interiorLimit) break;
 
338
  if (seen.has(key)) continue;
339
  seen.add(key);
340
  const isExact = exact.has(key);
341
+ const productFloor = options.productFloor ?? 20;
342
+ const score = Number.isFinite(item?.score) ? item.score : 0;
343
+ // A product that only scraped a 3-point token overlap is noise, not an
344
+ // answer: it would paint an unrelated photograph next to the query typed.
345
+ if (score < productFloor) continue;
346
+ scoredHits.push({ product, src, key, isExact, score });
347
  if (scoredHits.length >= productLimit) break;
348
  }
349
  // Products arrive already ranked by the worker; the score field is the