Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

LSHRS

CI Publish to PyPI PyPI version Python MIT License Ruff

Redis-backed locality-sensitive hashing toolkit that stores bucket membership in Redis while keeping the heavy vector payloads in your primary datastore.

logo

Table of Contents

Positioning

LSHRS adds cosine approximate-nearest-neighbor (ANN) search on top of the datastore you already run. Redis holds only a compact bucket -> set-of-indices index — typically much smaller than the vectors it indexes, with the gap widening as embedding dimensionality grows. The vectors themselves stay external in your system of record (PostgreSQL/pgvector, Parquet, an object store, anything) and are fetched on demand, only when you opt into cosine reranking via vector_fetch_fn.

See docs/positioning.md for the full comparison (LSHRS vs datasketch vs RediSearch HNSW vs pgvector vs FAISS) and when not to use LSHRS.

How It Works

LSHRS runs the full LSH workflow: hash vectors into banded random-projection signatures, store only bucket membership in Redis for low-latency candidate enumeration, then optionally rerank candidates by cosine similarity using vectors fetched from your system of record. It auto-selects bands/rows, pipelines Redis operations, and exposes hooks for streaming ingestion, persistence, and maintenance.

Concern Component
Hashing LSHHasher — banded random-projection signatures
Storage RedisStorage — bucket membership via Redis sets + pipelines
Ingestion LSHRS.create_signatures() — streams from PostgreSQL or Parquet
Reranking top_k_cosine() — cosine similarity for candidates
Configuration get_optimal_config() — bands/rows for a target threshold

Installation

pip install lshrs              # core
pip install 'lshrs[postgres]'  # + PostgreSQL streaming (psycopg)
pip install 'lshrs[parquet]'   # + Parquet ingestion (pyarrow)

From source:

git clone https://github.com/mxngjxa/lshrs.git
cd lshrs
uv sync --dev

Quick Start

import numpy as np
from lshrs import LSHRS

def fetch_vectors(indices: list[int]) -> np.ndarray:
    # Replace with your vector store retrieval (PostgreSQL, disk, object store, etc.)
    embeddings = np.load("vectors.npy")
    return embeddings[indices]

lsh = LSHRS(
    dim=768,
    num_perm=256,
    redis_host="localhost",
    redis_prefix="demo",
    vector_fetch_fn=fetch_vectors,
)

# Stream index construction from PostgreSQL
lsh.create_signatures(
    format="postgres",
    dsn="postgresql://user:pass@localhost/db",
    table="documents",
    index_column="doc_id",
    vector_column="embedding",
)

# Insert an ad-hoc document
lsh.ingest(42, np.random.randn(768).astype(np.float32))

# Retrieve candidates
query = np.random.randn(768).astype(np.float32)
top10 = lsh.get_top_k(query, topk=10)         # fast collision lookup -> List[int]
reranked = lsh.get_above_p(query, p=0.2)      # cosine-reranked -> List[(index, score)]

Ingestion

Querying

LSHRS.query() offers two retrieval modes:

Mode When Result
Top-k (top_p=None) Latency-critical, coarse candidates List[int] ordered by band collisions
Top-p (top_p=0.0–1.0) Precision-sensitive, rerank by cosine List[Tuple[int, float]] of (index, similarity)

Convenience wrappers: get_top_k() and get_above_p().

Persistence & Lifecycle

Operation Reference
Inspect runtime config / Redis namespace LSHRS.stats()
Clear all buckets for the prefix (irreversible) LSHRS.clear()
Hard-delete specific indices LSHRS.delete()
Save / restore projection matrices save_to_disk() / load_from_disk()

Because LSHRS stores only bucket -> set-of-indices membership, LSHRS.delete() makes per-id removal cheap and exact — an id is dropped from its bands with no rebuild or compaction, which suits GDPR / right-to-be-forgotten workflows. See docs/positioning.md for details.

API Surface

Area Primary Entry Point
Bulk streaming ingestion LSHRS.create_signatures()
Batch / single ingestion LSHRS.index() / LSHRS.ingest()
Search with optional reranking LSHRS.query()
Hash persistence save_to_disk() / load_from_disk()
Redis maintenance RedisStorage.clear() / RedisStorage.remove_indices()
Probability utilities compute_collision_probability() / compute_false_rates()

Benchmarks

A reproducible benchmark harness lives in benchmarks/. It generates synthetic random unit vectors and measures index build throughput, top-k / top-p query latency (p50/p95), the Redis footprint ratio (raw N x dim x 4 bytes vs the bucket index — the ratio grows with dim), and delete latency.

# Runs anywhere via in-memory fakeredis (functional timings, estimated footprint)
uv run python benchmarks/run_benchmark.py --n 5000 --dim 256 --num-perm 128

# Use a real Redis server for measured memory (MEMORY USAGE / INFO memory)
uv run python benchmarks/run_benchmark.py --real-redis --redis-host localhost

Results print as a markdown table and are written to benchmarks/RESULTS_TEMPLATE.md. See benchmarks/README.md for full details. All numbers are machine-dependent.

Development & Testing

git clone https://github.com/mxngjxa/lshrs.git
cd lshrs
uv sync --dev
uv run pytest                  # tests
uv run ruff check .            # lint
uv run ruff format --check .   # format check

License

Licensed under the terms of LICENSE.

Metadata

Release files for lshrs 0.2.0b1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for lshrs 0.2.0b1
File Size Uploaded
lshrs-0.2.0b1.tar.gz 152.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for lshrs 0.2.0b1
File Interpreter ABI Platform
lshrs-0.2.0b1-py3-none-any.whl Python 3 none any Details

Total release size: 205.3 kB

Release files / lshrs-0.2.0b1.tar.gz

Download URL lshrs-0.2.0b1.tar.gz
Size 152.8 kB
Tags Source
SHA-256 checksum
How to use checksums
60791db40f7d035f21f243069ca2e60a4269d3830274ce3ad7e6b3c8ee8a03ae
BLAKE2b-256 checksum
How to use checksums
1b036d8129e8925f30a337c91b3ded7d587b1ac48d0aaad96b26ed05c298754c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / lshrs-0.2.0b1-py3-none-any.whl

Download URL lshrs-0.2.0b1-py3-none-any.whl
Size 52.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
838063bf293659465ecaa0cf8dd0ac9e35d92ca7c526472e1b4810c5df8d0999
BLAKE2b-256 checksum
How to use checksums
8a554bb5133679b635fc7e4322d9ad75f0329e9efc349a2d22d3153842006988
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page