kv-search
Keyword, vector, and semantic hybrid search library with a pluggable backend model.
What it does
kv-search provides a SearchEngine that combines three complementary search strategies over a corpus of documents (identified by path strings):
- Keyword search — exact/BM25-style matching via a
KeywordSearchBackend - Vector search — embedding similarity via a
VectorSearchBackend, optionally constrained to an allowlist of paths from prior keyword results - Semantic search — LLM-assisted reranking/reasoning via a
SemanticSearchBackend, which receives all configured backends and an LLM callable to do whatever hybrid logic it needs
Backends are optional and pluggable — pass only what you have. The engine raises RuntimeError if you call a search method without a configured backend.
Each search operation runs against a SearchSession, which accumulates and deduplicates hits across calls. When keyword results exist in a session, vector search automatically narrows its scope to those paths (and tightens the minimum score threshold).
Installation
pip install kv-search # core only
pip install "kv-search[elasticsearch]" # with Elasticsearch keyword backend
Usage
import asyncio
from kv_search import SearchEngine, ElasticsearchKeywordBackend
keyword_backend = ElasticsearchKeywordBackend(
hosts="http://localhost:9200",
index="my-docs",
)
engine = SearchEngine(keyword_backend=keyword_backend)
session = engine.new_session()
hits = asyncio.run(engine.keyword_search(session, ["transformer attention"]))
# hits: list[SearchHit] with .path and .score
Hybrid keyword + vector
from kv_search import SearchEngine
engine = SearchEngine(
keyword_backend=my_keyword_backend,
vector_backend=my_vector_backend,
)
session = engine.new_session()
# keyword results populate the session allowlist
await engine.keyword_search(session, ["attention mechanism"])
# vector search is automatically scoped to those paths
hits = await engine.vector_search(session, "how does self-attention work?")
Semantic search with an LLM
engine = SearchEngine(
keyword_backend=my_keyword_backend,
vector_backend=my_vector_backend,
semantic_backend=my_semantic_backend,
llm=my_llm_fn, # async (messages, *, system) -> str
)
session = engine.new_session()
results = await engine.semantic_search(session, "explain positional encoding")
# results: list[SemanticResult] with .path, .score, .reasoning
Implementing custom backends
Subclass the relevant ABC from kv_search:
from kv_search import KeywordSearchBackend, SearchHit
class MyKeywordBackend(KeywordSearchBackend):
async def keyword_search(self, queries: list[str]) -> list[SearchHit]:
...
Same pattern for VectorSearchBackend and SemanticSearchBackend. The LLMCompletionFn is a Protocol — any async callable with the right signature works.
Requirements
Python 3.11–3.14. The elasticsearch extra requires pydantic >= 2.12.5.
Metadata
Release files for kv-search 0.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| kv_search-0.3.tar.gz | 30.2 kB | With provenance | Details for kv_search-0.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| kv_search-0.3-py3-none-any.whl | Python 3 | none | any | Details for kv_search-0.3-py3-none-any.whl |
Total release size: 42.6 kB
Release files / kv_search-0.3.tar.gz
| Download URL | kv_search-0.3.tar.gz |
|---|---|
| Size | 30.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
216651733fb06c2839ad32f981be0334e9a8ba2006b32acc612f3ed2d90b2452
|
|
BLAKE2b-256 checksum How to use checksums |
d822e8edb4623182c37ab30e80aceb6755159d4839af9e28d02158e5140586ff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 7, 2026.
Transparency logRelease files / kv_search-0.3-py3-none-any.whl
| Download URL | kv_search-0.3-py3-none-any.whl |
|---|---|
| Size | 12.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a250c2b365495461b179099b5dad9fb6e01f64cab1b832efb3ccb2b2d607b388
|
|
BLAKE2b-256 checksum How to use checksums |
870d538803d73e3bee8bb3aa900537160a6864c73b5e1ada43d816818d9198b3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 7, 2026.
Transparency logSecurity for kv-search 0.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for kv_search-0.3.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 7, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.