Feature/unified nl search #106
+18
-4
@@ -364,10 +364,24 @@ pub async fn unified_search<TagD: TagDao>(
|
||||
// ── 4. Rank ──
|
||||
match semantic {
|
||||
Some(ref sem) => {
|
||||
// Semantic term present: CLIP-rank, then keep only hits that pass
|
||||
// the structured filters (by content_hash).
|
||||
let scored =
|
||||
match score_photos(&state, &exif_dao, sem, &library_ids, threshold, None).await {
|
||||
// When structured filters are present they ARE the constraint —
|
||||
// CLIP only ranks within the candidate set. So drop the global
|
||||
// similarity threshold (it's tuned for whole-library search and
|
||||
// would pre-discard filter-matching photos that scored just under
|
||||
// it — e.g. a 2022 beach photo at 0.18 — before the intersection
|
||||
// ever runs). With no filters, keep the user's threshold for the
|
||||
// plain semantic case.
|
||||
let clip_threshold = if has_struct { -1.0 } else { threshold };
|
||||
let scored = match score_photos(
|
||||
&state,
|
||||
&exif_dao,
|
||||
sem,
|
||||
&library_ids,
|
||||
clip_threshold,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(s) => s,
|
||||
Err(e) => return score_error_response(e),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user