Skip to content
67 changes: 67 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
When performing a code review, check that:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can copilot instructions point to the existing AGENTS.md files where applicable? It looks like a lot of instructions are manually duplicated here, so we risk them getting out of sync.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1.
Do we really need .github/copilot-instructions.md? if so, how is it semantically different from /AGENTS.md? Why can't we keep all agent-related instructions in /AGENTS.md?

- No unit tests were eliminated without a strong reason.
- Additional dependencies introduced have a strong justification.
- Changes are not likely to increase build times.
- Each file has a license header.
```
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT license.
*/
```

## SemVer and API Compatibility

- The workspace obeys SemVer. Removing or changing public API signatures (functions, types, re-exports) is a breaking change and requires a major version bump or a deprecated compatibility shim.
- Re-exports are part of the public API surface — removing them is also a breaking change.
- If changing public behavior, explain migration impact in the PR description.

## Error Handling

- Do not introduce `panic!` paths for recoverable errors — propagate with `Result` instead.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably deserves a mention/move to the top-level AGENTS.md

- Keep error types small. Avoid large enums/structs that blow up the stack; look for ways to reduce field sizes (e.g., compute derivable fields, use enums instead of `&'static str`).
- Prefer `ANNError::new(ANNErrorKind::…, e)` over the old `log_*`-style constructors, which force eager string formatting and double-log errors.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: There is not double-log from these APIs (the name is a misnomer). The biggest issue is eager string formatting.

- When using `thiserror`, rely on `#[from]` for automatic `Error::source` chaining — do not format the inner error in the `#[error("…")]` display string.
- Include relevant context values (e.g., the kind, key, or dimension) in error messages for debuggability.

## Documentation

- Doc comments and README examples must match actual API signatures and serialized shapes. Stale examples that fail to compile or deserialize are treated as bugs.
- Do not leave dead references to APIs that no longer exist.
- When changing a function signature or removing a parameter, update all doc comments that mention the old signature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More suggestions on documentation:

  • Doc and inline comments should describe what the code does. Do not describe behavior by contrasting it with other code, except when referencing documented external behavior.
  • Avoid comments that simply restate what is already clear from function signatures or where clauses.
  • Do not list functions or types in module docs that rustdoc already documents.
  • Module-level docs should describe the purpose and structure of the module, not its contents.


## Constants and Assumptions

- Do not hardcode magic values — make them configurable with sensible defaults and document the rationale.
- If using `wrapping_add` or other wrapping arithmetic, justify why overflow is expected or acceptable.
- Add assertions for invariants that callers or maintainers would otherwise have to discover by reading the implementation.

## SIMD and Platform Portability

- Do not assume specific SIMD lane widths (e.g., `f32s::LANES == 8`). Code must be correct on AVX2, AVX-512, and ARM/NEON.
- When touching architecture-specific intrinsics, verify cross-platform behavior per `diskann-wide/README.md`.

## Testing

- Keep test helpers close to the code they exercise, typically in a `mod tests` at the bottom of the file or in an adjacent test module, guarded with `#[cfg(test)]`.
- Do not add tests for derived traits (`Clone`, `Debug`, `PartialEq`) or enums unless they have explicit behavior beyond the derive.
- Test edge cases like empty inputs (e.g., empty iterators) to lock in defined behavior and prevent divide-by-zero or NaN results.

## Rayon and Parallelism

- Never use the global Rayon thread pool. Always execute parallel work within the provided `RayonThreadPool` or `RayonThreadPoolRef`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guidance is more for diskann-providers/diskann-disk than lower level crates. Lower level crates like diskann-quantization should use the dynamically scoped thread pool, but advertise this using the Parallelism enum.

- Preserve deadlock-avoidance intent when modifying nested parallel loops. Be aware that combining blocking synchronization (e.g., mutex acquisition) with Rayon work-stealing can cause deadlocks.

## Unsafe Code and Safety

- Every `unsafe` block must have a `// SAFETY:` comment directly above it explaining why the operation is sound. This is enforced by the `undocumented_unsafe_blocks = "warn"` workspace lint.
- Safety comments must be specific and verifiable — state the concrete precondition that makes the operation safe (e.g., `// SAFETY: i + width <= len ensures this read is in-bounds`). Do not use vague justifications like `// SAFETY: this is safe`.
- Safety contracts on `unsafe fn` signatures must be internally consistent — if the documented precondition says `scratch.len() >= n`, ensure the implementation does not write beyond `n` elements (e.g., due to rounding up to a panel/block size).
- Prefer safe abstractions over raw `unsafe` when possible. Use `unsafe` only when there is a measurable performance benefit or when interfacing with FFI/intrinsics.
- For pointer arithmetic, prefer `offset_from` to express bounds rather than `wrapping_add` unless wrapping behavior is intentionally needed — and document why.
- When calling SIMD intrinsics or FFI, list the specific preconditions being satisfied (alignment, length, non-null, valid initialization).

## Naming

