|
5 | 5 |
|
6 | 6 | use std::{num::NonZeroUsize, sync::Arc}; |
7 | 7 |
|
| 8 | +#[cfg(feature = "pipnn")] |
| 9 | +use diskann::graph::AdjacencyList; |
8 | 10 | use diskann::{ |
9 | 11 | error::DiskANNError::StartPointComputeError, |
10 | 12 | graph::{DiskANNIndex, StartPointStrategy}, |
@@ -170,10 +172,18 @@ where |
170 | 172 | .context("PiPNN cannot connect a start point to an empty dataset") |
171 | 173 | }) |
172 | 174 | .collect::<anyhow::Result<Vec<_>>>()?; |
173 | | - let start_neighbors: Vec<_> = start_sources |
| 175 | + let degree = graph.pruned_degree().get(); |
| 176 | + let start_neighbors = start_sources |
174 | 177 | .into_iter() |
175 | | - .map(|source| adjacency[source].clone()) |
176 | | - .collect(); |
| 178 | + .map(|source| { |
| 179 | + let source_id = u32::try_from(source).context("PiPNN start source exceeds u32::MAX")?; |
| 180 | + let mut neighbors = AdjacencyList::with_capacity(degree); |
| 181 | + neighbors.push(source_id); |
| 182 | + neighbors.extend_from_slice(&adjacency[source]); |
| 183 | + neighbors.truncate(degree); |
| 184 | + Ok(neighbors) |
| 185 | + }) |
| 186 | + .collect::<anyhow::Result<Vec<_>>>()?; |
177 | 187 | let batch_elapsed = started.elapsed(); |
178 | 188 |
|
179 | 189 | // Unlike incremental insertion, PiPNN finishes all batch-build scratch |
@@ -461,5 +471,15 @@ mod pipnn_tests { |
461 | 471 | .get_vector_sync(starts[0] as usize) |
462 | 472 | }; |
463 | 473 | assert_eq!(start, [0.0, 0.0]); |
| 474 | + let mut neighbors = AdjacencyList::new(); |
| 475 | + index |
| 476 | + .provider() |
| 477 | + .neighbors() |
| 478 | + .get_neighbors_sync(starts[0] as usize, &mut neighbors) |
| 479 | + .unwrap(); |
| 480 | + assert!( |
| 481 | + neighbors.contains(0), |
| 482 | + "start slot must enter the real graph" |
| 483 | + ); |
464 | 484 | } |
465 | 485 | } |
0 commit comments