This release is a pre-release and may not be stable for production use.
Qenlo Python SDK
Type-safe Python bindings for Qenlo — the embedded, durable vector database written in Rust.
Qenlo provides exact filtered cosine vector search with atomic commits, write-ahead logging (WAL), portable .qn snapshot files, and zero external database services. Every search returns an execution report containing routing decisions, memory allocations, and hardware execution telemetry.
Installation
pip install qenlo
Pre-built binary wheels bundle the native Rust engine for:
- Linux (
x86_64,aarch64) - macOS (
Apple Silicon arm64,Intel x86_64) - Windows (
x86_64)
For source checkouts or development builds, set QENLO_LIBRARY_PATH to point to your compiled qenlo_ffi.dll, libqenlo_ffi.so, or libqenlo_ffi.dylib.
Quickstart
In-Memory Collection
from qenlo import Collection, Filter, Record
# Create an in-memory collection with 3-dimensional vectors
with Collection.memory(dimension=3) as db:
# Insert records
db.add(Record(id=1, user_id=42, timestamp=100, vector=(1.0, 0.0, 0.0)))
db.add(Record(id=2, user_id=42, timestamp=200, vector=(0.0, 1.0, 0.0)))
db.add(Record(id=3, user_id=99, timestamp=150, vector=(0.7, 0.7, 0.0)))
# Search with combined user and timestamp filters
response = db.search(
query=(1.0, 0.0, 0.0),
filter=Filter(user_id=42, timestamp_lower=50, timestamp_upper=150),
k=5,
)
for hit in response.results:
print(f"ID: {hit.id}, Cosine Distance: {hit.distance:.4f}")
# Inspect hardware and routing telemetry
report = response.report
print(f"Backend: {report.actual_backend}, Algorithm: {report.algorithm}")
print(f"Total Duration: {report.total_duration_ns} ns")
Durable Storage & Restarts
Qenlo collections can be persisted to disk with crash-safe write-ahead logging (WAL) and atomic compaction:
from qenlo import Collection, Record, Filter
path = "./my_collection.qenlo"
# 1. Create a new durable collection directory
with Collection.create(path, dimension=128) as db:
db.add(Record(id=1, user_id=7, timestamp=10, vector=my_vector))
db.flush() # Compact and ensure full disk sync
# 2. Reopen across application restarts
with Collection.open(path, dimension=128) as db:
response = db.search(query=my_query, filter=Filter(user_id=7), k=10)
print(f"Found {len(response.results)} matches")
Portable .qn Interchange Files
Export and import standalone, checksummed, immutable .qn snapshots:
# Export an existing collection to a .qn file
db.export_qn("snapshots/v1.qn")
# Import from a .qn file into a fast in-memory collection
with Collection.import_qn("snapshots/v1.qn", dimension=128) as snapshot_db:
stats = snapshot_db.stats()
print(f"Loaded {stats.live_rows} rows from generation {stats.generation}")
Batch Operations
Qenlo supports high-throughput atomic batch mutations:
records = [
Record(id=10, user_id=1, timestamp=1000, vector=(0.1, 0.2, 0.3)),
Record(id=11, user_id=1, timestamp=1001, vector=(0.4, 0.5, 0.6)),
Record(id=12, user_id=2, timestamp=1002, vector=(0.7, 0.8, 0.9)),
]
# Insert all atomically (all-or-nothing validation)
db.add_batch(records)
# Delete multiple records by ID
db.delete_batch([10, 11])
Data Model & Types
Record
id:int(unsigned 64-bit integer, unique and non-reusable)user_id:int(unsigned 64-bit integer)timestamp:int(signed 64-bit integer)vector:Sequence[float](normalized FP32 components)
Filter
user_id:Optional[int](exact equality match)timestamp_lower:Optional[int](inclusive lower bound)timestamp_upper:Optional[int](exclusive upper bound)
ExecutionReport
operation_id:int— Unique monotonically increasing query IDrequested_backend:str—Cpu,GpuPredicate, orAutomaticactual_backend:str— Hardware engine that executed the searchalgorithm:str— Search algorithm (Exact,IvfFlat, etc.)filter_execution:str— Filter strategy evaluatedindex_generation:int— Generation watermark observedtotal_duration_ns:int— Total wall-clock time in nanosecondslock_wait_ns:int— Time spent acquiring read lockseligible_rows:Optional[int]— Number of live rows passing metadata filtersupload_bytes:Optional[int]— Host-to-device bytes transferredreadback_bytes:Optional[int]— Device-to-host bytes read back
Error Handling
All native and validation failures raise QenloError or standard Python exceptions (ValueError):
from qenlo import Collection, QenloError, Record
try:
with Collection.memory(3) as db:
db.add(Record(1, 1, 0, (1.0, 0.0, 0.0)))
# Duplicate IDs are strictly rejected
db.add(Record(1, 1, 0, (0.0, 1.0, 0.0)))
except QenloError as e:
print(f"Operation rejected: {e}")
Anonymous Telemetry Notice
Qenlo collects anonymous installation, execution, and hardware environment telemetry (OS platform, CPU architecture, SDK version, and search duration metrics) transmitted securely to https://api.gobitsnbytes.org/qenlo/telemetry. This telemetry is strictly anonymous, privacy-preserving, and mandatory across all SDK installations (there is no opt-out) in order to monitor stability, diagnose GPU driver regressions, and optimize embedded vector routing algorithms.
License
Dual-licensed under MIT or Apache-2.0 at your option.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qenlo-0.1.0a1-py3-none-win_amd64.whl.
File metadata
- Download URL: qenlo-0.1.0a1-py3-none-win_amd64.whl
- Upload date:
- Size: 267.4 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5fc8e899abfa93243244b48ae93ee69286cef4c6d9d3b16d55fe0d6ff84d64f
|
|
| MD5 |
5e66fa302550c3f751ae4b41f4b2bcfc
|
|
| BLAKE2b-256 |
d6c5b74495d2af5e1824b4abe0d704e87a3948517a259f1760df8b88303831c9
|
File details
Details for the file qenlo-0.1.0a1-py3-none-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: qenlo-0.1.0a1-py3-none-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 396.8 kB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37d736cab1a618448a4f0e5f8cb64629d4273581dc5602f66fa7c21f62949203
|
|
| MD5 |
ba80f908d76f6e59d08aa37b606608ed
|
|
| BLAKE2b-256 |
eae5620bd243f2da784d1178243fc1ec631221bcf51b5550c9681ef98fa95317
|
File details
Details for the file qenlo-0.1.0a1-py3-none-macosx_14_0_arm64.whl.
File metadata
- Download URL: qenlo-0.1.0a1-py3-none-macosx_14_0_arm64.whl
- Upload date:
- Size: 350.3 kB
- Tags: Python 3, macOS 14.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
478d04d158335e1a74998115acf4936db0cd5488a7f9abb2e0eaec4c817f7da1
|
|
| MD5 |
83c7fae8ed324ee59cf7805bd2b6a3fa
|
|
| BLAKE2b-256 |
87a1d781fad54e050162b584f7c8e05b86a2af8ddbdc37d8775aa50017c2075f
|