- Use names that reflect the current architecture, not historical ones. Rename outdated terms when refactoring.
- Struct and type names should map clearly to their domain concepts for easier mental mapping.
11 changes: 0 additions & 11 deletions .github/instructions.md

This file was deleted.

46 changes: 33 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
# DiskANN

[![DiskANN Main](https://github.com/microsoft/DiskANN/actions/workflows/push-test.yml/badge.svg?branch=main)](https://github.com/microsoft/DiskANN/actions/workflows/push-test.yml)
[![PyPI version](https://img.shields.io/pypi/v/diskannpy.svg)](https://pypi.org/project/diskannpy/)
[![Downloads shield](https://pepy.tech/badge/diskannpy)](https://pepy.tech/project/diskannpy)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
The new main branch implements DiskANN3 in Rust, and used by many search, recommendation, RAG and vector DB platforms across Microsoft.
DiskANN3 is a library for bringing scalable, accurate and cost-effective vector indexing to stores and databases.
See our [wiki](https://github.com/microsoft/DiskANN/wiki/DiskANN-Project-and-Research-Overview-(2018%E2%80%90present)) for a comrehensive overview of research underlying this project.

[![DiskANN Paper](https://img.shields.io/badge/Paper-NeurIPS%3A_DiskANN-blue)](https://papers.nips.cc/paper/9527-rand-nsg-fast-accurate-billion-point-nearest-neighbor-search-on-a-single-node.pdf)
[![DiskANN Paper](https://img.shields.io/badge/Paper-Arxiv%3A_Fresh--DiskANN-blue)](https://arxiv.org/abs/2105.09613)
[![DiskANN Paper](https://img.shields.io/badge/Paper-Filtered--DiskANN-blue)](https://harsha-simhadri.org/pubs/Filtered-DiskANN23.pdf)
DiskANN3 is written to be extensible to a new store via the implementation of `Provider` API.
The library provides and update and query API to users and translate the requests into reads and mutations to the underlying store via the Provider API.

The library supports the following algorithmic features
- Real-time updates while allowing stable recall under long update streams -- no merges, rebuilds, patches needed.
- A diverse set of distance functions and quantizers (PQ, MinMax, Scalar, Spherical) implemented for x86 and aarch64.
- Hooks to allow simple filters (predicate) processsing in conjuction with vector search.

This repo has several Provider implementations.
- In-memory providers. These are volatile and not intended for use in databses. DiskANN3 with in-memory providers outperforms HNSWlib on throughput.
- Disk provider. This is intended to match the performormance of the first version of DiskANN reported in NeurIPS'19 paper.
- Garnet provider for high-through scale up vector search
- Bf-tree provider.
A provider for Cosmos DB NoSQL is not included but documented in this paper at [https://www.vldb.org/pvldb/vol18/p5166-upreti.pdf](aka.ms/CosmosDB/VectorSearch).

> [!IMPORTANT]
> We are currently in the process of updating this repository with a new version of the code written in Rust.
## Getting Started

- To benchmark this library, please start with [diskann-benchmarks](/diskann-benchmark/README.md). This also allows you to build, store and load indices
- To add a new backend, implement the [Provider API](/diskann/src/provider.rs) contract for your store/DB.

DiskANN is a suite of scalable, accurate and cost-effective approximate nearest neighbor search algorithms for large-scale vector search that support real-time changes and simple filters.
This code is based on ideas from Microsoft's [DiskANN](https://aka.ms/AboutDiskANN).
The main branch now contains a rearchitected project written in Rust.

This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
Expand All @@ -24,7 +33,18 @@ See [guidelines](CONTRIBUTING.md) for contributing to this project.

## Legacy C++ Code

Older C++ code is retained on the `cpp_main` branch, but is not actively developed or maintained.
[![DiskANN Main](https://github.com/microsoft/DiskANN/actions/workflows/push-test.yml/badge.svg?branch=main)](https://github.com/microsoft/DiskANN/actions/workflows/push-test.yml)
[![PyPI version](https://img.shields.io/pypi/v/diskannpy.svg)](https://pypi.org/project/diskannpy/)
[![Downloads shield](https://pepy.tech/badge/diskannpy)](https://pepy.tech/project/diskannpy)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)


Older C++ code is retained on the `cpp_main` branch, and implements the following papers, but is not actively developed or maintained.

[![DiskANN Paper](https://img.shields.io/badge/Paper-NeurIPS%3A_DiskANN-blue)](https://papers.nips.cc/paper/9527-rand-nsg-fast-accurate-billion-point-nearest-neighbor-search-on-a-single-node.pdf)
[![DiskANN Paper](https://img.shields.io/badge/Paper-Arxiv%3A_Fresh--DiskANN-blue)](https://arxiv.org/abs/2105.09613)
[![DiskANN Paper](https://img.shields.io/badge/Paper-Filtered--DiskANN-blue)](https://harsha-simhadri.org/pubs/Filtered-DiskANN23.pdf)

The legacy C++ code was forked off from [code for NSG](https://github.com/ZJULearning/nsg) algorithm.

If you use the C++ version in your software please cite the following:
Expand Down
Loading
Loading