Releases: microsoft/DiskANN
Release list
diskann-garnet v4.0.1
Resolves minor concurrency issue with append_vector where the neighbor cache and stored neighbors could potentially diverge.
DiskANN v0.55.0
Breaking changes since 0.54.0
Removed diskann-platform; decoupled diskann-providers (#1205)
The diskann-platform crate is deleted — its perf counters become a private
detail of Timer, and its io primitives (io_uring / Windows IOCP / handles)
move next to their only consumer, aligned_file_reader, in diskann-disk.
Timer relocates from diskann-providers to
diskann-disk::utils::instrumentation::Timer. diskann-providers loses its
opentelemetry / diskann-platform dependencies and its perf_test feature;
diskann-disk loses its unused virtual_storage feature and
Timer::{elapsed_seconds, elapsed_seconds_for_step}.
- Upgrade: Drop any dependency on
diskann-platform. ReferenceTimerat
diskann_disk::utils::instrumentation::Timer(or usestd::time::Instant
directly, as the providers/tools call sites now do). Remove references to the
diskann-providersperf_testfeature and thediskann-disk
virtual_storagefeature.
Removed dead pub code; dropped diskann-tools → diskann-disk dependency (#1185)
Removed the dead search_disk_index / build_disk_index modules in
diskann-tools, the unwired AssociatedDataFilter /
default_associated_data_filter in diskann-disk, and unreferenced
test_utils size constants. Ground-truth utilities and build_pq are no longer
generic over diskann-disk's GraphDataType.
- Upgrade: Replace uses of the removed modules with the live disk build/search
paths indiskann-benchmark, and the removedAssociatedDataFilterwith the
liveVectorFilter/default_vector_filter. Where you relied on the
GraphDataTypegeneric, switch to a plainV: VectorRepr(plus an
associated-data generic where needed).
FilteredAccessor introduced; QueryVisitDecision removed (#1141, #1192)
A new filter-aware FilteredAccessor trait replaces the pattern of passing a
QueryLabelProvider to every call site; multi-hop search is rewritten on top of
it. The SearchAccessor bound on SearchStrategy::SearchAccessor is relaxed to
let the disjoint FilteredAccessor participate. QueryVisitDecision is removed,
and QueryLabelProvider moves to diskann::graph::ext::labeled (as a
compatibility layer). Follow-up #1192
changes the expand_beam_accept_only bound from
P: HybridPredicate<Accept<Self::Id>> to
P: Predicate<Self::Id> + PredicateMut<Accept<Self::Id>>.
- Upgrade: Implement/consume
FilteredAccessorfor filtered search; move
QueryLabelProviderimports todiskann::graph::ext::labeled. Remove any use
ofQueryVisitDecision. Updateexpand_beam_accept_onlypredicate bounds to
the splitPredicate+PredicateMut<Accept<_>>form.
Disk-path filtered search: search() signatures gained adaptive_l (#1173)
DiskIndexSearcher::search / search_internal now take
adaptive_l: Option<AdaptiveL>. None preserves today's behavior; Some(_)
routes the graph path through the new filter_search() (backed by
InlineFilterSearch + the new PredicateLabelProvider adapting
&dyn Fn(&u32) -> bool to QueryLabelProvider<u32>).
- Upgrade: Add the new
adaptive_largument at disk-search call sites (pass
Nonefor unfiltered search).
Flat index: SearchStrategy / DistancesUnordered trait changes (#1160)
FlatIndex::knn_search gains post-processing support via
diskann::glue::SearchPostProcess. With the VectorId scalar-conversion
constraint gone, DistancesUnordered now has HasId as a super-trait and
SearchStrategy no longer carries an Id associated type.
- Upgrade: Add a
HasIdimpl to yourDistancesUnorderedtypes and remove the
Idassociated type fromSearchStrategyimplementations; tie the flat
index's ID type to the underlyingDataProvider::InternalId.
Benchmark::try_match / description signatures changed (#1231)
try_match changes from
fn try_match(&self, input: &Self::Input) -> Result<MatchScore, FailureScore>
to fn try_match(&self, input: &Self::Input, context: &MatchContext) -> Score,
and description drops its input: Option<&Self::Input> argument.
- Upgrade: Update
Benchmarkimplementors to accumulate into the newScore
type (recording a reason on every failure viaMatchContext) and to the
simplifieddescription(&self, f)signature.
SampleableForStart now requires WithApproximateNorm (#1223)
WithApproximateNorm is now a super-trait of SampleableForStart (required by
StartPointStrategy::compute).
- Upgrade: Ensure
SampleableForStartimplementors also implement
WithApproximateNorm.
bf-tree upgraded 0.4 → 0.5; snapshot API migration (#1183)
Migrates to bf-tree 0.5's CPR snapshot API: snapshot* →
cpr_snapshot(&path) / BfTree::new_from_cpr_snapshot(); save_bftree is no
longer async; BfTreeParams::to_config and copy_snapshot_if_needed are
removed. A new use_snapshot: bool is added to BfTreeProvider,
BfTreeProviderParameters, and SavedParams;
BfTreeStoreConfig::use_snapshot is required in benchmark JSON input
(SavedParams::use_snapshot defaults for backwards compatibility with existing
saved-param files).
- Upgrade: Set
use_snapshotinBfTreeStoreConfigJSON; migrate any direct
snapshot calls to the CPR API; treatsave_bftreeas synchronous.
diskann-garnet FFI: inline filtering, bumped to 3.0.0 (#1162)
Garnet replaces its postfilter with inline filtering (~50x QPS improvement in
the PR's measurement) and is bumped to 3.0.0.
- Upgrade: Garnet consumers must adopt the 3.0.0 FFI surface with inline
filtering.
diskann-tools CLI standardized to kebab-case; range-search bin removed (#1217, #1213, #1212)
All diskann-tools command-line parameters now use kebab-case, variable names
are standardized, and the old (disabled) disk-index range-search binary is
removed in favor of the new range-groundtruth utility. The
vector_filters_file option is renamed to reflect that it takes a
pre-calculated bitmap.
- Upgrade: Update scripts to the kebab-case flag names and the renamed
bitmap-input option; use the new range-groundtruth utility instead of the
removed binary.
Notable fixes & features (non-breaking)
- Serialization: New foundational
diskann-recordcrate for versioned
save/load of DiskANN indexes (Disk + Memory backends,Save/Loadtraits,
save_fields/load_fieldsmacros) (#1188). - Distance functions: New
ProjectedEigendistance for multi-vector re-ranking
indiskann-quantization(#1203). - Diversity search: Determinant-diversity post-processing wired as an optional
plugin for async full-precision topk and disk-index search, with new example
configs (#1011). - Benchmarks: New end-to-end flat-index benchmark for full-precision in-memory
search (#1170); consolidated
Benchmark::try_matchlogic reduces implementor boilerplate (~700 lines)
(#1231); directory checking
added todiskann-benchmark-runner(unifies file/dir discovery)
(#1227). - bftree concurrency: Striped
RwLockonNeighborProvidereliminates lost
edges under concurrent mutation (11–51% edge loss → 0), safe dual-store write
ordering, and quant-store cleanup on delete (#1158). - bftree correctness: Validate record sizes at construction and force insert
errors to be handled, fixing misleading "vector not found" errors on
oversized records (#1166,
#1194). - Benchmark recall: Fixed floating-point precision loss in the recall
calculation (exact integer accumulation grouped by denominator)
(#1171 / #1241). - Filtered search: Simplified the
expand_beam_accept_onlypre-filter
predicate, restoring multi-hop filtered-search recall (#1192).
diskann-garnet v4.0.0
Adds support for persisting quantization state, and adds a new out parameter to create_index().
diskann-garnet v3.0.0
Adds inline filtering support via a new filter callback.
DiskANN v0.54.0
Breaking changes since 0.53.0
Graph search: DataProvider contract collapsed into SearchAccessor (#1067)
Accessor, BuildQueryComputer, ExpandBeam, SearchExt, and AsNeighbor/NeighborAccessor are merged into a single SearchAccessor trait. The indexing layer no longer has a notion of element types.
- Upgrade: Implement
SearchAccessorinstead of the removed traits; useSearchAccessor::expand_beamfor search.SearchStrategy/InsertStrategy/DefaultSearchStrategy/DefaultPostProcessornow carry a lifetime, and the query is passed intosearch_accessor(accessors may now borrow the query).SearchPostProcessno longer takes aQueryComputer(only requiresHasId). The blanketworkingset::Fillimpl forworkingset::Mapwas removed — implementFillyourself, or use the new synchronousMap::fillhelper.
Insert/prune: consolidated into PruneAccessor (#1138, follow-up to #1067)
Removed DelegateNeighbor, AsNeighbor, AsNeighborMut, HasElementRef, BuildDistanceComputer, workingset::Fill, and workingset::AsWorkingSet, folded into a single PruneAccessor trait.
- Upgrade: Implement
PruneAccessor(providesneighbors()for neighbor delegation andfill()returning both aViewand the distance computer). Noteneighbors()now borrows&mut self.
VectorId: removed scalar conversion traits/bounds (#1145, #1133)
Dropped VectorIdTryFrom, TryIntoVectorId, methods vector_id_try_from/try_into_vector_id, helpers vecid_from_u32/vecid_from_usize, and IdConversionError/ErrorToVectorId. Internal IDs no longer need to convert to/from usize.
- Upgrade: Where
usizeconversion is still required (e.g. roaring-treemap keys indiskann-label-filter), add an explicitIntoUsizebound (now required onRoaringAttributeStore,InlineBetaStrategy,QueryBitmapEvaluator/BitmapFilter).DiskANNIndex::prune_rangenow takesimpl IntoIterator<Item = DP::InternalId> + Sendinstead ofRange<DP::InternalId>— construct the iterator for your ID type at the call site.SimpleNeighborProviderAsyncandbftree::VectorProviderare no longer generic over the ID type (fixed tou32).
DiskIndexReader: dropped vestigial VectorType generic (#1161)
- Upgrade: Replace
DiskIndexReader::<T>::new(...)withDiskIndexReader::new(...).
Filtered search renames (#1149)
MultihopSearch → MultihopFilterSearch; benchmark config phases MultiHopSearchPhase/InlineSearchPhase → MultihopFilterSearchPhase/InlineFilterSearchPhase.
- Upgrade: Update references to the new names.
diskann-garnet FFI: BIN/Q8 quantizers, bumped to 2.0.0 (#1050)
Vectors are now stored as Poly<[u8], AlignOfEight>; a type-erased GarnetQuantizer trait replaces index/provider type parameterization. New FFI: insert() returns a success/training-ready flag, plus build_quant_table() and backfill_quant_vectors() for caller-driven async training/backfill. Accessor renamed to DynamicAccessor; the FSM is now lockable and gained visit_used().
- Upgrade: Garnet consumers must adopt the new 2.0.0 FFI surface (handle the new
insert()return flag and drivebuild_quant_table/backfill_quant_vectors).
Full list of changes.
- Multi-vector MaxSim benchmark with BYOTE factory by @suri-kumkaran in #1027
- BufferedFnPtr and take
UnalignedSlice. by @hildebrandmw in #1113 - [diskann-wide] Test unaligned loads properly. by @hildebrandmw in #1110
- [diskann-garnet] Implement BIN and Q8 quantizers by @metajack in #1050
- Right-size tile conversion buffer in
tiled_reduceby @suri-kumkaran in #1123 - Add JobId labels to disk benchmark CI runners by @arrayka in #1120
- nightly: remove stale
bf_treefeature from DISKANN_FEATURES by @Copilot in #1112 - Add a small streaming runbook and groundtruth to test_data by @magdalendobson in #1127
- fix: redirect disk-index benchmark build artifacts to target/tmp by @arrayka in #1132
- Remove
try_into_vector_idconversion in prune. by @hildebrandmw in #1133 - [diskann-garnet] Fix handling of missing quant vectors during delete() by @metajack in #1130
- Simplify the
DataProvidercontract for graph search by @hildebrandmw in #1067 - Add Documentation DO/DON'T section in
agents.mdby @suri-kumkaran in #1103 - Fix quantizer detection in train_quantizer() and set_element() by @metajack in #1140
- add bf_tree benchmark infrastructure by @JordanMaples in #1106
- [RFC] What filtered search algorithms should DiskANN support? by @magdalendobson in #1128
- Inline filtered search with adaptive L by @magdalendobson in #1131
- [benchmark] Spherical exhaustive benchmark threadpool bug by @arkrishn94 in #1148
- Consolidate insert into
PruneAccessorby @hildebrandmw in #1138 - Rename MultihopSearch to MultihopFilterSearch by @magdalendobson in #1149
- [bftree] Bug with writing length to neighbor list by @arkrishn94 in #1150
- Fix handling of deletes and ID minting during concurrent insert/delete by @metajack in #1146
- [VectorId] Remove Id conversion bounds and traits by @arkrishn94 in #1145
- Remove vestigial VectorType parameter from DiskIndexReader by @doliawu in #1161
- change documentation link to repository link by @harsha-simhadri in #1156
- [diskann-garnet] Fix handling of start points on fresh indexes by @metajack in #1167
- Bump version to 0.54.0 by @arkrishn94 in #1165
Full Changelog: v0.53.0...v0.54.0
diskann-garnet v2.0.4
Fixed handling of start points on fresh indexes.
diskann-garnet v2.0.3
Fixed race condition where IDs could be handed out multiple times.
diskann-garnet v2.0.2
Fixed issue where quantizer training could be retriggered.
diskann-garnet 2.0.1
Small bugfix release. Fixes handling of missing quant vectors during delete().
diskann-garnet v2.0.0
This release adds support for I8 vectors as well as binary (BIN) and scalar 8-bit (Q8) quantizers. For f32 vectors, the available quantizers are now NOQUANT, BIN, and Q8. For u8 and i8 vectors, XNOQUANT_U8, XNOQUANT_I8, XBIN_U8, and XBIN_I8 are available.
The version is now 2.0.0 to account for the FFI changes.
Note, quantization support is not yet persisted to disk, so this release should be used for in-memory workloads only. Persistence will follow shortly.