Skip to content

Dual search box, vector and lexical, plus hybrid slider#4744

Draft
joelochlann wants to merge 4 commits into
mainfrom
js-manual-hybrid-search
Draft

Dual search box, vector and lexical, plus hybrid slider#4744
joelochlann wants to merge 4 commits into
mainfrom
js-manual-hybrid-search

Conversation

@joelochlann

@joelochlann joelochlann commented May 20, 2026

Copy link
Copy Markdown
Member

It seems like the hybrid search perform that well in cases like:

  • "Hamburg in the rain"
  • "Liverpool at dusk"
  • "A busy street scene in Manchester"

I was curious whether manually separating out the specific bits ("Hamburg", "Liverpool") from generic ("in the rain", "at dusk") might improve matters.

To that end, I've added a new AI search mode, hidden behind a feature switch & UI toggle, that provides a dual search box:

  • If AI search box is empty, it behaves exactly like the Grid currently (lexical search only)
  • If lexical search box is empty, it behaves like "use AI search" ticked (knn only)
  • If both, it filters on the lexical (as per current Grid behaviour), then ranks by knn

This is currently intended to be used by us for evaluation purposes, not necessarily directly by normal Grid users.

The idea is that if, when we evaluate hybrid search, we find cases where it struggles regardless of the mix, we have another approach that we can manually experiment with to see if better results are possible in principle given current functionality.

If we confirm that a manual hybrid does work the best, we would need to decide whether to give that control directly to users, or perhaps have a lightweight model doing the splitting up of the query on behalf of users and allowing power users to modify the dual query manually if they wish.

I've also added a slider for hybrid search weight in the UI, to make our evaluation process a bit easier.

Dual search box

The dual searchbox is gated from users in two ways:

1. You must enable a feature switch to access the feature (in addition to the AI feature switch toggle)

Screenshot 2026-05-28 at 11 46 24

Without this switch on, it looks just like the existing search.

2. You must toggle hybrid => manual

Screenshot 2026-05-28 at 11 59 35 Screenshot 2026-05-28 at 11 59 39

Slider

This is accessible, but hidden behind an unobtrusive toggle icon, regardless of whether the new feature switch is on or not
Screenshot 2026-05-28 at 12 06 21
Screenshot 2026-05-28 at 12 06 28

Other screenshots

Screenshot 2026-05-28 at 11 38 43 Screenshot 2026-05-28 at 11 40 06

@github-actions

github-actions Bot commented May 20, 2026

Copy link
Copy Markdown

@ellenmuller ellenmuller left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the same question/comment three times, otherwise looks good from what I can see!

Comment thread kahuna/public/js/search/results.js Outdated
// TODO: avoid this initial search (two API calls to init!)
const isAiSearch = !!$stateParams.useAISearch;
// AI/KNN search activates when an aiQuery is present.
const isAiSearch = !!($stateParams.aiQuery && $stateParams.aiQuery.trim());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to trim?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess in case there were accidental leading or trailing spaces typed in by the user? But not sure if this is the right place to do that. Or if we do it here, why not for everything

Comment thread kahuna/public/js/search/results.js Outdated

ctrl.loadRange = function(start, end) {
if ($stateParams.useAISearch) {
if ($stateParams.aiQuery && $stateParams.aiQuery.trim()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Comment thread kahuna/public/js/search/results.js Outdated
// Polling for new images is meaningless for AI search — results are
// ranked by vector similarity, not upload time.
if ($stateParams.useAISearch) { return; }
if ($stateParams.aiQuery && $stateParams.aiQuery.trim()) { return; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above :)

@ellenmuller ellenmuller left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice idea and I think we should have a conversation about it with the data scientists too. I'd want to think through the implications of filtering by lexical and then ranking by knn... One of the implications would be that we wouldn't be able to surface images without any metadata/description etc right?

@jonathonherbert

Copy link
Copy Markdown
Contributor

Cool! Alternative pattern might be to introduce it as a field, e.g. 'liverpool looks-like:"city at dusk"'

Feels much less discoverable for what is (I assume!) going to be on a hot UI path, though!

@paperboyo

Copy link
Copy Markdown
Contributor

I'd want to think through the implications of filtering by lexical and then ranking by knn... One of the implications would be that we wouldn't be able to surface images without any metadata/description etc right?

+1. There are arguments for both pre-filtering and post-filtering, I think. Just hard to think of UX that will allow both… But given that we only have 200 results to post-filter, I think pre-filtering this PR proposes is a stronger use case? Maybe?

Would love to chat. My head hurts trying to come up with UX/UI ideas given all the possibilities (add sorting and vecWeight and it explodes ;-)

@joelochlann

Copy link
Copy Markdown
Member Author

One of the implications would be that we wouldn't be able to surface images without any metadata/description etc right?

Nope. If AI search is empty, it's just a metadata search. If metadata search is empty, is just an AI search.

@joelochlann joelochlann added the feature Departmental tracking: work on a new feature label May 28, 2026
@joelochlann joelochlann changed the title [VIBE-CODED] Dual search box, vector and lexical Dual search box, vector and lexical, plus hybrid slider May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Departmental tracking: work on a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants