Vector Search with Whoosh‑NG
This example shows how to enable semantic/vector search using the optional vector extra. We index document embeddings and perform k-nearest neighbour (k-NN) search.
1. Install Optional Dependencies
pip install "whoosh-ng[vector]" numpy
2. Schema with a Vector Field
from whoosh.fields import Schema, TEXT, ID, VECTOR
from whoosh.vector import VectorField
schema = Schema(
doc_id=ID(stored=True, unique=True),
title=TEXT(stored=True),
content=TEXT,
embedding=VECTOR(stored=True, dim=128), # 128-dimensional embedding
)
3. Indexing Vectors
import numpy as np
from whoosh import index
shutil.rmtree("vector_index", ignore_errors=True)
ix = index.create_in("vector_index", schema)
# Simulate embeddings (in practice, use a model like SentenceTransformer)
documents = [
{"doc_id": "doc1", "title": "Python Basics", "content": "Learn Python programming fundamentals."},
{"doc_id": "doc2", "title": "Advanced Python", "content": "Deep dive into Python decorators and metaclasses."},
{"doc_id": "doc3", "title": "Data Science", "content": "Pandas and NumPy for data analysis."},
]
# Generate random embeddings for demo
np.random.seed(42)
embeddings = {d["doc_id"]: np.random.rand(128).astype(np.float32) for d in documents}
with ix.writer() as w:
for doc in documents:
w.add_document(
doc_id=doc["doc_id"],
title=doc["title"],
content=doc["content"],
embedding=embeddings[doc["doc_id"]].tobytes(),
)
w.commit()
4. Vector Search with NumpyProvider
from whoosh_modern.vector import VectorField
from whoosh_modern.vector.numpy_provider import NumpyProvider
from whoosh_modern.vector.plugin import VectorPlugin
from whoosh.plugins.manager import PluginManager
# Register the vector plugin
VectorPlugin().register(PluginManager())
# Create provider and add vectors
provider = NumpyProvider()
for doc_id, vec in embeddings.items():
provider.add([(doc_id, vec.tolist())])
# Search: find 2 most similar docs to a query vector
query_vec = embeddings["doc1"] # use doc1's embedding as query
hits = provider.search(query_vec, k=2)
for hit in hits:
print(f"doc_id={hit.doc_id}, score={hit.score:.3f}")
5. Using VectorField for Serialization
from whoosh.vector import VectorField
vf = VectorField(dimension=128, name="embedding")
# Convert list to bytes for storage
values = [0.1, 0.2, 0.3, 0.4] + [0.0] * 124 # 128 values
raw = vf.vector_to_bytes(values)
# Restore from bytes
restored = vf.bytes_to_vector(raw)
print(restored == tuple(values)) # True
6. Key Takeaways
- Install with
pip install whoosh-ng[vector]to getwhoosh_modern.vector. VECTORfield stores raw bytes; useVectorFieldto convert to/from Python lists.NumpyProviderimplements cosine similarity via dot product.- Register the plugin via
VectorPlugin().register(manager)or usePluginManager.load_plugins(). - Use
filter_idsinprovider.search()to restrict to a subset of documents.