Train a PQ codec from a built HNSW index's live vectors.
(index: &HnswIndex, pq_m: usize)
| 84 | |
| 85 | /// Train a PQ codec from a built HNSW index's live vectors. |
| 86 | pub fn build_pq_for_index(index: &HnswIndex, pq_m: usize) -> Option<(PqCodec, Vec<u8>)> { |
| 87 | let dim = index.dim(); |
| 88 | if pq_m == 0 || !dim.is_multiple_of(pq_m) { |
| 89 | return None; |
| 90 | } |
| 91 | let n = index.len(); |
| 92 | let mut refs: Vec<Vec<f32>> = Vec::with_capacity(n); |
| 93 | for i in 0..n { |
| 94 | if !index.is_deleted(i as u32) |
| 95 | && let Some(v) = index.get_vector(i as u32) |
| 96 | { |
| 97 | refs.push(v.to_vec()); |
| 98 | } |
| 99 | } |
| 100 | if refs.is_empty() { |
| 101 | return None; |
| 102 | } |
| 103 | let refs_slices: Vec<&[f32]> = refs.iter().map(|v| v.as_slice()).collect(); |
| 104 | let k = 256usize.min(refs.len()); |
| 105 | let codec = PqCodec::train(&refs_slices, dim, pq_m, k, 20); |
| 106 | let codes = codec.encode_batch(&refs_slices).ok()?; |
| 107 | Some((codec, codes)) |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | // Keep the DEFAULT_SEAL_THRESHOLD import live when future refactors move |
nothing calls this directly
no test coverage detected