Skip to content

Add Semantic Search Filter to Entities Visualizer #8788

Draft
yusufkinatas wants to merge 2 commits into
yk/update-entities-visualizer-finalfrom
follow-up-entities-visualizer-semantic-search
Draft

Add Semantic Search Filter to Entities Visualizer #8788
yusufkinatas wants to merge 2 commits into
yk/update-entities-visualizer-finalfrom
follow-up-entities-visualizer-semantic-search

Conversation

@yusufkinatas
Copy link
Copy Markdown
Collaborator

@yusufkinatas yusufkinatas commented May 29, 2026

🌟 What is the purpose of this PR?

Adds a semantic search filter to the Entities Visualizer. Users can add a "Semantic search" filter from the "Add filter" menu and type a free-text query; entities are then ranked server-side by embedding similarity to that query, rather than by column sort.

This mirrors the behaviour of the global search bar (same embedding model, same distance threshold), but surfaces it as a dismissable, debounced filter pill that composes with the existing web/type/archived filters.

🔍 What does this change?

  • Filter state (data/types.ts): adds a semanticSearch: { added, query } field to EntitiesFilterState, plus a hasActiveSemanticQuery helper. added tracks whether the pill is present (it can exist with an empty query as a no-op browse); query holds the debounced free-text query.
  • Filter building (data/build-filter.ts): when a semantic query is active, pushes a cosineDistance clause against the entity embedding path, using a MAXIMUM_SEMANTIC_DISTANCE of 0.7 (matching search-bar.tsx). The query string is embedded server-side.
  • Semantic search pill (header/semantic-search-pill.tsx, new): a dismissable pill styled to match the other filter pills, with an inline borderless input. It owns its instantly-updating input buffer and reports a debounced (300ms) value upward. Uses flushOnUnmount so a final keystroke isn't dropped if the pill unmounts mid-debounce.
  • Add-filters menu (header/add-filters-menu.tsx): both menu items (Include archived, Semantic search) are now optional and self-gating, so adding one filter never blocks adding the other. The menu only hides once both extra filters are added.
  • Filter ribbon (header/filter-ribbon.tsx): wires the pill in, factors semantic search into the "filters are default" / clear-filters logic, and conditionally renders the pill.
  • Data hook (use-entities-visualizer-data.tsx): the graph layer disallows cursors alongside a cosineDistance filter ("Cannot use distance function with cursor"), so the cursor is forced off whenever a semantic query is active to guarantee the request can't 500.
  • Visualizer (entities-visualizer.tsx): wires up add/remove/change handlers (with a guard so a late debounced keystroke can't resurrect a stale query), disables "load more" while searching, and shows a "Ranked by relevance" / "Top 500 by relevance" hint. Extracts the result limit into a named ENTITIES_TABLE_RESULT_LIMIT constant — when searching this is a hard cap (no pagination), so the best matches by relevance are always the ones shown.
  • Entities table (entities-table.tsx): "has more rows" now also requires loadMoreRows to be set, so the load-more affordance disappears while searching.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

⚠️ Known issues

  • Semantic search and cursor pagination are mutually exclusive at the graph layer, so while a search is active results are capped at the top 500 by relevance with no "load more". The header hint communicates this.

🛡 What tests cover this?

  • No automated tests added; covered by manual testing.

❓ How to test this?

  1. Checkout the branch / view the deployment
  2. Open the Entities Visualizer, click "Add filter" → "Semantic search"
  3. Type a free-text query (e.g. describe an entity by meaning rather than exact text)
  4. Confirm results re-rank by relevance, the "Ranked by relevance" / "Top 500 by relevance" hint appears, and "load more" is disabled
  5. Confirm the filter composes with web/type/archived filters and that removing the pill (or "Clear filters") restores the normal browse

📹 Demo

Screenshare.-.2026-05-29.8_40_39.PM.mp4

@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment May 29, 2026 4:57pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
hashdotdesign-tokens Ignored Ignored Preview May 29, 2026 4:57pm
petrinaut Skipped Skipped May 29, 2026 4:57pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps > hash* Affects HASH (a `hash-*` app) area/apps type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

1 participant