Search Multi-Index
One query, four libraries, one merged result set
- model
- index_1
- index_2
- index_3
- index_4
- results
Most people who use this pack end up with more than one index - "portraits", "products", "archives" - and then immediately want to search across all of them. Search Multi-Index is that node: you feed it one text query and up to four SEMANTIC_INDEX handles, and it searches each, merges the results, deduplicates by file path, and returns a single ranked SEARCH_RESULTS set.
The interesting mechanics are in the merging. Indexes built at different times, with different embedding models, or on different libraries can have score distributions that don't compare cleanly - index A's 0.5 might be a great match while index B's 0.5 is noise. That's what normalize_scores (default true) is for: it rescales each index's raw scores into a 0–1 range within that index before merging, so a strong match in a picky index competes fairly with a strong match in a generous one. The README's note is the practical rule: if the same file appears in more than one index, only the highest score survives.
Inputs
Required: model, query, index_1. Optional: index_2, index_3, index_4 (leave unconnected to skip), top_k (default 50 - total across all indexes, not per index), normalize_scores, min_score, result_type, instruction. Output: results (SEARCH_RESULTS).
One quirk to keep in mind: top_k is the combined budget. Three indexes each returning 50 would blow past it, so the node sizes each index's contribution and merges. If one library dominates your results, that's usually a top_k-budget artifact, not the algorithm being unfair.
Install
Same pack install as everything else - ComfyUI Manager (search "Semantic-Search") or git clone https://github.com/EricRollei/Semantic-Search into custom_nodes, install the requirements, restart, find it under Eric/SemanticSearch.
Where people get burned
- Mixing indexes with different
embedding_dim. An 8B-model index (4096-dim) and a 2B-model index (2048-dim) can't be searched by one node - the vectors don't even have the same shape. Keep the dims consistent across the indexes you plan to combine, or rebuild one to match. - Scores look odd after merging. That's
normalize_scoresdoing its job. If it produces results that feel wrong (e.g. a weak match ranked high), try toggling it off - but know that off means raw scores, which are only comparable if the indexes were built identically. - Forgetting
index_1is required. It's the one index you must wire; the other three are optional. Staring at a node with three empty sockets and wondering why it does nothing is a rite of passage.
Search Multi-Index is the "organize your library into logical piles, then search across the piles" node. It's the natural destination once a single "default" index starts feeling like a junk drawer.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| model | EMBEDDING_MODEL | — | |
| query | STRING | — | |
| index_1 | SEMANTIC_INDEX | — | |
| index_2opt | SEMANTIC_INDEX | — | |
| index_3opt | SEMANTIC_INDEX | — | |
| index_4opt | SEMANTIC_INDEX | — | |
| top_kopt | INT | 501–500 | Total results across all indexes |
| normalize_scoresopt | BOOLEAN | true | Normalize scores to 0-1 range per index before merging |
| min_scoreopt | FLOAT | 0.000–1 | — |
| result_typeopt | COMBO | all | Filter results by media type: all, images, videos, documents, or media (images+videos) |
| instructionopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| results | SEARCH_RESULTS | — |