[RFC] What filtered search algorithms should DiskANN support?#1128
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an RFC documenting an empirical evaluation of DiskANN filtered-search algorithm variants, with a recommendation for which algorithms the repo should support going forward.
Changes:
- Introduces a new RFC describing existing and proposed filtered-search algorithms (inline, beta, multi-hop, two-queue, adaptive-L).
- Records benchmark results on two datasets (Caselaw and YFCC) with accompanying plots.
- Proposes a path forward: add inline (optionally adaptive-L), retain multi-hop, deprecate beta, and close two-queue.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1128 +/- ##
==========================================
+ Coverage 88.87% 89.45% +0.57%
==========================================
Files 485 484 -1
Lines 92112 91407 -705
==========================================
- Hits 81868 81767 -101
+ Misses 10244 9640 -604
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…soft/DiskANN into users/magdalen/filtered_search_rfc
|
Could this be in the wiki? The plots are a quite large addition to the repo. |
Do we want an RFC that points to benchmarks in the wiki then? Because folks were pretty clear that they wanted an RFC on filtered search. |
I have moved the benchmark discussion section to the DiskANN wiki: https://github.com/microsoft/DiskANN/wiki/Evaluation-of-Filtered-Search-Algorithms |
arrayka
left a comment
There was a problem hiding this comment.
LGTM. Approving, assuming the QPS and latency comparison between Adaptive L and the beta filter for disk search scenarios looks promising.
There was a problem hiding this comment.
Thanks for the great work. The RFC recommendations around deprecating beta filter, adding inline filtered search, and adding adaptive L search make sense to me.
One follow up implementation question is how we should expose these similar and overlapping algorithms at the right level of granularity, so clients can reuse them through providers, with or without their own query planners, depending on their use cases.
This PR implements the recommendation in the [filtered search RFC](#1128) to implement inline filtering with the adaptive L method as an optional addition. --------- Co-authored-by: qingcha chen <qinchen@microsoft.com> Co-authored-by: Magdalen Manohar <magdalen@magdalen.localdomain> Co-authored-by: Magdalen Manohar <mmanohar@microsoft.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Mark Hildebrand <hildebrandmw@gmail.com> Co-authored-by: Mark Hildebrand <mhildebrand@microsoft.com>
## 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 `SearchAccessor` instead of the removed traits; use `SearchAccessor::expand_beam` for search. `SearchStrategy`/`InsertStrategy`/`DefaultSearchStrategy`/`DefaultPostProcessor` now carry a lifetime, and the query is passed into `search_accessor` (accessors may now borrow the query). `SearchPostProcess` no longer takes a `QueryComputer` (only requires `HasId`). The blanket `workingset::Fill` impl for `workingset::Map` was removed — implement `Fill` yourself, or use the new synchronous `Map::fill` helper. ### 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` (provides `neighbors()` for neighbor delegation and `fill()` returning both a `View` and the distance computer). Note `neighbors()` 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 `usize` conversion is still required (e.g. roaring-treemap keys in `diskann-label-filter`), add an explicit `IntoUsize` bound (now required on `RoaringAttributeStore`, `InlineBetaStrategy`, `QueryBitmapEvaluator`/`BitmapFilter`). `DiskANNIndex::prune_range` now takes `impl IntoIterator<Item = DP::InternalId> + Send` instead of `Range<DP::InternalId>` — construct the iterator for your ID type at the call site. `SimpleNeighborProviderAsync` and `bftree::VectorProvider` are no longer generic over the ID type (fixed to `u32`). ### `DiskIndexReader`: dropped vestigial `VectorType` generic (#1161) - **Upgrade:** Replace `DiskIndexReader::<T>::new(...)` with `DiskIndexReader::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 drive `build_quant_table`/`backfill_quant_vectors`). ## Notable fixes & features (non-breaking) - **Concurrency:** Fixed an ID double-minting race during concurrent insert/delete; delete now removes mapping/attributes before marking the ID free (#1146). Fixed garnet handling of missing quant vectors during `delete()` (#1130). - **Quantization:** Fixed quantizer detection in `train_quantizer()` / `set_element()` (#1140). - **Filtered search:** Added inline filtered search with adaptive `L` (#1131), per the filtered-search RFC (#1128). - **bftree:** Fixed a bug writing the length to the neighbor list (#1150). - **Benchmarks/infra:** Multi-vector MaxSim benchmark with BYOTE factory (#1027); `bf_tree` benchmark infrastructure (#1106); spherical exhaustive benchmark threadpool fix (#1148); right-sized `tiled_reduce` tile buffer (#1123). - `BufferedDistance` accepts `UnalignedSlice`: added a `PreprocessedDistanceFunction<UnalignedSlice<'_, T>>` impl for `BufferedDistance` (#1113).
This PR adds an RFC on which filtered search algorithms the DiskANN repo should support.