class Mood(IntEnum) Values
PARKED | 1 | Idle workers sleep; the next call pays a wake-up. |
|---|---|---|
SPINNING | 2 | Idle workers stay hot, trading power for the next call's latency. |
An executor owns host threads or device streams; an index owns entries. Keeping them apart is what lets one pool serve several indexes, and what makes the cost of spawning visible at the line that spawns it rather than hidden in a constructor. Its residency must match that of every index it drives.
One factory per residency, since each spawns something different and takes different arguments:
pool = usearch.Executor.for_ram(threads=8) # 0 derives from the hardware
numa_pool = usearch.Executor.for_ram(threads=8, memory_domains=[0, 1])
device_pool = usearch.Executor.for_vram(devices=[0, 1]) # One stream per CUDA ordinal
disk_pool = usearch.Executor.for_nvme(threads=8, paths=["/mnt/nvme0", "/mnt/nvme1"])
shared_pool = usearch.Executor.on_pool(fu_pool_address) # Borrows a ForkUnion pool by address
pool.drain(usearch.Mood.SPINNING) # Waits, then keeps idle workers hotfor_ram creates an executor of host threads, and its memory_domains are the NUMA node IDs those threads stay local to. for_nvme opens one submission ring per worker, striping shards across the paths it is given. for_vram takes no thread count at all: one host thread drives one stream per device, so the width of that pool is the device list rather than a worker count. on_pool borrows a ForkUnion fu_pool_t another library spawned, passed as an integer address the way ctypes and cffi hand pointers over, and the pool must outlive the executor.
One call holds an executor at a time, and nothing queues: a second call finishes with Status.CONTENDED and raises ContendedError, a deferred one once awaited.
A deferred call on a caller-exclusive pool, which for_ram and for_nvme spawn for more than one thread, runs on the pool’s thread 0, so polling status alone finishes it, and its progress and predicate callbacks run on the pool’s threads under the GIL; a single thread or a VRAM executor runs it at submission. drain waits until no call holds the executor, then lets idle workers sleep with Mood.PARKED, the default, or keeps them hot with Mood.SPINNING.
Used as a context manager, an executor waits for its calls and closes on exit, after which a receiver naming it raises UninitializedError.
Calling usearch.Executor() raises a TypeError naming the factories, since what a pool spawns cannot be derived from nothing.
The index and every receiver derived from it never change after they are made, so threads share them freely.
Searches never write to the graph, so any number may overlap with insertions, and saving needs a mutation-free window.
The extension declares Py_MOD_GIL_NOT_USED, so free-threaded builds run without the interpreter lock.
Critical sections or atomics fence the few fields the binding mutates: an arena’s exports and generation, the handle a cursor or stream lends its running pull, a closed executor’s handle, a latched callback exception, a DenseTraversalStats total and an absorbed donor’s handle.
A receiver carries what every C argument struct puts before its inputs: the executor and the completion.
The index runs a verb on the calling thread, index.on(executor) answers a usearch.On whose verbs block on that executor, and index.deferred(executor) answers a usearch.DeferredOn whose verbs submit there and answer a usearch.Deferred.
The receiver’s type alone chooses the completion, so all three offer the same verbs with the same arguments, and no verb takes an executor= keyword.
In a coroutine, await a deferred call; anywhere else, wait() blocks the thread with its state detached:
import asyncio
async def nearest(pool):
here, there = usearch.Arena(), usearch.Arena(pool)
matches = index.search(queries, 10, here) # the calling thread
matches = index.on(pool).search(queries, 10, there) # blocking, holding the pool until it returns
call = index.deferred(pool).search(queries, 10, there) # a usearch.Deferred, submitted now
call.status # usearch.Status.DEFERRED until final
return await call # or: call.wait()
matches = asyncio.run(nearest(pool))await runs wait() on the running event loop’s default executor, so the thread it blocks belongs to asyncio.
A Deferred holds the outcome and every input buffer the library reads, so nothing the call reads ever moves.
It holds its arena as a blocking call does, until it is waited on or dropped: meanwhile another call naming that arena raises ContendedError, and its result views the arena like the blocking verb’s.
Dropping an unfinished one waits for its call, which is the C contract rather than binding logic.
The collector leaves a cycle through an unfinished one for a later collection, never clearing what the library still reads.
Constructors address no index yet, so no receiver offers them; the ones the C ABI lets fan out take executor=, and run on the calling thread without one.
MoodWhat an executor's idle workers do: sleep, or stay hot.class Mood(IntEnum) PARKED | 1 | Idle workers sleep; the next call pays a wake-up. |
|---|---|---|
SPINNING | 2 | Idle workers stay hot, trading power for the next call's latency. |
ExecutorThe workers a verb runs on, shared across indexes and named by on and deferred.7class Executor for_ramSpawns host worker threads for a RAM-resident index.@classmethod
def for_ram(
threads: int = 0,
*,
memory_domains: Sequence[int] | None = None,
deferred_limit: int = 0,
cpu_class: CPUClass | None = None,
) -> Executor on_poolDrives RAM-resident indexes on a thread pool the caller owns.@classmethod
def on_pool(
pool: int,
/,
*,
memory_domains: Sequence[int] | None = None,
deferred_limit: int = 0,
cpu_class: CPUClass | None = None,
) -> Executor for_vramOpens one stream per device for a VRAM-resident index.@classmethod
def for_vram(
*,
devices: Sequence[int] | None = None,
deferred_limit: int = 0,
gpu_class: GPUClass | None = None,
) -> Executor for_nvmeOpens one submission ring per worker for an NVMe-resident index.@classmethod
def for_nvme(
threads: int = 0,
*,
paths: Sequence[_PathLike] | None = None,
deferred_limit: int = 0,
nvme_class: NVMeClass | None = None,
cpu_class: CPUClass | None = None,
) -> Executor drainWaits for every call submitted before it, then sets what idle workers do.def drain(mood: Mood = ...) -> None __exit__Closes it once its calls finish, or leaves that to its last live GPU arena.def __exit__(
kind: type[BaseException] | None,
value: BaseException | None,
traceback: TracebackType | None,
/,
) -> None residencyThe Residency its calls compute in.DeferredA call a DeferredOn submitted: await it, or wait() for it; dropping it waits.4class Deferred[AnswerT] __class_getitem__Names what wait() answers, as Deferred[Matches].def __class_getitem__(item: Any, /) -> GenericAlias waitBlocks until the call is final, then answers or raises.def wait() -> AnswerT __await__Runs wait() on the running event loop's default executor, suspending the task meanwhile.def __await__() -> Generator[Any, None, AnswerT] statusStatus.DEFERRED until the call is final, then the final one.status: Status OnAn index bound to the executor its verbs block on, as index.on(executor) answers it.20class On[IndexT] __class_getitem__Names the index the receiver addresses, as On[DenseIndex].def __class_getitem__(item: Any, /) -> GenericAlias *× 2The frozen metadata and the current counters, read in one call.def describe() -> DenseIndexDescription Each counter is read once, so under concurrent insertions they may come from slightly different moments.
>>> usearch.DenseIndex.init_ram(256).describe().metadata.dimensions
256
*× 2Grows the index to host at least capacity entries, a hint, since insertions grow the index on demand.def reserve(capacity: int, /) -> None capacityint | Entries the index must accept without growing again. |
|---|
*× 2Drops every entry, keeping the capacity and the frozen geometry.def clear() -> None *× 2Inserts a batch of vectors under a batch of keys; one vector is a one-row matrix.def insert(
keys: Sequence[_KeyLike] | _Tensor,
vectors: _Tensor,
/,
*,
expansion_factor: int = 0,
dtype: Scalar | None = None,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> None Keys need not be unique: inserting one twice stores two entries, and count reports both. A batch is all-or-nothing and becomes visible at once, so a rejected batch leaves the index untouched and a concurrent search sees all of it or none.
keysSequence[_KeyLike] | _Tensor | One key per row, or an (N, 16) buffer. | |
|---|---|---|
vectors_Tensor | An (N, dimensions) matrix; only the row stride may vary. | |
expansion_factorint | Breadth of the candidates; 0 derives it. | |
dtypeScalar | None | Names the input scalar type when the buffer cannot; it must be as wide as the buffer's items. | |
progress_Progress | None | Called with (completed, total) entries. It reports and cannot stop the batch, every entry being claimed before the first report; what it raises surfaces once the batch has finished. Reports are serialized. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
>>> from array import array
>>> index = usearch.DenseIndex.init_ram(dimensions=4)
>>> index.reserve(1)
>>> index.insert([1], array('d', [0.1, 0.2, 0.3, 0.4]))
>>> len(index)
1
*× 2Re-selects the neighbors of every stored entry against the finished graph, improving edges that were chosen when the graph around them was still incomplete.def refine(
*,
expansion_factor: int = 0,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> RefineReport A build step rather than a repair: a cheap insertion pass followed by one refinement
reaches a better graph, in less total time, than one expensive insertion pass - so a
wide expansion_factor belongs here rather than in insert. Searches may run
throughout on a RAM handle but not on a VRAM one, and a caller loops until the
report's changed falls below whatever change rate they consider settled.
Stopping is safe: re-selecting edges claims no identity, so a stopped sweep still
re-links its islands, leaves the graph correct and merely less improved, and raises
CancelledError. A handler is therefore how a sweep is put under a time budget.
expansion_factorint | Breadth of the candidates; 0 derives it. | |
|---|---|---|
progress_Progress | None | Called with (completed, total) nodes; returning False ends the sweep, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
changed at zero means the graph has settled.>>> from array import array
>>> index = usearch.DenseIndex.init_ram(dimensions=4)
>>> index.reserve(1)
>>> index.insert([1], array('d', [0.1, 0.2, 0.3, 0.4]))
>>> index.refine().changed
0
*× 2Audits how much of the graph a search can reach, sweeping forward reachability from as many landmarks as one search draws.def health() -> DenseReachability Read-only.
>>> from array import array
>>> index = usearch.DenseIndex.init_ram(dimensions=4)
>>> index.reserve(1)
>>> index.insert([1], array('d', [0.1, 0.2, 0.3, 0.4]))
>>> health = index.health()
>>> health.reachable == health.audited == 1
True
*× 2Finds the wanted nearest entries for every query row; one query is a one-row matrix.def search(
queries: _Tensor,
wanted: int,
arena: Arena,
/,
*,
expansion_factor: int = 0,
traversal: Traversal = ...,
dtype: Scalar | None = None,
predicate: Callable[[Key], bool] | None = None,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> Matches Never writes to the graph, so any number of searches may overlap with insertions.
queries_Tensor | A (Q, dimensions) matrix of query rows. | |
|---|---|---|
wantedint | Upper bound on matches per query - the 'k' in 'kANN'. | |
arenaArena | Where the matches land, rewound by the call. | |
expansion_factorint | Breadth of the candidates; 0 derives it. | |
traversalTraversal | Traversal.WALK, the default, walks the graph;
Traversal.SCAN scores every entry exactly, on RAM and NVMe handles. | |
dtypeScalar | None | Names the query scalar type when the buffer cannot. | |
predicateCallable[[Key], bool] | None | Admits a Key when it returns truthy. Non-matching entries still route the traversal, so recall survives low selectivity. The callback re-enters Python, so it runs under the GIL and serializes the walk. | |
progress_Progress | None | Called with (completed, total) queries; returning
False stops the batch and raises CancelledError, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
wanted, each count
bounding its own row.>>> from array import array
>>> index = usearch.DenseIndex.init_ram(dimensions=4)
>>> index.reserve(1)
>>> query = array('d', [0.1, 0.2, 0.3, 0.4])
>>> index.insert([7], query)
>>> key, distance = index.search(query, 1, usearch.Arena())[0][0]
>>> int(key)
7
*× 2How many entries share key; zero means the index holds none.def count(key: _KeyLike, /) -> int key_KeyLike | The identity to count. |
|---|
>>> from array import array
>>> index = usearch.DenseIndex.init_ram(dimensions=2)
>>> index.reserve(2)
>>> row = array('d', [0.1, 0.2])
>>> index.insert([7], row)
>>> index.insert([7], row)
>>> index.count(7)
2
*× 2Every vector stored under key, in insertion order, and none when the key is absent.def get(
key: _KeyLike,
arena: Arena,
/,
*,
outputs_dtype: Scalar = ...,
) -> DenseVectors key_KeyLike | The identity to retrieve. | |
|---|---|---|
arenaArena | Where the rows land, rewound by the call. | |
outputs_dtypeScalar | The scalar type to export as; converted from storage. |
memoryview can format - f64, f32, f16, i8, u8. Sub-byte and mini-float kinds,
bf16 among them, leave as a (count, row_bytes) run of 'B' instead. Empty, so falsy,
when the index holds no entry under key.*× 2Approximate sparse product of a matrix against the indexed vectors - the linear algebra sibling of search, reporting every pair the traversal scored rather than only the nearest.def multiply(
rows: _Tensor,
wanted: int,
arena: Arena,
/,
*,
expansion_factor: int = 0,
dtype: Scalar | None = None,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> DenseProducts Pairs arrive in traversal order rather than sorted, and carry no duplicates. How many a walk scores is known only once it ends, so the pairs come back ragged.
rows_Tensor | An (R, dimensions) matrix of left-hand rows. | |
|---|---|---|
wantedint | Upper bound on pairs kept per row, the first ones its walk scored; 0 keeps every pair. | |
arenaArena | Where the pairs and their offsets land, rewound by the call. | |
expansion_factorint | Breadth of the candidates; 0 derives it. A wider factor widens the emitted pattern, being what the walk's breadth decides. | |
dtypeScalar | None | Names the left-hand scalar type when the buffer cannot. | |
progress_Progress | None | Called with (completed, total) rows; returning False
stops the batch and raises CancelledError, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
*× 2Softmax attention of every query row over every indexed key its walk scores, folded online as Flash Attention folds key tiles, with no top-k cut.def attend(
queries: _Tensor,
values: _Tensor,
row_of: Callable[[Key], int | None],
arena: Arena,
/,
*,
head_count: int = 1,
expansion_factor: int = 0,
score_scale: float = 0.0,
dtype: Scalar | None = None,
values_dtype: Scalar | None = None,
outputs_dtype: Scalar | None = None,
carry: _Tensor | None = None,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> DenseVectors Never writes to the graph, so a growing context may stream through this while insertions continue.
The index holds one layer's keys for one key-value head and no values: row_of names
the row of values each scored key reads, so only keys a walk scores are ever resolved.
queries_Tensor | A (Q, dimensions) matrix; row t * head_count + h is head h
of token t. | |
|---|---|---|
values_Tensor | An (N, dimensions) matrix of value rows, as wide as the keys and stored in the index's quantization, borrowed until the call is final. | |
row_ofCallable[[Key], int | None] | Called with each scored Key, answers its row of values. None, or
a row outside them, refuses the call with ShapeMismatchError, as do values of
another width or scalar type. It re-enters Python from the library's threads, so it
runs under the GIL and serializes the walk. A VRAM walk resolves values on the
device, where no Python callable runs, so a VRAM arena raises DeviceError. | |
arenaArena | Where the attended rows land, rewound by the call. | |
head_countint | The query heads sharing the index's key-value head, and with it one walk per token; it must divide Q. | |
expansion_factorint | Breadth of the candidates; 0 derives it. Wider candidates walk further, folding more of the tail. | |
score_scalefloat | The logit scale, conventionally the inverse square root of the head dimensionality; 0.0 derives it from the frozen geometry. | |
dtypeScalar | None | Names the query scalar type when the buffer cannot. | |
values_dtypeScalar | None | Names the values' scalar type when the buffer cannot. | |
outputs_dtypeScalar | None | The scalar type to write the outputs as; defaults to the queries' own. | |
carry_Tensor | None | A writable (Q, 2) buffer of float32, holding each query's largest logit and the softmax denominator taken against it. The pair recombines this branch with another over the same queries - attention sinks, a dense recent window, or a second index of one context - by partial-softmax rescaling; a maximum without its partition is a number nothing can rescale, which is why they travel as one row. | |
progress_Progress | None | Called with (completed, total) tokens; returning
False stops the batch and raises CancelledError, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
memoryview cannot format leave as a (Q, row_bytes) run of 'B'.*× 2Late-interaction scoring of multi-row queries against multi-vector documents: every query row takes its best match within a key, and those maxima sum to that key's score.def maxsim(
queries: _Tensor,
rows_per_query: int,
wanted: int,
arena: Arena,
/,
*,
expansion_factor: int = 0,
traversal: Traversal = ...,
dtype: Scalar | None = None,
predicate: Callable[[Key], bool] | None = None,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> DenseProducts A document is one key holding its token rows, which is what values_per_key above one
exists for, and the walk stays over individual tokens under a plain inner product - so
a document's vectors need no ordering and two documents need not share a vector count.
The result is sized over documents rather than over rows.
queries_Tensor | The token rows of every query laid end to end, an (Q * R, dimensions) matrix. | |
|---|---|---|
rows_per_queryint | Rows every query occupies; uniform, so ColBERT's padding applies as is. The query row count must be a whole multiple of it. | |
wantedint | Upper bound on matches per query - the 'k' over documents, not rows; 0 keeps every document the query scored. | |
arenaArena | Where the scored documents land, rewound by the call. | |
expansion_factorint | Breadth of the candidates; 0 derives it. Widening it nominates more documents, each still scored exactly. | |
traversalTraversal | Traversal.WALK, the default, nominates documents by
walking the graph; Traversal.SCAN nominates every document, on RAM and NVMe. | |
dtypeScalar | None | Names the query scalar type when the buffer cannot. | |
predicateCallable[[Key], bool] | None | Admits a Key when it returns truthy, asked before any of its vectors are scored, so a rejected document never scores. | |
progress_Progress | None | Called with (completed, total) queries; returning
False stops the batch and raises CancelledError, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
*× 2Absorbs every donor into this index, one after another, keeping their graphs rather than re-inserting their vectors, and linking each in by walks across the appended part.def absorb(
*donors: DenseIndex = (),
progress: _Progress | None = None,
progress_steps: int = 0,
) -> RefineReport Each donor handle is consumed and every verb on it afterwards raises. Readers of a RAM index may keep searching throughout, while a VRAM one admits no overlapping search.
Cancellation stops the closing refinement alone: every donor is still consumed, the
islands still re-linked, and the call raises CancelledError. A donor whose absorption
fails, and every later one, stays a live handle its caller still owns, though the
entries of the one it struck may already have moved into this index.
donorsDenseIndex | The indexes to absorb. | |
|---|---|---|
progress_Progress | None | Called with (completed, total) nodes the closing refinement re-selected; returning False stops it, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. |
*× 2Splits this index into the empty receivers, the inverse of absorb: the entries are partitioned along the graph, each part lands in one receiver with its edges kept, and a closing refinement re-links every receiver.def split(
*receivers: DenseIndex = (),
expansion_factor: int = 0,
seed: int = 0,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> RefineReport This index is left empty and live. Receivers match its residency, scalar, metric, geometry and shard count.
receiversDenseIndex | At least two empty indexes, one per part. | |
|---|---|---|
expansion_factorint | Breadth of the closing walks; 0 derives it. | |
seedint | Picks the part roots; equal seeds split equally. | |
progress_Progress | None | Called with (completed, total) nodes the closing refinements re-selected; returning False stops them, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
*× 2Draws keys around focus, or across the whole index, each hanging from a shown or earlier draw and placed in three dimensions beside the shown ones - so a view grows one connected sample as it zooms, never scanning the index.def sample(
wanted: int,
arena: Arena,
/,
*,
shown: Sequence[_KeyLike] | _Tensor | None = None,
shown_coordinates: _Tensor | None = None,
focus: Sequence[_KeyLike] | _Tensor | None = None,
seed: int = 0,
expansion_factor: int = 0,
progress: _Progress | None = None,
progress_steps: int = 0,
stats: DenseTraversalStats | None = None,
) -> Sample Equal seeds, shown keys and focus over an unchanged index draw equally, and a larger wanted draws a superset. Only a RAM index samples yet.
wantedint | The upper bound on draws. | |
|---|---|---|
arenaArena | Where the draws are written, rewound by the call. | |
shownSequence[_KeyLike] | _Tensor | None | The keys already shown, never drawn again. | |
shown_coordinates_Tensor | None | (len(shown), 3) float32 places of the shown keys, the points later draws are placed against. | |
focusSequence[_KeyLike] | _Tensor | None | The keys to look around; None looks across the index. | |
seedint | The draw; equal seeds draw equally. | |
expansion_factorint | Breadth of the walks behind the draws; 0 derives. | |
progress_Progress | None | Called with (written, wanted) draws. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. | |
statsDenseTraversalStats | None | Overwritten with this call's telemetry. |
wanted only once the region is exhausted.*× 2Writes the index under path, in the layout its extension picks: one .safegraphs monolith, or a .safegraphs.json manifest beside one part per shard.def save(
path: _PathLike,
/,
*,
progress: _Progress | None = None,
progress_steps: int = 0,
) -> None Demands a mutation-free window; concurrent readers keep searching throughout.
path_PathLike | Where the checkpoint goes. | |
|---|---|---|
progress_Progress | None | Called with (completed, total) shards; returning
False stops the write and raises CancelledError, leaving a checkpoint no
reader accepts and whatever parts it already wrote for the caller to remove. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. |
save_*_buffer× 2Serializes the index as one monolith of every shard, the very bytes save writes to a .safegraphs path.def save__buffer(
arena: Arena,
/,
*,
progress: _Progress | None = None,
progress_steps: int = 0,
) -> Monolith arenaArena | Where the monolith lands, rewound by the call. | |
|---|---|---|
progress_Progress | None | Called with (completed, total) bytes; returning
False stops the write and raises CancelledError, None carries on. | |
progress_stepsint | Reports the call makes at most; 0 derives to ten. |
>>> index = usearch.DenseIndex.init_ram(dimensions=4)
>>> index.reserve(1)
>>> checkpoint = index.save_buffer(usearch.Arena())
>>> usearch.DenseIndex.metadata_read_buffer(checkpoint).dimensions
4
cursorOpens a walk over the stored entries that DenseCursor.next pulls in batches, from the starts keys in their order when given, or across every entry as stored otherwise.def cursor(
starts: Sequence[_KeyLike] | _Tensor | None = None,
) -> DenseCursor search_streamOpens a resumable nearest-neighbor stream for one query, which next pulls for as long as the caller wants more, each pull into the arena it names.def search_stream(
query: _Tensor,
/,
*,
expansion_factor: int = 0,
dtype: Scalar | None = None,
) -> DenseSearchStream Every pull blocks, on the receiver's executor, which the stream keeps alive, or on the calling thread.
query_Tensor | One vector of dimensions scalars. | |
|---|---|---|
expansion_factorint | Breadth of the candidates; 0 derives it. | |
dtypeScalar | None | Names the query scalar type when the buffer cannot. |
>>> from array import array
>>> index = usearch.DenseIndex.init_ram(dimensions=2)
>>> index.reserve(1)
>>> index.insert([5], array('d', [0.1, 0.2]))
>>> stream, arena = index.search_stream(array('d', [0.1, 0.2])), usearch.Arena()
>>> [int(match.key) for match in stream.next(4, arena)[0]]
[5]
>>> len(stream.next(4, arena)[0])
0
DeferredOnAn index bound to the executor its verbs submit to, each answering a Deferred at once.1class DeferredOn[IndexT] __class_getitem__Names the index the receiver addresses, as DeferredOn[DenseIndex].def __class_getitem__(item: Any, /) -> GenericAlias