use ndarray::Array1;
use ndarray::Array2;
use rayon::prelude::*;
use crate::error::{Error, Result};
pub fn reconstruct_embeddings(
index: &crate::index::MmapIndex,
doc_ids: &[i64],
) -> Result<Vec<Array2<f32>>> {
let num_documents = index.num_documents();
for &doc_id in doc_ids {
if doc_id < 0 || doc_id as usize >= num_documents {
return Err(Error::Search(format!(
"Invalid document ID: {} (index has {} documents)",
doc_id, num_documents
)));
}
}
doc_ids
.par_iter()
.map(|&doc_id| {
let doc_id_usize = doc_id as usize;
let start = index.doc_offsets[doc_id_usize];
let end = index.doc_offsets[doc_id_usize + 1];
let doc_len = end - start;
if doc_len == 0 {
return Ok(Array2::zeros((0, index.embedding_dim())));
}
let codes_slice = index.mmap_codes.slice(start, end);
let residuals_view = index.mmap_residuals.slice_rows(start, end);
let codes: Array1<usize> = Array1::from_iter(codes_slice.iter().map(|&c| c as usize));
let residuals = residuals_view.to_owned();
index.codec.decompress(&residuals, &codes.view())
})
.collect()
}
pub fn reconstruct_single(index: &crate::index::MmapIndex, doc_id: i64) -> Result<Array2<f32>> {
let results = reconstruct_embeddings(index, &[doc_id])?;
Ok(results.into_iter().next().unwrap())
}
#[cfg(test)]
mod tests {
#[test]
fn test_reconstruct_embeddings_validates_ids() {
}
#[test]
fn test_empty_doc_ids() {
}
}