Converts raw embeddings into `IndexableEmbedding` i.e. ready to be indexed - with quantization performed and property values and metadata fields converted into appropriate types. If metadata filtering is supported for the collection, then one input raw embedding may result in multiple `IndexableEmbedding` instances.
(
collection: &Collection,
hnsw_index: &HNSWIndex,
quantization_metric: &RwLock<QuantizationMetric>,
raw_emb: &RawDenseVectorEmbedding,
)
| 627 | /// input raw embedding may result in multiple `IndexableEmbedding` |
| 628 | /// instances. |
| 629 | fn preprocess_embedding( |
| 630 | collection: &Collection, |
| 631 | hnsw_index: &HNSWIndex, |
| 632 | quantization_metric: &RwLock<QuantizationMetric>, |
| 633 | raw_emb: &RawDenseVectorEmbedding, |
| 634 | ) -> Result<Vec<IndexableEmbedding>, WaCustomError> { |
| 635 | let quantization = quantization_metric.read().unwrap(); |
| 636 | let quantized_vec = Arc::new(quantization.quantize( |
| 637 | &raw_emb.raw_vec, |
| 638 | *hnsw_index.storage_type.read().unwrap(), |
| 639 | *hnsw_index.values_range.read().unwrap(), |
| 640 | )?); |
| 641 | |
| 642 | let base_id = raw_emb.hash_vec; |
| 643 | |
| 644 | let metadata_schema = collection.meta.metadata_schema.as_ref(); |
| 645 | let prop_file = &hnsw_index.cache.prop_file; |
| 646 | |
| 647 | let embeddings = if raw_emb.is_pseudo { |
| 648 | let replicas = pseudo_metadata_replicas(metadata_schema.unwrap(), prop_file, &base_id)?; |
| 649 | let num_levels = hnsw_index.levels_prob.len() - 1; |
| 650 | let plp = pseudo_level_probs(num_levels as u8, replicas.len() as u16); |
| 651 | |
| 652 | // Find the pseudo root node so that we can reuse it's |
| 653 | // prop_value in rest of the pseudo nodes |
| 654 | let pseudo_root = hnsw_index.pseudo_root_vec.unwrap(); |
| 655 | let pseudo_root_lazy = unsafe { &*pseudo_root }.latest; |
| 656 | let pseudo_root_node = unsafe { &*pseudo_root_lazy }.try_get_data(&hnsw_index.cache)?; |
| 657 | |
| 658 | let mut embeddings: Vec<IndexableEmbedding> = vec![]; |
| 659 | for prop_metadata in replicas.into_iter() { |
| 660 | let emb = IndexableEmbedding { |
| 661 | prop_value: pseudo_root_node.prop_value.clone(), |
| 662 | prop_metadata: Some(Arc::new(prop_metadata)), |
| 663 | overridden_level_probs: Some(plp.clone()), |
| 664 | }; |
| 665 | embeddings.push(emb); |
| 666 | } |
| 667 | embeddings |
| 668 | } else { |
| 669 | // Write props to the prop file |
| 670 | let mut prop_file_guard = hnsw_index.cache.prop_file.write().unwrap(); |
| 671 | let location = write_prop_value_to_file(&base_id, &quantized_vec, &mut prop_file_guard) |
| 672 | .expect("failed to write prop"); |
| 673 | drop(prop_file_guard); |
| 674 | |
| 675 | let prop_value = Arc::new(NodePropValue { |
| 676 | id: base_id, |
| 677 | vec: quantized_vec.clone(), |
| 678 | location, |
| 679 | }); |
| 680 | |
| 681 | let metadata_replicas = prop_metadata_replicas( |
| 682 | collection.meta.metadata_schema.as_ref(), |
| 683 | raw_emb.raw_metadata.as_ref(), |
| 684 | &hnsw_index.cache.prop_file, |
| 685 | &base_id, |
| 686 | )?; |
no test coverage detected