Skip to content

Feat: Add semantic search experiment to AI plugin - #891

Open
priyanshuhaldar007 wants to merge 2 commits into
WordPress:developfrom
priyanshuhaldar007:feat-844/semantic-search-implementation
Open

Feat: Add semantic search experiment to AI plugin#891
priyanshuhaldar007 wants to merge 2 commits into
WordPress:developfrom
priyanshuhaldar007:feat-844/semantic-search-implementation

Conversation

@priyanshuhaldar007

@priyanshuhaldar007 priyanshuhaldar007 commented Jul 23, 2026

Copy link
Copy Markdown

What?

Closes #844

Adds a new Semantic Search experiment to the AI plugin, extending semantic/vector search from the frontend into wp-admin. This covers two surfaces:

  • Posts list search — a "Search semantically" option on edit.php list tables that re-ranks results by meaning instead of exact keyword matching, with graceful fallback to default WordPress search when no provider is configured or nothing is indexed yet.
  • Command palette (Cmd/Ctrl+K) — the block editor's command palette gains live semantic search results as the author types, letting them jump directly to a post they're thinking of.

Also adds a Tools → Semantic Search Index admin page for configuring an embedding provider, testing connectivity(for Google Gemini), and batch-indexing existing content.

Why?

The built-in admin search only matches exact words. If an editor remembers "that post about pricing changes" but the post is titled "Updates to our plans," searching "pricing" in the posts list returns nothing. This friction compounds daily for anyone actively managing a large site, and content managers hit it more often than any single frontend visitor hits search — the same problem #683 already solves for frontend search but not for wp-admin.

This PR is intended as a follow-on to #683, not a parallel implementation. It reuses the same conceptual approach (embed content, compare via cosine similarity) but is currently backed by a temporary, self-contained implementation since the two foundational pieces this issue is blocked on are not yet merged:

  • php-ai-client#244 (embedding generation API) — still open, changes requested
  • ai#683 (native vector index) — still in draft

Rather than wait, this PR ships a fully working version now, with the two upstream-dependent pieces isolated behind clear TODO markers so migration is a small, contained change once each lands.

How?

Implemented as a new Semantic_Search experiment following the existing Feature/Experiment pattern used by Comment_Moderation, Summarisation, and Abilities_Explorer.

