1#![allow(dead_code)]
16use anyhow::Result;
105
106pub mod adaptive_compression;
107pub mod adaptive_intelligent_caching;
108pub mod adaptive_recall_tuner;
109pub mod advanced_analytics;
110pub mod advanced_benchmarking;
111pub mod advanced_caching;
112pub mod advanced_caching_eviction;
113pub mod advanced_caching_multilevel;
114pub mod advanced_caching_worker;
115pub mod advanced_metrics;
116pub mod advanced_result_merging;
117pub mod automl_optimization;
118pub mod bench_metrics;
119pub mod bench_runner;
120pub mod bench_tests;
121pub mod benchmarking;
122pub mod cache_friendly_index;
123pub mod clustering;
124pub mod compaction;
125pub mod compression;
126pub mod compression_codecs;
127pub mod compression_io;
128#[cfg(test)]
129pub mod compression_tests;
130pub mod compression_types;
131#[cfg(feature = "content-processing")]
132pub mod content_processing;
133pub mod crash_recovery;
134pub mod cross_language_alignment;
135pub mod cross_modal_embeddings;
136pub mod delta_sync_store;
137pub mod diskann;
138pub mod distance_metrics;
139pub mod distributed;
140pub mod distributed_vector_search;
141pub mod dynamic_index_selector;
142pub mod embedding_pipeline;
143pub mod embeddings;
144pub mod enhanced_performance_monitoring;
145pub mod faiss_compatibility;
146pub mod faiss_gpu_integration;
147pub mod faiss_integration;
148pub mod faiss_migration_tools;
149pub mod faiss_native_integration;
150pub mod fault;
151pub mod federated_search;
152pub mod filtered_search;
153pub mod gnn_embeddings;
154pub mod gpu;
155pub mod gpu_benchmarks;
156pub mod gpu_hnsw_index;
157pub mod gpu_search_enhanced;
158pub mod graph_aware_search;
159pub mod graph_indices;
160pub mod hierarchical_similarity;
161pub mod hnsw;
162pub mod hnsw_persistence;
163pub mod huggingface;
164pub mod hybrid_fusion;
165pub mod hybrid_search;
166pub mod index;
167pub mod ivf;
168pub mod joint_embedding_spaces;
169pub mod joint_embedding_spaces_align;
170pub mod joint_embedding_spaces_aligner;
171pub mod joint_embedding_spaces_eval;
172#[cfg(test)]
173pub mod joint_embedding_spaces_tests;
174pub mod joint_embedding_spaces_transfer;
175pub mod joint_embedding_spaces_types;
176pub mod kg_embeddings;
177pub mod learned_index;
178pub mod lsh;
179pub mod mmap_advanced;
180pub mod mmap_index;
181pub mod multi_modal_search;
182pub mod multi_tenancy;
183pub mod nsg;
184pub mod opq;
185pub mod oxirs_arq_integration;
186pub mod performance_insights;
187pub mod persistence;
188pub mod personalized_search;
189pub mod pq;
190pub mod pq_index;
191pub mod pytorch;
192pub mod quantized_cache;
193pub mod quantum_search;
194pub mod query_planning;
195pub mod query_rewriter;
196pub mod random_utils;
197pub mod rdf_content_enhancement;
198pub mod rdf_integration;
199pub mod real_time_analytics;
200pub mod real_time_embedding_pipeline;
201pub mod real_time_updates;
202pub mod reranking;
203pub mod result_fusion;
204pub mod rta_aggregators;
205pub mod rta_engine;
206pub mod rta_tests;
207#[cfg(test)]
208mod score_contract_tests;
209pub mod similarity;
210pub mod sparql_integration;
211pub mod sparql_service_endpoint;
212pub mod sparse;
213pub mod sq;
214pub mod storage_optimizations;
215pub mod store_integration;
216pub(crate) mod store_integration_adapters;
217pub(crate) mod store_integration_sync;
218#[cfg(test)]
219mod store_integration_tests;
220pub mod store_integration_types;
221pub mod structured_vectors;
222pub mod tensorflow;
223pub mod tiering;
224pub mod tree_indices;
225pub mod tree_indices_balltree;
226pub mod tree_indices_covertree;
227pub mod tree_indices_kdtree;
228pub mod tree_indices_rptree;
229#[cfg(test)]
230mod tree_indices_tests;
231pub mod tree_indices_types;
232pub mod tree_indices_unified;
233pub mod tree_indices_vptree;
234pub mod validation;
235pub mod wal;
236pub mod word2vec;
237pub mod flat_ivf_index;
239
240pub mod lsh_index;
242
243pub mod ivfpq_index;
245
246pub mod hnsw_builder;
248
249pub mod product_search;
251
252pub mod quantizer;
254
255pub mod delta_encoder;
257
258pub mod embedding_similarity;
260
261pub mod hnsw_search;
263
264pub mod vector_cache;
266
267pub mod ann_benchmark;
269
270pub mod cluster_index;
273
274pub mod index_merger;
277
278pub mod approximate_counter;
280
281pub mod pq_encoder;
284
285#[cfg(feature = "python")]
287pub mod python_bindings;
288
289pub mod vector_index;
291
292pub mod vector_store;
294
295pub mod optimizer;
298
299pub mod index_dispatcher;
302
303pub use vector_index::{MemoryVectorIndex, VectorIndex};
305pub use vector_store::{
306 DocumentBatchProcessor, SearchOptions, SearchQuery, SearchType, VectorOperationResult,
307 VectorStore, VectorStoreConfig,
308};
309
310pub use adaptive_compression::{
312 AdaptiveCompressor, CompressionMetrics, CompressionPriorities, MultiLevelCompression,
313 VectorStats,
314};
315pub use adaptive_intelligent_caching::{
316 AccessPatternAnalyzer, AdaptiveIntelligentCache, CacheConfiguration, CacheOptimizer,
317 CachePerformanceMetrics, CacheTier, MLModels, PredictivePrefetcher,
318};
319pub use advanced_analytics::{
320 AnomalyDetection, AnomalyDetector, AnomalyType, ImplementationEffort,
321 OptimizationRecommendation, PerformanceTrends, Priority, QualityAspect, QualityRecommendation,
322 QueryAnalytics, QueryAnomaly, RecommendationType, VectorAnalyticsEngine,
323 VectorDistributionAnalysis, VectorQualityAssessment,
324};
325pub use advanced_benchmarking::{
326 AdvancedBenchmarkConfig, AdvancedBenchmarkResult, AdvancedBenchmarkSuite, AlgorithmParameters,
327 BenchmarkAlgorithm, BuildTimeMetrics, CacheMetrics, DatasetQualityMetrics, DatasetStatistics,
328 DistanceStatistics, EnhancedBenchmarkDataset, HyperparameterTuner, IndexSizeMetrics,
329 LatencyMetrics, MemoryMetrics, ObjectiveFunction, OptimizationStrategy,
330 ParallelBenchmarkConfig, ParameterSpace, ParameterType, ParameterValue, PerformanceMetrics,
331 PerformanceProfiler, QualityDegradation, QualityMetrics, ScalabilityMetrics,
332 StatisticalAnalyzer, StatisticalMetrics, ThroughputMetrics,
333};
334pub use advanced_caching::{
335 BackgroundCacheWorker, CacheAnalysisReport, CacheAnalyzer, CacheConfig, CacheEntry,
336 CacheInvalidator, CacheKey, CacheStats, CacheWarmer, EvictionPolicy, InvalidationStats,
337 MultiLevelCache, MultiLevelCacheStats,
338};
339pub use advanced_result_merging::{
340 AdvancedResultMerger, ConfidenceInterval, DiversityConfig, DiversityMetric, FusionStatistics,
341 MergedResult, RankFusionAlgorithm, RankingFactor, ResultExplanation, ResultMergingConfig,
342 ResultMetadata, ScoreCombinationStrategy, ScoreNormalizationMethod, ScoredResult,
343 SourceContribution, SourceResult, SourceType,
344};
345pub use automl_optimization::{
346 AutoMLConfig, AutoMLOptimizer, AutoMLResults, AutoMLStatistics, IndexConfiguration,
347 IndexParameterSpace, OptimizationMetric, OptimizationTrial, ResourceConstraints, SearchSpace,
348 TrialResult,
349};
350pub use benchmarking::{
351 BenchmarkConfig, BenchmarkDataset, BenchmarkOutputFormat, BenchmarkResult, BenchmarkRunner,
352 BenchmarkSuite, BenchmarkTestCase, MemoryMetrics as BenchmarkMemoryMetrics,
353 PerformanceMetrics as BenchmarkPerformanceMetrics, QualityMetrics as BenchmarkQualityMetrics,
354 ScalabilityMetrics as BenchmarkScalabilityMetrics, SystemInfo,
355};
356pub use cache_friendly_index::{CacheFriendlyVectorIndex, IndexConfig as CacheFriendlyIndexConfig};
357pub use compaction::{
358 CompactionConfig, CompactionManager, CompactionMetrics, CompactionResult, CompactionState,
359 CompactionStatistics, CompactionStrategy,
360};
361pub use compression::{create_compressor, CompressionMethod, VectorCompressor};
362#[cfg(feature = "content-processing")]
363pub use content_processing::{
364 ChunkType, ChunkingStrategy, ContentChunk, ContentExtractionConfig, ContentLocation,
365 ContentProcessor, DocumentFormat, DocumentStructure, ExtractedContent, ExtractedImage,
366 ExtractedLink, ExtractedTable, FormatHandler, Heading, ProcessingStats, TocEntry,
367};
368pub use crash_recovery::{CrashRecoveryManager, RecoveryConfig, RecoveryPolicy, RecoveryStats};
369pub use cross_modal_embeddings::{
370 AttentionMechanism, AudioData, AudioEncoder, CrossModalConfig, CrossModalEncoder, FusionLayer,
371 FusionStrategy, GraphData, GraphEncoder, ImageData, ImageEncoder, Modality, ModalityData,
372 MultiModalContent, TextEncoder, VideoData, VideoEncoder,
373};
374pub use diskann::{
375 DiskAnnBuildStats, DiskAnnBuilder, DiskAnnConfig, DiskAnnError, DiskAnnIndex, DiskAnnResult,
376 DiskStorage, IndexMetadata as DiskAnnIndexMetadata, MemoryMappedStorage, NodeId,
377 PruningStrategy, SearchMode as DiskAnnSearchMode, SearchStats as DiskAnnSearchStats,
378 StorageBackend, VamanaGraph, VamanaNode, VectorId as DiskAnnVectorId,
379};
380pub use distributed::{
381 AppendEntriesRequest,
383 AppendEntriesResponse,
384 ClusterSimulator,
385 ConflictRecord,
387 ConflictResolutionStrategy,
388 CrossDcConfig,
389 CrossDcCoordinator,
390 CrossDcStats,
391 IndexCommand,
392 NodeId as RaftNodeId,
393 NodeRole,
394 PrimaryDcManager,
395 RaftConfig,
396 RaftIndexNode,
397 RaftStats,
398 ReplicaDcManager,
399 ReplicaStatus,
400 ReplicationEntry,
401 ReplicationHealth,
402 ReplicationOperation,
403 ReplicationSeq,
404 RequestVoteRequest,
405 RequestVoteResponse,
406 Term,
407 VectorEntry as RaftVectorEntry,
408};
409pub use distributed_vector_search::{
410 ConsistencyLevel, DistributedClusterStats, DistributedNodeConfig, DistributedQuery,
411 DistributedSearchResponse, DistributedVectorSearch, LoadBalancingAlgorithm, NodeHealthStatus,
412 PartitioningStrategy, QueryExecutionStrategy,
413};
414pub use dynamic_index_selector::{DynamicIndexSelector, IndexSelectorConfig};
415pub use embedding_pipeline::{
416 DimensionalityReduction, EmbeddingPipeline, NormalizationConfig, PostprocessingPipeline,
417 PreprocessingPipeline, TokenizerConfig, VectorNormalization,
418};
419pub use embeddings::{
420 EmbeddableContent, EmbeddingConfig, EmbeddingManager, EmbeddingStrategy, ModelDetails,
421 OpenAIConfig, OpenAIEmbeddingGenerator, SentenceTransformerGenerator, TransformerModelType,
422};
423pub use enhanced_performance_monitoring::{
424 Alert, AlertManager, AlertSeverity, AlertThresholds, AlertType, AnalyticsEngine,
425 AnalyticsReport, DashboardData, EnhancedPerformanceMonitor, ExportConfig, ExportDestination,
426 ExportFormat, LatencyDistribution, MonitoringConfig as EnhancedMonitoringConfig,
427 QualityMetrics as EnhancedQualityMetrics, QualityMetricsCollector, QualityStatistics,
428 QueryInfo, QueryMetricsCollector, QueryStatistics, QueryType, Recommendation,
429 RecommendationCategory, RecommendationPriority, SystemMetrics, SystemMetricsCollector,
430 SystemStatistics, TrendData, TrendDirection,
431};
432pub use faiss_compatibility::{
433 CompressionLevel, ConversionMetrics, ConversionResult, FaissCompatibility, FaissExportConfig,
434 FaissImportConfig, FaissIndexMetadata, FaissIndexType, FaissMetricType, FaissParameter,
435 SimpleVectorIndex,
436};
437pub use federated_search::{
438 AuthenticationConfig, FederatedSearchConfig, FederatedVectorSearch, FederationEndpoint,
439 PrivacyEngine, PrivacyMode, SchemaCompatibility, TrustManager,
440};
441pub use gnn_embeddings::{AggregatorType, GraphSAGE, GCN};
442pub use gpu::{
443 create_default_accelerator,
444 create_memory_optimized_accelerator,
445 create_performance_accelerator,
446 is_gpu_available,
447 GpuAccelerator,
448 GpuBatchDistanceComputer,
450 GpuBuffer,
451 GpuConfig,
452 GpuDevice,
453 GpuDeviceMetrics,
455 GpuDistanceMetric,
456 GpuExecutionConfig,
457 GpuHnswIndexBuilder,
458 GpuIndexBuildStats,
459 GpuIndexBuilderConfig,
460 GpuTaskOutput,
461 GpuTaskResult,
462 HnswGraph,
463 HnswNode,
464 IncrementalGpuIndexBuilder,
465 LoadBalancingStrategy,
466 MultiGpuConfig,
467 MultiGpuConfigFactory,
468 MultiGpuManager,
469 MultiGpuStats,
470 MultiGpuTask,
471 TaskPriority,
472};
473pub use gpu_benchmarks::{
474 BenchmarkResult as GpuBenchmarkResult, GpuBenchmarkConfig, GpuBenchmarkSuite,
475};
476pub use gpu_search_enhanced::{BatchSearchEngine, SearchMetrics, SimdVectorSearch};
477pub use graph_indices::{
478 DelaunayGraph, GraphIndex, GraphIndexConfig, GraphType, NSWGraph, ONNGGraph, PANNGGraph,
479 RNGGraph,
480};
481pub use hierarchical_similarity::{
482 ConceptHierarchy, HierarchicalSimilarity, HierarchicalSimilarityConfig,
483 HierarchicalSimilarityResult, HierarchicalSimilarityStats, SimilarityContext,
484 SimilarityExplanation, SimilarityTaskType,
485};
486pub use hnsw::{HnswConfig, HnswIndex};
487pub use hybrid_fusion::{
488 FusedResult, HybridFusion, HybridFusionConfig, HybridFusionStatistics, HybridFusionStrategy,
489 NormalizationMethod,
490};
491pub use hybrid_search::{
492 Bm25Scorer, DocumentScore, HybridQuery, HybridResult, HybridSearchConfig, HybridSearchManager,
493 KeywordAlgorithm, KeywordMatch, KeywordSearcher, QueryExpander, RankFusion, RankFusionStrategy,
494 SearchMode, SearchWeights, TfidfScorer,
495};
496
497#[cfg(feature = "tantivy-search")]
498pub use hybrid_search::{
499 IndexStats, RdfDocument, TantivyConfig, TantivySearchResult, TantivySearcher,
500};
501pub use index::{AdvancedVectorIndex, DistanceMetric, IndexConfig, IndexType, SearchResult};
502pub use ivf::{IvfConfig, IvfIndex, IvfStats, QuantizationStrategy};
503pub use joint_embedding_spaces::{
504 ActivationFunction, AlignmentPair, CLIPAligner, ContrastiveOptimizer, CrossModalAttention,
505 CurriculumLearning, DataAugmentation, DifficultySchedule, DomainAdapter, DomainStatistics,
506 JointEmbeddingConfig, JointEmbeddingSpace, LearningRateSchedule, LinearProjector,
507 PacingFunction, ScheduleType, TemperatureScheduler, TrainingStatistics,
508};
509pub use kg_embeddings::{
510 ComplEx, KGEmbedding, KGEmbeddingConfig, KGEmbeddingModel as KGModel, KGEmbeddingModelType,
511 RotatE, TransE, Triple,
512};
513pub use lsh::{LshConfig, LshFamily, LshIndex, LshStats};
514pub use mmap_index::{MemoryMappedIndexStats, MemoryMappedVectorIndex};
515pub use multi_tenancy::{
516 AccessControl, AccessPolicy, AdmissionController, AdmissionError, BillingEngine,
517 BillingMetrics, BillingPeriod, IsolationLevel, IsolationStrategy, MultiTenancyError,
518 MultiTenancyResult, MultiTenantManager, NamespaceManager, Permission, PricingModel,
519 PrioritizedQuery, QuotaEnforcer, QuotaLimits, QuotaUsage, RateLimiter, ResourceQuota,
520 ResourceType, Role, SlaClass, SlaQueryDispatcher, SlaThresholds, Tenant, TenantConfig,
521 TenantContext, TenantId, TenantManagerConfig, TenantMetadata, TenantOperation,
522 TenantStatistics, TenantStatus, UsageRecord,
523};
524pub use nsg::{DistanceMetric as NsgDistanceMetric, NsgConfig, NsgIndex, NsgStats};
525pub use performance_insights::{
526 AlertingSystem, OptimizationRecommendations, PerformanceInsightsAnalyzer,
527 PerformanceTrends as InsightsPerformanceTrends, QueryComplexity,
528 QueryStatistics as InsightsQueryStatistics, ReportFormat, VectorStatistics,
529};
530pub use persistence::{
531 apply_wal_entry, restore_to_timestamp, CheckpointRef, PointInTimeRestore, RestoreReport,
532};
533pub use pq::{PQConfig, PQIndex, PQStats};
534pub use pytorch::{
535 ArchitectureType, CompileMode, DeviceManager, PyTorchConfig, PyTorchDevice, PyTorchEmbedder,
536 PyTorchModelManager, PyTorchModelMetadata, PyTorchTokenizer,
537};
538pub use quantum_search::{
539 QuantumSearchConfig, QuantumSearchResult, QuantumSearchStatistics, QuantumState,
540 QuantumVectorSearch,
541};
542pub use query_planning::{
543 CostModel, IndexStatistics, QueryCharacteristics, QueryPlan, QueryPlanner, QueryStrategy,
544 VectorQueryType,
545};
546pub use query_rewriter::{
547 QueryRewriter, QueryRewriterConfig, QueryVectorStatistics, RewriteRule, RewrittenQuery,
548};
549pub use rdf_content_enhancement::{
550 ComponentWeights, MultiLanguageProcessor, PathConstraint, PathDirection, PropertyAggregator,
551 PropertyPath, RdfContentConfig, RdfContentProcessor, RdfContext, RdfEntity, RdfValue,
552 TemporalInfo,
553};
554pub use rdf_integration::{
555 RdfIntegrationStats, RdfTermMapping, RdfTermMetadata, RdfTermType, RdfVectorConfig,
556 RdfVectorIntegration, RdfVectorSearchResult, SearchMetadata,
557};
558pub use real_time_analytics::{
559 AlertSeverity as AnalyticsAlertSeverity, AlertType as AnalyticsAlertType, AnalyticsConfig,
560 AnalyticsEvent, AnalyticsReport as RealTimeAnalyticsReport,
561 DashboardData as RealTimeDashboardData, ExportFormat as AnalyticsExportFormat,
562 MetricsCollector, PerformanceMonitor, QueryMetrics, SystemMetrics as AnalyticsSystemMetrics,
563 VectorAnalyticsEngine as RealTimeVectorAnalyticsEngine,
564};
565pub use real_time_embedding_pipeline::{
566 AlertThresholds as PipelineAlertThresholds, AutoScalingConfig, CompressionConfig, ContentItem,
567 MonitoringConfig as PipelineMonitoringConfig, PipelineConfig as RealTimeEmbeddingConfig,
568 PipelineStatistics as PipelineStats, ProcessingPriority, ProcessingResult, ProcessingStatus,
569 RealTimeEmbeddingPipeline, VersioningStrategy,
570};
571pub use real_time_updates::{
572 BatchProcessor, RealTimeConfig, RealTimeVectorSearch, RealTimeVectorUpdater, UpdateBatch,
573 UpdateOperation, UpdatePriority, UpdateStats,
574};
575pub use reranking::{
576 CrossEncoder, CrossEncoderBackend, CrossEncoderModel, CrossEncoderReranker, DiversityReranker,
577 DiversityStrategy, FusionStrategy as RerankingFusionStrategy, ModelBackend, ModelConfig,
578 RerankingCache, RerankingCacheConfig, RerankingConfig, RerankingError, RerankingMode,
579 RerankingOutput, RerankingStats, Result as RerankingResult, ScoreFusion, ScoreFusionConfig,
580 ScoredCandidate,
581};
582pub use result_fusion::{
583 FusedResults, FusionAlgorithm, FusionConfig, FusionQualityMetrics, FusionStats,
584 ResultFusionEngine, ScoreNormalizationStrategy, SourceResults, VectorSearchResult,
585};
586pub use similarity::{AdaptiveSimilarity, SemanticSimilarity, SimilarityConfig, SimilarityMetric};
587pub use sparql_integration::{
588 CrossLanguageProcessor, FederatedQueryResult, QueryExecutor, SparqlVectorFunctions,
589 SparqlVectorService, VectorOperation, VectorQuery, VectorQueryResult, VectorServiceArg,
590 VectorServiceConfig, VectorServiceResult,
591};
592
593#[cfg(feature = "tantivy-search")]
594pub use sparql_integration::{RdfLiteral, SearchStats, SparqlSearchResult, SparqlTextFunctions};
595pub use sparql_service_endpoint::{
596 AuthenticationInfo, AuthenticationType, CustomFunctionRegistry, FederatedOperation,
597 FederatedSearchResult, FederatedServiceEndpoint, FederatedVectorQuery, FunctionMetadata,
598 LoadBalancer, ParameterInfo, ParameterType as ServiceParameterType, PartialSearchResult,
599 QueryScope, ReturnType, ServiceCapability, ServiceEndpointManager, ServiceType,
600};
601pub use sparse::{COOMatrix, CSRMatrix, SparseVector};
602pub use sq::{QuantizationMode, QuantizationParams, SqConfig, SqIndex, SqStats};
603pub use storage_optimizations::{
604 CompressionType, MmapVectorFile, StorageConfig, StorageUtils, VectorBlock, VectorFileHeader,
605 VectorReader, VectorWriter,
606};
607pub use structured_vectors::{
608 ConfidenceScoredVector, HierarchicalVector, NamedDimensionVector, TemporalVector,
609 WeightedDimensionVector,
610};
611pub use tensorflow::{
612 OptimizationLevel, PreprocessingPipeline as TensorFlowPreprocessingPipeline, ServerConfig,
613 SessionConfig, TensorDataType, TensorFlowConfig, TensorFlowDevice, TensorFlowEmbedder,
614 TensorFlowModelInfo, TensorFlowModelServer, TensorSpec,
615};
616pub use tiering::{
617 IndexMetadata, StorageTier, TierMetrics, TierStatistics, TierTransitionReason, TieringConfig,
618 TieringManager, TieringPolicy,
619};
620pub use tree_indices::{
621 BallTree, CoverTree, KdTree, RandomProjectionTree, TreeIndex, TreeIndexConfig, TreeType, VpTree,
622};
623pub use wal::{WalConfig, WalEntry, WalManager};
624pub use word2vec::{
625 AggregationMethod, OovStrategy, Word2VecConfig, Word2VecEmbeddingGenerator, Word2VecFormat,
626};
627
628pub use index_dispatcher::{DispatchedSearch, IndexDispatcher, IndexDispatcherConfig};
630pub use optimizer::{
631 CostEstimate, CostModel as OptimizerCostModel, CostWeights, DispatchError, DispatchPlan,
632 DispatcherConfig as OptimizerDispatcherConfig, FamilyStats, IndexFamily, IndexParameters,
633 OptimizerDispatcher, QueryObservation, QueryStats, WorkloadProfile,
634};
635
636pub type VectorId = String;
638
639pub type BatchSearchResult = Vec<Result<Vec<(String, f32)>>>;
641
642pub trait VectorStoreTrait: Send + Sync {
644 fn insert_vector(&mut self, id: VectorId, vector: Vector) -> Result<()>;
646
647 fn add_vector(&mut self, vector: Vector) -> Result<VectorId>;
649
650 fn get_vector(&self, id: &VectorId) -> Result<Option<Vector>>;
652
653 fn get_all_vector_ids(&self) -> Result<Vec<VectorId>>;
655
656 fn search_similar(&self, query: &Vector, k: usize) -> Result<Vec<(VectorId, f32)>>;
658
659 fn remove_vector(&mut self, id: &VectorId) -> Result<bool>;
661
662 fn len(&self) -> usize;
664
665 fn is_empty(&self) -> bool {
667 self.len() == 0
668 }
669}
670
671#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
673pub enum VectorPrecision {
674 F32,
675 F64,
676 F16,
677 I8,
678 Binary,
679}
680
681#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
683pub struct Vector {
684 pub dimensions: usize,
685 pub precision: VectorPrecision,
686 pub values: VectorData,
687 pub metadata: Option<std::collections::HashMap<String, String>>,
688}
689
690#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
692pub enum VectorData {
693 F32(Vec<f32>),
694 F64(Vec<f64>),
695 F16(Vec<u16>), I8(Vec<i8>),
697 Binary(Vec<u8>), }
699
700impl Vector {
701 pub fn new(values: Vec<f32>) -> Self {
703 let dimensions = values.len();
704 Self {
705 dimensions,
706 precision: VectorPrecision::F32,
707 values: VectorData::F32(values),
708 metadata: None,
709 }
710 }
711
712 pub fn with_precision(values: VectorData) -> Self {
714 let (dimensions, precision) = match &values {
715 VectorData::F32(v) => (v.len(), VectorPrecision::F32),
716 VectorData::F64(v) => (v.len(), VectorPrecision::F64),
717 VectorData::F16(v) => (v.len(), VectorPrecision::F16),
718 VectorData::I8(v) => (v.len(), VectorPrecision::I8),
719 VectorData::Binary(v) => (v.len() * 8, VectorPrecision::Binary), };
721
722 Self {
723 dimensions,
724 precision,
725 values,
726 metadata: None,
727 }
728 }
729
730 pub fn with_metadata(
732 values: Vec<f32>,
733 metadata: std::collections::HashMap<String, String>,
734 ) -> Self {
735 let dimensions = values.len();
736 Self {
737 dimensions,
738 precision: VectorPrecision::F32,
739 values: VectorData::F32(values),
740 metadata: Some(metadata),
741 }
742 }
743
744 pub fn f64(values: Vec<f64>) -> Self {
746 Self::with_precision(VectorData::F64(values))
747 }
748
749 pub fn f16(values: Vec<u16>) -> Self {
751 Self::with_precision(VectorData::F16(values))
752 }
753
754 pub fn i8(values: Vec<i8>) -> Self {
756 Self::with_precision(VectorData::I8(values))
757 }
758
759 pub fn binary(values: Vec<u8>) -> Self {
761 Self::with_precision(VectorData::Binary(values))
762 }
763
764 pub fn as_f32(&self) -> Vec<f32> {
766 match &self.values {
767 VectorData::F32(v) => v.clone(),
768 VectorData::F64(v) => v.iter().map(|&x| x as f32).collect(),
769 VectorData::F16(v) => v.iter().map(|&x| Self::f16_to_f32(x)).collect(),
770 VectorData::I8(v) => v.iter().map(|&x| x as f32 / 128.0).collect(), VectorData::Binary(v) => {
772 let mut result = Vec::new();
773 for &byte in v {
774 for bit in 0..8 {
775 result.push(if (byte >> bit) & 1 == 1 { 1.0 } else { 0.0 });
776 }
777 }
778 result
779 }
780 }
781 }
782
783 #[allow(dead_code)]
785 fn f32_to_f16(value: f32) -> u16 {
786 let bits = value.to_bits();
788 let sign = (bits >> 31) & 0x1;
789 let exp = ((bits >> 23) & 0xff) as i32;
790 let mantissa = bits & 0x7fffff;
791
792 let f16_exp = if exp == 0 {
794 0
795 } else {
796 (exp - 127 + 15).clamp(0, 31) as u16
797 };
798
799 let f16_mantissa = (mantissa >> 13) as u16;
800 ((sign as u16) << 15) | (f16_exp << 10) | f16_mantissa
801 }
802
803 fn f16_to_f32(value: u16) -> f32 {
805 let sign = (value >> 15) & 0x1;
807 let exp = ((value >> 10) & 0x1f) as i32;
808 let mantissa = value & 0x3ff;
809
810 if exp == 0 {
811 if mantissa == 0 {
812 if sign == 1 {
813 -0.0
814 } else {
815 0.0
816 }
817 } else {
818 let f32_exp = -14 - 127;
820 let f32_mantissa = (mantissa as u32) << 13;
821 f32::from_bits(((sign as u32) << 31) | ((f32_exp as u32) << 23) | f32_mantissa)
822 }
823 } else {
824 let f32_exp = exp - 15 + 127;
825 let f32_mantissa = (mantissa as u32) << 13;
826 f32::from_bits(((sign as u32) << 31) | ((f32_exp as u32) << 23) | f32_mantissa)
827 }
828 }
829
830 pub fn quantize_to_i8(values: &[f32]) -> Vec<i8> {
832 let min_val = values.iter().fold(f32::INFINITY, |a, &b| a.min(b));
834 let max_val = values.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
835 let range = max_val - min_val;
836
837 if range == 0.0 {
838 vec![0; values.len()]
839 } else {
840 values
841 .iter()
842 .map(|&x| {
843 let normalized = (x - min_val) / range; let scaled = normalized * 254.0 - 127.0; scaled.round().clamp(-127.0, 127.0) as i8
846 })
847 .collect()
848 }
849 }
850
851 pub fn to_binary(values: &[f32], threshold: f32) -> Vec<u8> {
853 let mut binary = Vec::new();
854 let mut current_byte = 0u8;
855 let mut bit_position = 0;
856
857 for &value in values {
858 if value > threshold {
859 current_byte |= 1 << bit_position;
860 }
861
862 bit_position += 1;
863 if bit_position == 8 {
864 binary.push(current_byte);
865 current_byte = 0;
866 bit_position = 0;
867 }
868 }
869
870 if bit_position > 0 {
872 binary.push(current_byte);
873 }
874
875 binary
876 }
877
878 pub fn cosine_similarity(&self, other: &Vector) -> Result<f32> {
880 if self.dimensions != other.dimensions {
881 return Err(anyhow::anyhow!("Vector dimensions must match"));
882 }
883
884 let self_f32 = self.as_f32();
885 let other_f32 = other.as_f32();
886
887 let dot_product: f32 = self_f32.iter().zip(&other_f32).map(|(a, b)| a * b).sum();
888
889 let magnitude_self: f32 = self_f32.iter().map(|x| x * x).sum::<f32>().sqrt();
890 let magnitude_other: f32 = other_f32.iter().map(|x| x * x).sum::<f32>().sqrt();
891
892 if magnitude_self == 0.0 || magnitude_other == 0.0 {
893 return Ok(0.0);
894 }
895
896 Ok(dot_product / (magnitude_self * magnitude_other))
897 }
898
899 pub fn euclidean_distance(&self, other: &Vector) -> Result<f32> {
901 if self.dimensions != other.dimensions {
902 return Err(anyhow::anyhow!("Vector dimensions must match"));
903 }
904
905 let self_f32 = self.as_f32();
906 let other_f32 = other.as_f32();
907
908 let distance = self_f32
909 .iter()
910 .zip(&other_f32)
911 .map(|(a, b)| (a - b).powi(2))
912 .sum::<f32>()
913 .sqrt();
914
915 Ok(distance)
916 }
917
918 pub fn manhattan_distance(&self, other: &Vector) -> Result<f32> {
920 if self.dimensions != other.dimensions {
921 return Err(anyhow::anyhow!("Vector dimensions must match"));
922 }
923
924 let self_f32 = self.as_f32();
925 let other_f32 = other.as_f32();
926
927 let distance = self_f32
928 .iter()
929 .zip(&other_f32)
930 .map(|(a, b)| (a - b).abs())
931 .sum();
932
933 Ok(distance)
934 }
935
936 pub fn minkowski_distance(&self, other: &Vector, p: f32) -> Result<f32> {
938 if self.dimensions != other.dimensions {
939 return Err(anyhow::anyhow!("Vector dimensions must match"));
940 }
941
942 if p <= 0.0 {
943 return Err(anyhow::anyhow!("p must be positive"));
944 }
945
946 let self_f32 = self.as_f32();
947 let other_f32 = other.as_f32();
948
949 if p == f32::INFINITY {
950 return self.chebyshev_distance(other);
952 }
953
954 let distance = self_f32
955 .iter()
956 .zip(&other_f32)
957 .map(|(a, b)| (a - b).abs().powf(p))
958 .sum::<f32>()
959 .powf(1.0 / p);
960
961 Ok(distance)
962 }
963
964 pub fn chebyshev_distance(&self, other: &Vector) -> Result<f32> {
966 if self.dimensions != other.dimensions {
967 return Err(anyhow::anyhow!("Vector dimensions must match"));
968 }
969
970 let self_f32 = self.as_f32();
971 let other_f32 = other.as_f32();
972
973 let distance = self_f32
974 .iter()
975 .zip(&other_f32)
976 .map(|(a, b)| (a - b).abs())
977 .fold(0.0f32, |max, val| max.max(val));
978
979 Ok(distance)
980 }
981
982 pub fn magnitude(&self) -> f32 {
984 let values = self.as_f32();
985 values.iter().map(|x| x * x).sum::<f32>().sqrt()
986 }
987
988 pub fn normalize(&mut self) {
990 let mag = self.magnitude();
991 if mag > 0.0 {
992 match &mut self.values {
993 VectorData::F32(values) => {
994 for value in values {
995 *value /= mag;
996 }
997 }
998 VectorData::F64(values) => {
999 let mag_f64 = mag as f64;
1000 for value in values {
1001 *value /= mag_f64;
1002 }
1003 }
1004 _ => {
1005 let mut f32_values = self.as_f32();
1007 for value in &mut f32_values {
1008 *value /= mag;
1009 }
1010 self.values = VectorData::F32(f32_values);
1011 self.precision = VectorPrecision::F32;
1012 }
1013 }
1014 }
1015 }
1016
1017 pub fn normalized(&self) -> Vector {
1019 let mut normalized = self.clone();
1020 normalized.normalize();
1021 normalized
1022 }
1023
1024 pub fn add(&self, other: &Vector) -> Result<Vector> {
1026 if self.dimensions != other.dimensions {
1027 return Err(anyhow::anyhow!("Vector dimensions must match"));
1028 }
1029
1030 let self_f32 = self.as_f32();
1031 let other_f32 = other.as_f32();
1032
1033 let result_values: Vec<f32> = self_f32
1034 .iter()
1035 .zip(&other_f32)
1036 .map(|(a, b)| a + b)
1037 .collect();
1038
1039 Ok(Vector::new(result_values))
1040 }
1041
1042 pub fn subtract(&self, other: &Vector) -> Result<Vector> {
1044 if self.dimensions != other.dimensions {
1045 return Err(anyhow::anyhow!("Vector dimensions must match"));
1046 }
1047
1048 let self_f32 = self.as_f32();
1049 let other_f32 = other.as_f32();
1050
1051 let result_values: Vec<f32> = self_f32
1052 .iter()
1053 .zip(&other_f32)
1054 .map(|(a, b)| a - b)
1055 .collect();
1056
1057 Ok(Vector::new(result_values))
1058 }
1059
1060 pub fn scale(&self, scalar: f32) -> Vector {
1062 let values = self.as_f32();
1063 let scaled_values: Vec<f32> = values.iter().map(|x| x * scalar).collect();
1064
1065 Vector::new(scaled_values)
1066 }
1067
1068 pub fn len(&self) -> usize {
1070 self.dimensions
1071 }
1072
1073 pub fn is_empty(&self) -> bool {
1075 self.dimensions == 0
1076 }
1077
1078 pub fn as_slice(&self) -> Vec<f32> {
1080 self.as_f32()
1081 }
1082}
1083
1084#[derive(Debug, thiserror::Error)]
1086pub enum VectorError {
1087 #[error("Dimension mismatch: expected {expected}, got {actual}")]
1088 DimensionMismatch { expected: usize, actual: usize },
1089
1090 #[error("Empty vector")]
1091 EmptyVector,
1092
1093 #[error("Index not built")]
1094 IndexNotBuilt,
1095
1096 #[error("Embedding generation failed: {message}")]
1097 EmbeddingError { message: String },
1098
1099 #[error("SPARQL service error: {message}")]
1100 SparqlServiceError { message: String },
1101
1102 #[error("Compression error: {0}")]
1103 CompressionError(String),
1104
1105 #[error("Invalid dimensions: {0}")]
1106 InvalidDimensions(String),
1107
1108 #[error("Unsupported operation: {0}")]
1109 UnsupportedOperation(String),
1110
1111 #[error("Invalid data: {0}")]
1112 InvalidData(String),
1113
1114 #[error("IO error: {0}")]
1115 IoError(#[from] std::io::Error),
1116}
1117
1118pub mod utils {
1120 use super::Vector;
1121
1122 pub fn centroid(vectors: &[Vector]) -> Option<Vector> {
1124 if vectors.is_empty() {
1125 return None;
1126 }
1127
1128 let dimensions = vectors[0].dimensions;
1129 let mut sum_values = vec![0.0; dimensions];
1130
1131 for vector in vectors {
1132 if vector.dimensions != dimensions {
1133 return None; }
1135
1136 let vector_f32 = vector.as_f32();
1137 for (i, &value) in vector_f32.iter().enumerate() {
1138 sum_values[i] += value;
1139 }
1140 }
1141
1142 let count = vectors.len() as f32;
1143 for value in &mut sum_values {
1144 *value /= count;
1145 }
1146
1147 Some(Vector::new(sum_values))
1148 }
1149
1150 pub fn random_vector(dimensions: usize, seed: Option<u64>) -> Vector {
1152 use std::collections::hash_map::DefaultHasher;
1153 use std::hash::{Hash, Hasher};
1154
1155 let mut hasher = DefaultHasher::new();
1156 seed.unwrap_or(42).hash(&mut hasher);
1157 let mut rng_state = hasher.finish();
1158
1159 let mut values = Vec::with_capacity(dimensions);
1160 for _ in 0..dimensions {
1161 rng_state = rng_state.wrapping_mul(1103515245).wrapping_add(12345);
1162 let normalized = (rng_state as f32) / (u64::MAX as f32);
1163 values.push((normalized - 0.5) * 2.0); }
1165
1166 Vector::new(values)
1167 }
1168
1169 pub fn normalize_vector(vector: &Vector) -> Vector {
1171 vector.normalized()
1172 }
1173}
1174
1175#[cfg(test)]
1176mod tests {
1177 use super::*;
1178 use crate::similarity::SimilarityMetric;
1179
1180 #[test]
1181 fn test_vector_creation() {
1182 let values = vec![1.0, 2.0, 3.0];
1183 let vector = Vector::new(values.clone());
1184
1185 assert_eq!(vector.dimensions, 3);
1186 assert_eq!(vector.precision, VectorPrecision::F32);
1187 assert_eq!(vector.as_f32(), values);
1188 }
1189
1190 #[test]
1191 fn test_multi_precision_vectors() {
1192 let f64_values = vec![1.0, 2.0, 3.0];
1194 let f64_vector = Vector::f64(f64_values.clone());
1195 assert_eq!(f64_vector.precision, VectorPrecision::F64);
1196 assert_eq!(f64_vector.dimensions, 3);
1197
1198 let i8_values = vec![100, -50, 0];
1200 let i8_vector = Vector::i8(i8_values);
1201 assert_eq!(i8_vector.precision, VectorPrecision::I8);
1202 assert_eq!(i8_vector.dimensions, 3);
1203
1204 let binary_values = vec![0b10101010, 0b11110000];
1206 let binary_vector = Vector::binary(binary_values);
1207 assert_eq!(binary_vector.precision, VectorPrecision::Binary);
1208 assert_eq!(binary_vector.dimensions, 16); }
1210
1211 #[test]
1212 fn test_vector_operations() -> Result<()> {
1213 let v1 = Vector::new(vec![1.0, 2.0, 3.0]);
1214 let v2 = Vector::new(vec![4.0, 5.0, 6.0]);
1215
1216 let sum = v1.add(&v2)?;
1218 assert_eq!(sum.as_f32(), vec![5.0, 7.0, 9.0]);
1219
1220 let diff = v2.subtract(&v1)?;
1222 assert_eq!(diff.as_f32(), vec![3.0, 3.0, 3.0]);
1223
1224 let scaled = v1.scale(2.0);
1226 assert_eq!(scaled.as_f32(), vec![2.0, 4.0, 6.0]);
1227 Ok(())
1228 }
1229
1230 #[test]
1231 fn test_cosine_similarity() -> Result<()> {
1232 let v1 = Vector::new(vec![1.0, 0.0, 0.0]);
1233 let v2 = Vector::new(vec![1.0, 0.0, 0.0]);
1234 let v3 = Vector::new(vec![0.0, 1.0, 0.0]);
1235
1236 assert!((v1.cosine_similarity(&v2).expect("test value") - 1.0).abs() < 0.001);
1238
1239 assert!((v1.cosine_similarity(&v3).expect("test value")).abs() < 0.001);
1241 Ok(())
1242 }
1243
1244 #[test]
1245 fn test_vector_store() -> Result<()> {
1246 let mut store = VectorStore::new();
1247
1248 store.index_resource("doc1".to_string(), "This is a test")?;
1250 store.index_resource("doc2".to_string(), "Another test document")?;
1251
1252 let results = store.similarity_search("test", 5)?;
1254 assert_eq!(results.len(), 2);
1255
1256 assert!(results[0].1 >= results[1].1);
1258 Ok(())
1259 }
1260
1261 #[test]
1262 fn test_similarity_metrics() -> Result<()> {
1263 let a = vec![1.0, 2.0, 3.0];
1264 let b = vec![4.0, 5.0, 6.0];
1265
1266 let cosine_sim = SimilarityMetric::Cosine.similarity(&a, &b)?;
1268 let euclidean_sim = SimilarityMetric::Euclidean.similarity(&a, &b)?;
1269 let manhattan_sim = SimilarityMetric::Manhattan.similarity(&a, &b)?;
1270
1271 assert!((0.0..=1.0).contains(&cosine_sim));
1273 assert!((0.0..=1.0).contains(&euclidean_sim));
1274 assert!((0.0..=1.0).contains(&manhattan_sim));
1275 Ok(())
1276 }
1277
1278 #[test]
1279 fn test_quantization() {
1280 let values = vec![1.0, -0.5, 0.0, 0.75];
1281 let quantized = Vector::quantize_to_i8(&values);
1282
1283 for &q in &quantized {
1285 assert!((-127..=127).contains(&q));
1286 }
1287 }
1288
1289 #[test]
1290 fn test_binary_conversion() {
1291 let values = vec![0.8, -0.3, 0.1, -0.9];
1292 let binary = Vector::to_binary(&values, 0.0);
1293
1294 assert_eq!(binary.len(), 1);
1296
1297 let byte = binary[0];
1299 assert_eq!(byte & 1, 1); assert_eq!((byte >> 1) & 1, 0); assert_eq!((byte >> 2) & 1, 1); assert_eq!((byte >> 3) & 1, 0); }
1304
1305 #[test]
1306 fn test_memory_vector_index() -> Result<()> {
1307 let mut index = MemoryVectorIndex::new();
1308
1309 let v1 = Vector::new(vec![1.0, 0.0, 0.0]);
1310 let v2 = Vector::new(vec![0.0, 1.0, 0.0]);
1311
1312 index.insert("v1".to_string(), v1.clone())?;
1313 index.insert("v2".to_string(), v2.clone())?;
1314
1315 let results = index.search_knn(&v1, 1)?;
1317 assert_eq!(results.len(), 1);
1318 assert_eq!(results[0].0, "v1");
1319
1320 let results = index.search_threshold(&v1, 0.5)?;
1322 assert!(!results.is_empty());
1323 Ok(())
1324 }
1325
1326 #[test]
1327 fn test_hnsw_index() -> Result<()> {
1328 use crate::hnsw::{HnswConfig, HnswIndex};
1329
1330 let config = HnswConfig::default();
1331 let mut index = HnswIndex::new(config)?;
1332
1333 let v1 = Vector::new(vec![1.0, 0.0, 0.0]);
1334 let v2 = Vector::new(vec![0.0, 1.0, 0.0]);
1335 let v3 = Vector::new(vec![0.0, 0.0, 1.0]);
1336
1337 index.insert("v1".to_string(), v1.clone())?;
1338 index.insert("v2".to_string(), v2.clone())?;
1339 index.insert("v3".to_string(), v3.clone())?;
1340
1341 let results = index.search_knn(&v1, 2)?;
1343 assert!(results.len() <= 2);
1344
1345 if !results.is_empty() {
1347 assert_eq!(results[0].0, "v1");
1348 }
1349 Ok(())
1350 }
1351
1352 #[test]
1353 fn test_save_load_roundtrip() -> Result<()> {
1354 let dir = std::env::temp_dir().join(format!("oxirs_vec_test_{}", uuid::Uuid::new_v4()));
1355
1356 let mut store = VectorStore::new();
1358 let v1 = Vector::new(vec![1.0, 0.0, 0.0]);
1359 let v2 = Vector::new(vec![0.0, 1.0, 0.0]);
1360 let v3 = Vector::new(vec![0.0, 0.0, 1.0]);
1361
1362 store.index_vector("alpha".to_string(), v1.clone())?;
1363 store.index_vector("beta".to_string(), v2.clone())?;
1364 store.index_vector("gamma".to_string(), v3.clone())?;
1365
1366 let path = dir
1368 .to_str()
1369 .ok_or_else(|| anyhow::anyhow!("temp dir path is not UTF-8"))?;
1370 store.save_to_disk(path)?;
1371
1372 let loaded = VectorStore::load_from_disk(path)?;
1374
1375 let r_alpha = loaded.get_vector("alpha").expect("alpha must be present");
1377 assert_eq!(r_alpha.as_f32(), v1.as_f32(), "alpha roundtrip mismatch");
1378
1379 let r_beta = loaded.get_vector("beta").expect("beta must be present");
1380 assert_eq!(r_beta.as_f32(), v2.as_f32(), "beta roundtrip mismatch");
1381
1382 let r_gamma = loaded.get_vector("gamma").expect("gamma must be present");
1383 assert_eq!(r_gamma.as_f32(), v3.as_f32(), "gamma roundtrip mismatch");
1384
1385 let results = loaded.similarity_search_vector(&v1, 3)?;
1387 assert!(!results.is_empty(), "search returned no results after load");
1388 assert_eq!(
1389 results[0].0, "alpha",
1390 "top result after load should be alpha"
1391 );
1392
1393 let _ = std::fs::remove_dir_all(&dir);
1395 Ok(())
1396 }
1397
1398 #[test]
1399 fn test_sparql_vector_service() -> Result<()> {
1400 use crate::embeddings::EmbeddingStrategy;
1401 use crate::sparql_integration::{
1402 SparqlVectorService, VectorServiceArg, VectorServiceConfig, VectorServiceResult,
1403 };
1404
1405 let config = VectorServiceConfig::default();
1406 let mut service = SparqlVectorService::new(config, EmbeddingStrategy::SentenceTransformer)?;
1407
1408 let v1 = Vector::new(vec![1.0, 0.0, 0.0]);
1410 let v2 = Vector::new(vec![1.0, 0.0, 0.0]);
1411
1412 let args = vec![VectorServiceArg::Vector(v1), VectorServiceArg::Vector(v2)];
1413
1414 let result = service.execute_function("vector_similarity", &args)?;
1415
1416 match result {
1417 VectorServiceResult::Number(similarity) => {
1418 assert!((similarity - 1.0).abs() < 0.001); }
1420 _ => panic!("Expected a number result"),
1421 }
1422
1423 let text_args = vec![VectorServiceArg::String("test text".to_string())];
1425 let embed_result = service.execute_function("embed_text", &text_args)?;
1426
1427 match embed_result {
1428 VectorServiceResult::Vector(vector) => {
1429 assert_eq!(vector.dimensions, 384); }
1431 _ => panic!("Expected a vector result"),
1432 }
1433 Ok(())
1434 }
1435}