pub mod anonymize;
pub mod buffered_update_bitslice;
pub mod error_logging;
pub mod flags;
pub mod macros;
pub mod memory_usage;
pub mod operation_error;
pub mod operation_time_statistics;
pub mod reciprocal_rank_fusion;
pub mod score_fusion;
pub mod utils;
pub mod validate_snapshot_archive;
pub mod vector_utils;
use std::sync::atomic::AtomicBool;
use crate::segment::common::operation_error::{OperationError, OperationResult};
use crate::segment::data_types::named_vectors::NamedVectors;
use crate::segment::data_types::vectors::{QueryVector, VectorRef};
use crate::segment::types::{SegmentConfig, SparseVectorDataConfig, VectorDataConfig, VectorName};
pub type Flusher = Box<dyn FnOnce() -> OperationResult<()> + Send>;
pub fn check_vector_name(
vector_name: &VectorName,
segment_config: &SegmentConfig,
) -> OperationResult<()> {
if get_vector_config_or_error(vector_name, segment_config).is_err() {
get_sparse_vector_config_or_error(vector_name, segment_config)?;
}
Ok(())
}
pub fn check_vector(
vector_name: &VectorName,
query_vector: &QueryVector,
segment_config: &SegmentConfig,
) -> OperationResult<()> {
let vector_config = get_vector_config_or_error(vector_name, segment_config);
if vector_config.is_ok() {
check_query_vector(query_vector, vector_config?)
} else {
let sparse_vector_config = get_sparse_vector_config_or_error(vector_name, segment_config)?;
check_query_sparse_vector(query_vector, sparse_vector_config)
}
}
fn check_query_vector(
query_vector: &QueryVector,
vector_config: &VectorDataConfig,
) -> OperationResult<()> {
match query_vector {
QueryVector::Nearest(vector) => {
check_vector_against_config(VectorRef::from(vector), vector_config)?
}
QueryVector::RecommendBestScore(reco_query)
| QueryVector::RecommendSumScores(reco_query) => {
reco_query.flat_iter().try_for_each(|vector| {
check_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
QueryVector::Discover(discover_query) => {
discover_query.flat_iter().try_for_each(|vector| {
check_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
QueryVector::Context(context_query) => {
context_query.flat_iter().try_for_each(|vector| {
check_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
QueryVector::FeedbackNaive(feedback_query) => {
feedback_query.flat_iter().try_for_each(|vector| {
check_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
}
Ok(())
}
fn check_query_sparse_vector(
query_vector: &QueryVector,
vector_config: &SparseVectorDataConfig,
) -> OperationResult<()> {
match query_vector {
QueryVector::Nearest(vector) => {
check_sparse_vector_against_config(VectorRef::from(vector), vector_config)?
}
QueryVector::RecommendBestScore(reco_query)
| QueryVector::RecommendSumScores(reco_query) => {
reco_query.flat_iter().try_for_each(|vector| {
check_sparse_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
QueryVector::Discover(discover_query) => {
discover_query.flat_iter().try_for_each(|vector| {
check_sparse_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
QueryVector::Context(context_query) => {
context_query.flat_iter().try_for_each(|vector| {
check_sparse_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
QueryVector::FeedbackNaive(feedback_query) => {
feedback_query.flat_iter().try_for_each(|vector| {
check_sparse_vector_against_config(VectorRef::from(vector), vector_config)
})?
}
}
Ok(())
}
pub fn check_query_vectors(
vector_name: &VectorName,
query_vectors: &[&QueryVector],
segment_config: &SegmentConfig,
) -> OperationResult<()> {
let vector_config = get_vector_config_or_error(vector_name, segment_config);
if let Ok(vector_config) = vector_config {
query_vectors
.iter()
.try_for_each(|qv| check_query_vector(qv, vector_config))?;
} else {
let sparse_vector_config = get_sparse_vector_config_or_error(vector_name, segment_config)?;
query_vectors
.iter()
.try_for_each(|qv| check_query_sparse_vector(qv, sparse_vector_config))?;
}
Ok(())
}
pub fn check_named_vectors(
vectors: &NamedVectors,
segment_config: &SegmentConfig,
) -> OperationResult<()> {
for (vector_name, vector_data) in vectors.iter() {
check_vector(vector_name, &vector_data.into(), segment_config)?;
}
Ok(())
}
fn get_vector_config_or_error<'a>(
vector_name: &VectorName,
segment_config: &'a SegmentConfig,
) -> OperationResult<&'a VectorDataConfig> {
segment_config
.vector_data
.get(vector_name)
.ok_or_else(|| OperationError::vector_name_not_exists(vector_name))
}
fn get_sparse_vector_config_or_error<'a>(
vector_name: &VectorName,
segment_config: &'a SegmentConfig,
) -> OperationResult<&'a SparseVectorDataConfig> {
segment_config
.sparse_vector_data
.get(vector_name)
.ok_or_else(|| OperationError::vector_name_not_exists(vector_name))
}
fn check_vector_against_config(
vector: VectorRef,
vector_config: &VectorDataConfig,
) -> OperationResult<()> {
match vector {
VectorRef::Dense(vector) => {
let dim = vector_config.size;
if vector.len() != dim {
return Err(OperationError::WrongVectorDimension {
expected_dim: dim,
received_dim: vector.len(),
});
}
Ok(())
}
VectorRef::Sparse(_) => Err(OperationError::WrongSparse),
VectorRef::MultiDense(multi_vector) => {
let dim = vector_config.size;
for vector in multi_vector.multi_vectors() {
if vector.len() != dim {
return Err(OperationError::WrongVectorDimension {
expected_dim: dim,
received_dim: vector.len(),
});
}
}
Ok(())
}
}
}
fn check_sparse_vector_against_config(
vector: VectorRef,
_vector_config: &SparseVectorDataConfig,
) -> OperationResult<()> {
match vector {
VectorRef::Dense(_) => Err(OperationError::WrongSparse),
VectorRef::Sparse(_vector) => Ok(()), VectorRef::MultiDense(_) => Err(OperationError::WrongMulti),
}
}
pub fn check_stopped(is_stopped: &AtomicBool) -> OperationResult<()> {
if is_stopped.load(std::sync::atomic::Ordering::Relaxed) {
return Err(OperationError::cancelled("Operation is stopped externally"));
}
Ok(())
}
pub const BYTES_IN_KB: usize = 1024;
pub const BYTES_IN_MB: usize = 1_048_576;