New classes (includes/Experiments/Semantic_Search/):

  • Semantic_Search.php — experiment entry point: metadata, settings registration, hook wiring
  • Embedding_Api.php — HTTP wrapper supporting OpenAI, Jina AI, Ollama, and Google Gemini embedding endpoints (temporary stand-in until php-ai-client#244 lands)
  • Embedding_Store.php — reads/writes embeddings as post meta (_wpai_semantic_search_embedding) (temporary stand-in until ai#683's native VECTOR column lands)
  • Indexer.php — orchestrates the API → store pipeline, batched at 5 posts per request to stay within PHP's execution timeout
  • Vector_Search.php — computes cosine similarity in PHP against all indexed posts; filters by a per-provider score threshold (model-dependent, user-configurable — higher-dimensional models produce lower absolute similarity scores for equivalent semantic pairs, so a single hardcoded threshold is wrong across providers)
  • List_Table_Integration.php — hooks pre_get_posts on edit.php; re-ranks results via post__in + orderby: post__in when semantic search is available and returns results, otherwise leaves the query untouched
  • REST_Controller.php — four routes under /ai/v1/semantic-search/... for search, indexing, index status, and connection testing
  • Index_Page.php — admin UI at Tools → Semantic Search Index

New assets:

  • build-scripts/experiments/semantic-search.js — registers a Gutenberg command loader via registerCommandLoader, debounced on the palette's search string

Modified:

  • Experiments.php — registers Semantic_Search::class in EXPERIMENT_CLASSES

Design decisions worth flagging for review:

  • All registered settings fields include show_in_rest: true so the React settings page at Settings → AI can read/write them via the core /wp/v2/settings route (matches the Comment_Moderation pattern).
  • The command palette embeds the search term directly into each command's name field, since cmdk (the library backing Gutenberg's palette) filters items on name + label, and whether keywords is forwarded to Command.Item varies by Gutenberg version. This is a defensive, version-agnostic fix; keywords is also set as a secondary safeguard.
  • Command icon is explicitly null rather than a string — Gutenberg expects null or a React element; a plain string silently fails to render with no visible error.
  • No echo/output is used inside REST callbacks or any code path they invoke, since any stray output corrupts the JSON body returned to apiFetch.
  • Both classes with upstream dependencies (Embedding_Api.php, Embedding_Store.php + Vector_Search.php) are marked with inline TODO comments describing the exact swap to php-ai-client#244's embedding API and ai#683's native VECTOR INDEX query, respectively. No other class in this PR should need to change across either migration.

Use of AI Tools

AI assistance: Yes
Tool(s): Claude (Anthropic)
Model(s): Claude Sonnet 5
Used for: Architecture planning, initial implementation, score threshold calibration across embedding providers, and documentation. All code was reviewed, tested against a live WordPress install, and adjusted by me based on real test results before inclusion in this PR.

Testing Instructions

  1. Activate the AI plugin and enable the Semantic Search experiment under Settings → AI.
  2. Configure an embedding provider (OpenAI, Jina AI, Ollama, or Google Gemini) and, if required, an API key.
  3. Go to Tools → Semantic Search Index, click Test Connection to confirm the provider responds with a model name and dimension count.
  4. Click Index All Posts and confirm the progress counter reaches "Done" with no errors.
  5. Posts list test: go to Posts, check "Search semantically," and search for a concept that's present in a post's content but not its title/keywords (e.g. search "pricing" against a post titled "Updates to our plans" that discusses subscription costs). Confirm the post is returned.
  6. Command palette test: open any post in the block editor, press Cmd/Ctrl+K, and type a concept-based query. Confirm semantically related posts appear as clickable results and navigate correctly on click.
  7. Fallback test: clear the API key in Settings and repeat steps 5–6. Confirm both surfaces fall back gracefully to default WordPress search behaviour with no errors or blank screens.

Screenshots or screencast

Before After
Screenshot 2026-07-23 at 9 54 45 PM Screenshot 2026-07-23 at 9 54 52 PM

Changelog Entry

Added - Semantic search experiment for wp-admin: posts list search and command palette results ranked by content meaning rather than exact keyword match, with configurable embedding provider support (OpenAI, Jina AI, Ollama, Google Gemini) and a Tools admin page for indexing.

Open WordPress Playground Preview

@priyanshuhaldar007
priyanshuhaldar007 requested a review from a team July 23, 2026 16:28
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @priyanshuhaldar007.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: priyanshuhaldar007.

Co-authored-by: dkotter <dkotter@git.wordpress.org>
Co-authored-by: jeffpaul <jeffpaul@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 1.45719% with 541 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.49%. Comparing base (5599e9d) to head (4c2d607).

Files with missing lines Patch % Lines
...ncludes/Experiments/Semantic_Search/Index_Page.php 0.00% 104 Missing ⚠️
...udes/Experiments/Semantic_Search/Embedding_Api.php 0.00% 99 Missing ⚠️
...es/Experiments/Semantic_Search/REST_Controller.php 0.00% 90 Missing ⚠️
...es/Experiments/Semantic_Search/Semantic_Search.php 8.42% 87 Missing ⚠️
...udes/Experiments/Semantic_Search/Vector_Search.php 0.00% 51 Missing ⚠️
...es/Experiments/Semantic_Search/Embedding_Store.php 0.00% 42 Missing ⚠️
...riments/Semantic_Search/List_Table_Integration.php 0.00% 41 Missing ⚠️
includes/Experiments/Semantic_Search/Indexer.php 0.00% 27 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##             develop     #891      +/-   ##
=============================================
- Coverage      80.43%   76.49%   -3.95%     
- Complexity      2565     2662      +97     
=============================================
  Files            110      118       +8     
  Lines          10448    10997     +549     
=============================================
+ Hits            8404     8412       +8     
- Misses          2044     2585     +541     
Flag Coverage Δ
unit 76.49% <1.45%> (-3.95%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dkotter dkotter 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.

So we don't want to have to maintain provider integrations within this plugin. Those integrations should be done upstream in their individual provider plugins if at all possible.

Also note we have #892 open now which brings over the embedding work from the PHP AI Client so we can start taking advantage of that prior to that being released into WordPress 7.2 (and allows us to support older versions of WordPress even after that point). So ideally this PR is refactored to remove any provider integration and any embedding generation should filter through the PHP AI Client changes in that PR

@jeffpaul jeffpaul added this to the Future Release milestone Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New Experiment: Semantic search in wp admin

3 participants