WP Manifestindependent plugin directory
manifest / utilities / wp-vector-search

WP Vector Search

WordPress plugin that enhances search with vector similarity and BM25 hybrid search, powered by php-vector-store

by Mauricio Perera · github.com/mauricioperera/wp-vector-search · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/mauricioperera/wp-vector-search/archive/refs/heads/master.zip

WordPress plugin that enhances the native search with vector similarity and BM25 hybrid search, powered by php-vector-store.

How it works

  1. BM25 text indexing happens automatically when posts are published/updated
  2. Embeddings are pushed externally via REST API (you bring your own embedding pipeline)
  3. Search combines both signals using Reciprocal Rank Fusion (RRF) or weighted scoring
WordPress Content → BM25 Index (automatic)
                  → Vector Store (via REST API) ← Your embedding pipeline
                                                   (OpenAI, Ollama, etc.)

User searches → Hybrid fusion (BM25 + Vector) → Reranked results

Features

  • Zero-dependency vector search — pure PHP, no extensions needed
  • Hybrid search — combines semantic (vector) + keyword (BM25) relevance
  • Native WP integration — hooks into pre_get_posts to enhance the default search
  • Shortcode[vector_search] for a dedicated semantic search widget
  • REST API — push embeddings from any external pipeline
  • Int8 quantization — 4x storage reduction with negligible accuracy loss
  • Admin dashboard — statistics, settings, one-click BM25 reindex

Requirements

  • PHP 8.1+
  • WordPress 6.0+
  • Composer

Installation

cd wp-content/plugins
git clone https://github.com/MauricioPerera/wp-vector-search.git
cd wp-vector-search
composer install

Activate from Plugins in wp-admin.

Configuration

Go to Settings → Vector Search in wp-admin:

Setting Default Description
Vector Dimensions 384 Must match your embedding model
Quantized Store On Int8 quantization (4x smaller)
Hybrid Mode RRF rrf or weighted
Vector Weight 0.5 Weight for vector similarity (weighted mode)
Text Weight 0.5 Weight for BM25 text score (weighted mode)
Enhance native search On Hook into WordPress search

REST API

Push Embeddings

# Single embedding
curl -X POST https://yoursite.com/wp-json/wp-vector-search/v1/embeddings \
  -H "X-WPVS-API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"post_id": 123, "vector": [0.1, 0.2, ...]}'

# Batch
curl -X POST https://yoursite.com/wp-json/wp-vector-search/v1/embeddings/batch \
  -H "X-WPVS-API-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"items": [{"post_id": 123, "vector": [...]}, {"post_id": 456, "vector": [...]}]}'

Search

# Text-only (BM25)
curl "https://yoursite.com/wp-json/wp-vector-search/v1/search?text=machine+learning&limit=10"

# Hybrid (vector + text)
curl -X GET "https://yoursite.com/wp-json/wp-vector-search/v1/search" \
  -d '{"text": "machine learning", "vector": [0.1, 0.2, ...], "limit": 10}'

Other Endpoints

DELETE /wp-json/wp-vector-search/v1/embeddings/{post_id}  — Remove embedding
GET    /wp-json/wp-vector-search/v1/stats                 — Index statistics
POST   /wp-json/wp-vector-search/v1/reindex               — Trigger BM25 reindex

Shortcode

[vector_search placeholder="Search our knowledge base..." limit="10"]

Renders a search form with live results via AJAX. Works with BM25-only if no embeddings are available.

Hooks & Filters

// Customize which post types are indexed
add_filter( 'wpvs_indexable_post_types', function ( $types ) {
    $types[] = 'product'; // Add WooCommerce products
    return $types;
} );

// Modify text before BM25 indexing
add_filter( 'wpvs_index_text', function ( $text, $post_id ) {
    // Add custom fields to searchable text
    $text .= ' ' . get_post_meta( $post_id, 'custom_field', true );
    return $text;
}, 10, 2 );

// React to search events
add_action( 'wpvs_search_performed', function ( $query, $results ) {
    // Log searches, analytics, etc.
}, 10, 2 );

// React to indexing events
add_action( 'wpvs_post_indexed', function ( $post_id, $vector ) {
    // Trigger re-embedding, sync, etc.
}, 10, 2 );

Example: External Embedding Pipeline

With OpenAI (Python)

import openai, requests

# Generate embedding
response = openai.embeddings.create(
    model="text-embedding-3-small",
    input="Your post content here"
)
vector = response.data[0].embedding

# Push to WordPress
requests.post(
    "https://yoursite.com/wp-json/wp-vector-search/v1/embeddings",
    headers={"X-WPVS-API-Key": "YOUR_KEY"},
    json={"post_id": 123, "vector": vector}
)

With n8n

  1. Trigger: WordPress webhook on post publish
  2. HTTP Request: Fetch post content
  3. OpenAI node: Generate embedding
  4. HTTP Request: POST to /wp-json/wp-vector-search/v1/embeddings

Architecture

wp-vector-search/
├── wp-vector-search.php      # Plugin bootstrap
├── includes/
│   ├── class-plugin.php       # Singleton, initializes all components
│   ├── class-indexer.php      # BM25 text indexing on save_post
│   ├── class-search.php       # pre_get_posts hook for native search
│   ├── class-rest-api.php     # REST API endpoints
│   ├── class-admin.php        # Settings page & dashboard
│   └── class-shortcode.php    # [vector_search] shortcode
├── assets/
│   ├── css/admin.css          # Admin styles
│   └── js/search-block.js     # Frontend search widget
└── templates/
    └── search-results.php     # Overridable result template

License

GPL-2.0-or-later