Feat: Add semantic search experiment to AI plugin - #891
Feat: Add semantic search experiment to AI plugin#891priyanshuhaldar007 wants to merge 2 commits into
Conversation
|
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 Unlinked AccountsThe 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. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Codecov Report❌ Patch coverage is 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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
dkotter
left a comment
There was a problem hiding this comment.
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
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:
edit.phplist 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.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 requestedai#683(native vector index) — still in draftRather than wait, this PR ships a fully working version now, with the two upstream-dependent pieces isolated behind clear
TODOmarkers so migration is a small, contained change once each lands.How?
Implemented as a new
Semantic_Searchexperiment following the existing Feature/Experiment pattern used byComment_Moderation,Summarisation, andAbilities_Explorer.New classes (
includes/Experiments/Semantic_Search/):Semantic_Search.php— experiment entry point: metadata, settings registration, hook wiringEmbedding_Api.php— HTTP wrapper supporting OpenAI, Jina AI, Ollama, and Google Gemini embedding endpoints (temporary stand-in untilphp-ai-client#244lands)Embedding_Store.php— reads/writes embeddings as post meta (_wpai_semantic_search_embedding) (temporary stand-in untilai#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 timeoutVector_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— hookspre_get_postsonedit.php; re-ranks results viapost__in+orderby: post__inwhen semantic search is available and returns results, otherwise leaves the query untouchedREST_Controller.php— four routes under/ai/v1/semantic-search/...for search, indexing, index status, and connection testingIndex_Page.php— admin UI at Tools → Semantic Search IndexNew assets:
build-scripts/experiments/semantic-search.js— registers a Gutenberg command loader viaregisterCommandLoader, debounced on the palette's search stringModified:
Experiments.php— registersSemantic_Search::classinEXPERIMENT_CLASSESDesign decisions worth flagging for review:
show_in_rest: trueso the React settings page at Settings → AI can read/write them via the core/wp/v2/settingsroute (matches theComment_Moderationpattern).namefield, since cmdk (the library backing Gutenberg's palette) filters items onname + label, and whetherkeywordsis forwarded toCommand.Itemvaries by Gutenberg version. This is a defensive, version-agnostic fix;keywordsis also set as a secondary safeguard.iconis explicitlynullrather than a string — Gutenberg expectsnullor a React element; a plain string silently fails to render with no visible error.echo/output is used inside REST callbacks or any code path they invoke, since any stray output corrupts the JSON body returned toapiFetch.Embedding_Api.php,Embedding_Store.php+Vector_Search.php) are marked with inlineTODOcomments describing the exact swap tophp-ai-client#244's embedding API andai#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
Screenshots or screencast
Changelog Entry