use std::sync::Arc;
use arrow::datatypes::{DataType, Field, Schema};
use super::{NodeId, SchemaRef};
mod brute_force;
mod cagra;
mod common;
mod definition;
mod ivf_flat;
mod ivf_pq;
mod kmeans;
mod pairwise;
mod pca;
mod top_k;
pub use brute_force::VectorBruteForceKnnParams;
pub use cagra::{VectorCagraBuildAlgo, VectorCagraParams, VectorCagraSearchAlgo};
pub use common::{VectorDistanceMetric, VectorRelationBinding, VectorRowIdBinding};
pub use definition::{
CUVS_BRUTE_FORCE_KNN_FUNCTION, CUVS_CAGRA_FUNCTION, CUVS_IVF_FLAT_FUNCTION, CUVS_IVF_PQ_FUNCTION,
CUVS_KMEANS_FUNCTION, CUVS_OPERATION_REGISTRY, CUVS_PAIRWISE_DISTANCE_FUNCTION, CUVS_PCA_FUNCTION,
CUVS_TOP_K_FUNCTION, CuvsOperation, CuvsOperationDescriptor, CuvsOutputContract, CuvsRelationRole,
CuvsVectorElementSupport, VectorAlgorithm, canonicalize_cuvs_options,
};
pub use ivf_flat::VectorIvfFlatParams;
pub use ivf_pq::{VectorIvfPqCodebookKind, VectorIvfPqParams};
pub use kmeans::{VectorKMeansInit, VectorKMeansMetric, VectorKMeansParams};
pub use pairwise::VectorPairwiseDistanceParams;
pub use pca::{VectorPcaParams, VectorPcaSolver};
pub use top_k::VectorTopKParams;
#[derive(Debug, Clone, PartialEq)]
pub enum VectorAlgorithmParams {
BruteForceKnn(VectorBruteForceKnnParams),
IvfFlat(VectorIvfFlatParams),
IvfPq(VectorIvfPqParams),
Cagra(VectorCagraParams),
PairwiseDistance(VectorPairwiseDistanceParams),
TopK(VectorTopKParams),
KMeans(VectorKMeansParams),
Pca(VectorPcaParams),
}
impl VectorAlgorithmParams {
pub const fn supports_algorithm(&self, algorithm: VectorAlgorithm) -> bool {
matches!(
(self, algorithm),
(Self::BruteForceKnn(_), VectorAlgorithm::BruteForceKnn)
| (Self::IvfFlat(_), VectorAlgorithm::IvfFlat)
| (Self::IvfPq(_), VectorAlgorithm::IvfPq)
| (Self::Cagra(_), VectorAlgorithm::Cagra)
| (Self::PairwiseDistance(_), VectorAlgorithm::PairwiseDistance)
| (Self::TopK(_), VectorAlgorithm::TopK)
| (Self::KMeans(_), VectorAlgorithm::KMeans)
| (Self::Pca(_), VectorAlgorithm::Pca)
)
}
pub fn relation_bindings(&self) -> Box<dyn Iterator<Item = &VectorRelationBinding> + '_> {
match self {
Self::BruteForceKnn(params) => Box::new([¶ms.dataset, ¶ms.queries].into_iter()),
Self::IvfFlat(params) => Box::new([¶ms.dataset, ¶ms.queries].into_iter()),
Self::IvfPq(params) => Box::new([¶ms.dataset, ¶ms.queries].into_iter()),
Self::Cagra(params) => Box::new([¶ms.dataset, ¶ms.queries].into_iter()),
Self::PairwiseDistance(params) => Box::new([¶ms.x, ¶ms.y].into_iter()),
Self::TopK(params) => Box::new(std::iter::once(¶ms.input)),
Self::KMeans(params) => Box::new(std::iter::once(¶ms.input).chain(params.initial_centroids.iter())),
Self::Pca(params) => Box::new(std::iter::once(¶ms.input)),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct VectorAlgorithmSpec {
pub algorithm: VectorAlgorithm,
pub params: VectorAlgorithmParams,
pub output_schema: SchemaRef,
}
impl VectorAlgorithmSpec {
pub fn new(algorithm: VectorAlgorithm, params: VectorAlgorithmParams, output_schema: SchemaRef) -> Self {
assert!(params.supports_algorithm(algorithm), "vector algorithm and parameter variant must match");
Self { algorithm, params, output_schema }
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct VectorAlgorithmNode {
pub inputs: Vec<NodeId>,
pub spec: VectorAlgorithmSpec,
}
impl VectorAlgorithmNode {
pub fn output_schema(&self) -> &SchemaRef {
&self.spec.output_schema
}
}
pub fn vector_knn_output_schema(query_id_type: DataType, neighbor_id_type: DataType) -> SchemaRef {
Arc::new(Schema::new(vec![
Field::new("query_ordinal", DataType::UInt64, false),
Field::new("query_id", query_id_type, false),
Field::new("neighbor_ordinal", DataType::UInt64, false),
Field::new("neighbor_id", neighbor_id_type, false),
Field::new("rank", DataType::UInt32, false),
Field::new("distance", DataType::Float32, false),
]))
}
pub fn vector_pairwise_distance_output_schema(
x_id_type: DataType,
y_id_type: DataType,
distance_type: DataType,
) -> SchemaRef {
Arc::new(Schema::new(vec![
Field::new("x_ordinal", DataType::UInt64, false),
Field::new("x_id", x_id_type, false),
Field::new("y_ordinal", DataType::UInt64, false),
Field::new("y_id", y_id_type, false),
Field::new("distance", distance_type, false),
]))
}
pub fn vector_top_k_output_schema(id_type: DataType) -> SchemaRef {
Arc::new(Schema::new(vec![
Field::new("row_ordinal", DataType::UInt64, false),
Field::new("id", id_type, false),
Field::new("rank", DataType::UInt32, false),
Field::new("position", DataType::Int64, false),
Field::new("value", DataType::Float32, false),
]))
}
pub fn vector_kmeans_output_schema(row_id_type: DataType) -> SchemaRef {
Arc::new(Schema::new(vec![
Field::new("row_ordinal", DataType::UInt64, false),
Field::new("id", row_id_type, false),
Field::new("cluster_id", DataType::Int32, false),
]))
}
pub fn vector_pca_output_schema(row_id_type: DataType, n_components: usize) -> SchemaRef {
let mut fields = Vec::with_capacity(n_components.saturating_add(2));
fields.push(Field::new("row_ordinal", DataType::UInt64, false));
fields.push(Field::new("id", row_id_type, false));
fields.extend((0..n_components).map(|index| Field::new(format!("pc_{index}"), DataType::Float32, false)));
Arc::new(Schema::new(fields))
}