Unified search: use ANY-mode tag matching, not ALL
ALL-mode over-constrains NL queries — the model maps several query words to tags and few photos carry every one, zeroing the candidate set. Switch to ANY (a photo matches if it has any named tag); the semantic CLIP ranking provides precision within that pool. Exclude tags still filter out. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -264,13 +264,15 @@ pub async fn unified_search<TagD: TagDao>(
|
|||||||
let mut allowed_hashes: HashSet<String> = HashSet::new();
|
let mut allowed_hashes: HashSet<String> = HashSet::new();
|
||||||
if has_struct {
|
if has_struct {
|
||||||
// Tag membership set (rel_path only — same cross-library imprecision
|
// Tag membership set (rel_path only — same cross-library imprecision
|
||||||
// as the existing /photos tag listing). ALL-mode: the photo must
|
// as the existing /photos tag listing). ANY-mode: a photo matches if
|
||||||
// carry every named tag.
|
// it carries any of the named tags. ALL-mode over-constrains NL
|
||||||
|
// queries (the model maps several words to tags and few photos carry
|
||||||
|
// them all); the semantic term does the precision work instead.
|
||||||
let tag_set: Option<HashSet<String>> = if sq.tag_ids.is_empty() {
|
let tag_set: Option<HashSet<String>> = if sq.tag_ids.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let mut dao = tag_dao.lock().expect("tag dao");
|
let mut dao = tag_dao.lock().expect("tag dao");
|
||||||
match dao.get_files_with_all_tag_ids(
|
match dao.get_files_with_any_tag_ids(
|
||||||
sq.tag_ids.clone(),
|
sq.tag_ids.clone(),
|
||||||
sq.exclude_tag_ids.clone(),
|
sq.exclude_tag_ids.clone(),
|
||||||
&ctx,
|
&ctx,
|
||||||
|
|||||||
Reference in New Issue
Block a user