Skip to main content

diskann_providers/storage/
api.rs

1/*
2 * Copyright (c) Microsoft Corporation.
3 * Licensed under the MIT license.
4 */
5
6use std::{future::Future, num::NonZeroUsize};
7
8use super::{StorageReadProvider, StorageWriteProvider};
9use diskann_vector::distance::Metric;
10
11use super::get_mem_index_data_file;
12use crate::model::graph::provider::async_::PrefetchCacheLineLevel;
13
14/// A general trait for saving `self` to disk.
15///
16/// The generic parameter `T` is used to allow types to require arbitrary associated
17/// metadata in order to successfully save themselves.
18///
19/// Additionally, types may overload the auxiliary state to customize semantics.
20///
21/// See also: [`LoadWith`].
22pub trait SaveWith<T> {
23    /// The return type upon successful saving. This is often (but is not required to be)
24    /// the number of bytes written to disk.
25    type Ok: Send;
26
27    /// The error type if serialization is unsuccessful.
28    type Error: std::error::Error + Send;
29
30    /// Safe `self` to disk using `provider` for IO-related needs. Argument `auxiliary`
31    /// can be arbitrary metadata required for a successful operation, such as file paths.
32    fn save_with<P>(
33        &self,
34        provider: &P,
35        auxiliary: &T,
36    ) -> impl Future<Output = Result<Self::Ok, Self::Error>> + Send
37    where
38        P: StorageWriteProvider;
39}
40
41/// A general trait for loading `self` from disk.
42///
43/// The generic parameter `T` is used to allow types to require arbitrary associated
44/// metadata in order to successfully load themselves.
45///
46/// Additionally, types may overload the auxiliary state to customize semantics.
47///
48/// See also: [`SaveWith`].
49pub trait LoadWith<T>: Sized {
50    /// The error type if deserialization is unsuccessful.
51    type Error: std::error::Error + Send;
52
53    /// Load `self` form disk using `provider` for IO-related needs. Argument `auxiliary`
54    /// can be arbitrary metadata required for a successful operation, such as file paths.
55    fn load_with<P>(
56        provider: &P,
57        auxiliary: &T,
58    ) -> impl Future<Output = Result<Self, Self::Error>> + Send
59    where
60        P: StorageReadProvider;
61}
62
63/// The file-path prefix for saving and loading an async index.
64///
65/// An auxiliary type for [`SaveWith`] and [`LoadWith`] to indicate that the object being
66/// saved or loaded is part of an async in-memory index.
67///
68/// This mainly controls how file-paths are generated.
69///
70/// For example, graph data is located at the raw-prefix, while the full-precision data
71/// is saved using the `.data` suffix.
72#[derive(Debug, Clone, PartialEq, Eq)]
73pub struct AsyncIndexMetadata {
74    prefix: String,
75}
76
77impl AsyncIndexMetadata {
78    /// Construct a new `AsyncIndexPrefix` from `pathlike`.
79    pub fn new<T>(pathlike: T) -> Self
80    where
81        String: From<T>,
82    {
83        Self {
84            prefix: pathlike.into(),
85        }
86    }
87
88    /// Return the file path contained in `self` as a `&str`.
89    pub fn prefix(&self) -> &str {
90        &self.prefix
91    }
92
93    /// Obtain the file path for full-precision data using `self` as the file path prefix.
94    pub fn data_path(&self) -> String {
95        get_mem_index_data_file(&self.prefix)
96    }
97
98    /// Obtain the file path for additional points file
99    pub fn additional_points_id_path(&self) -> String {
100        format!("{}.additional_points_id", self.prefix)
101    }
102}
103
104/// The file-path prefix for saving only graph data during disk index construction.
105///
106/// An auxiliary type for [`SaveWith`] to specify graph-only serialization.
107#[derive(Debug, Clone)]
108pub struct DiskGraphOnly {
109    prefix: String,
110}
111
112impl DiskGraphOnly {
113    /// Constructs a new `DiskGraphOnly` from a path-like object.
114    pub fn new<T>(pathlike: T) -> Self
115    where
116        String: From<T>,
117    {
118        Self {
119            prefix: pathlike.into(),
120        }
121    }
122
123    /// Return the file path contained in `self` as a `&str`.
124    pub fn prefix(&self) -> &str {
125        &self.prefix
126    }
127}
128
129/// Indicates that the canonical layout for a Quant index is expected for deserialization.
130///
131/// For a file-path prefix `prefix`, this layout includes the following files:
132///
133/// **Common:**
134/// * `prefix`: The file that contains the saved graph.
135/// * `prefix.data`: The serialized full-precision data in `.bin` form.
136///
137/// Depending on the quantization method used, one of the following sets of files will also be present:
138///
139/// **If Product Quantization (PQ) is used:**
140/// * `prefix_build_pq_pivots.bin`: The saved PQ pivot table.
141/// * `prefix_build_pq_compressed.bin`: The saved PQ codes.
142///
143/// **If Scalar Quantization (SQ) is used:**
144/// * `prefix_sq_compressed.bin`: The saved scalar quantized codes.
145/// * `prefix_scalar_quantizer_proto.bin`: The saved scalar quantizer metadata.
146pub struct AsyncQuantLoadContext {
147    /// The file path prefix of the index.
148    pub metadata: AsyncIndexMetadata,
149    /// The number of frozen points stored in the datasets.
150    pub num_frozen_points: NonZeroUsize,
151    /// The metric to use for this index.
152    pub metric: Metric,
153    /// The number of iterations to prefetch when performing bulk-retrievals.
154    pub prefetch_lookahead: Option<usize>,
155    /// Temporary parameter to indicate if the index is a disk index to load right file names.
156    /// This can be removed once disk index uses same file names as async index.
157    pub is_disk_index: bool,
158    /// controls the prefetch cache line level for the index.
159    pub prefetch_cache_line_level: Option<PrefetchCacheLineLevel>,
160}