ipfrs_semantic/lib.rs
1//! # IPFRS Semantic - Vector Search and Semantic Routing
2//!
3//! This crate provides high-performance semantic search and routing capabilities for IPFRS,
4//! enabling content discovery based on vector embeddings and semantic similarity.
5//!
6//! ## Features
7//!
8//! - **HNSW-based Vector Search** - Fast approximate nearest neighbor search
9//! - **Semantic Routing** - Content discovery based on embeddings
10//! - **Hybrid Search** - Combine vector search with metadata filtering
11//! - **Vector Quantization** - Memory-efficient index compression (PQ, OPQ, Scalar)
12//! - **Learned Indices** - ML-based indexing with Recursive Model Index (RMI)
13//! - **Logic Integration** - TensorLogic reasoning with embeddings
14//! - **DiskANN** - Disk-based indexing for 100M+ vectors
15//! - **SIMD Optimization** - ARM NEON and x86 SSE/AVX acceleration
16//! - **Caching** - Hot embedding cache with LRU eviction
17//! - **Batch Query Processing** - Parallel batch queries for high throughput
18//! - **Query Re-ranking** - Multi-criteria result re-ranking with weighted scoring
19//! - **Query Analytics** - Performance tracking and query pattern analysis
20//! - **Multi-Modal Search** - Unified search across text, image, audio, video, and code
21//! - **Differential Privacy** - Privacy-preserving embeddings with configurable privacy budgets
22//! - **Dynamic Updates** - Online embedding updates and version migration
23//! - **Vector Quality Analysis** - Data validation, anomaly detection, and quality metrics (NEW!)
24//! - **Index Diagnostics** - Health monitoring, performance profiling, and issue detection (NEW!)
25//! - **Index Optimization** - Automatic parameter tuning and resource management (NEW!)
26//! - **Auto-Scaling Advisor** - Intelligent scaling recommendations for production deployments (NEW!)
27//!
28//! ## Quick Start
29//!
30//! ### Basic Semantic Search
31//!
32//! ```rust
33//! use ipfrs_semantic::{SemanticRouter, RouterConfig};
34//! use ipfrs_core::Cid;
35//!
36//! # #[tokio::main]
37//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
38//! // Create a semantic router with default configuration
39//! let router = SemanticRouter::with_defaults()?;
40//!
41//! // Index content with embeddings (typically from a model like BERT, CLIP, etc.)
42//! let cid1: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
43//! let embedding1 = vec![0.1, 0.2, 0.3]; // 768-dim embedding in real use
44//!
45//! // Add to index
46//! router.add(&cid1, &vec![0.5; 768])?;
47//!
48//! // Query for similar content
49//! let query_embedding = vec![0.5; 768];
50//! let results = router.query(&query_embedding, 10).await?;
51//!
52//! for result in results {
53//! println!("CID: {}, Score: {}", result.cid, result.score);
54//! }
55//! # Ok(())
56//! # }
57//! ```
58//!
59//! ### Batch Query for High Throughput
60//!
61//! ```rust
62//! use ipfrs_semantic::{SemanticRouter, RouterConfig};
63//! use ipfrs_core::Cid;
64//!
65//! # #[tokio::main]
66//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
67//! // Create a semantic router
68//! let router = SemanticRouter::with_defaults()?;
69//!
70//! // Index multiple items
71//! let items = vec![
72//! ("bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse::<Cid>()?, vec![0.1; 768]),
73//! ("bafybeihpjhkeuiq3k6nqa3fkgeigeri7iebtrsuyuey5y6vy36n345xmbi".parse::<Cid>()?, vec![0.2; 768]),
74//! ("bafybeif2pall7dybz7vecqka3zo24irdwabwdi4wc55jznaq75q7eaavvu".parse::<Cid>()?, vec![0.3; 768]),
75//! ];
76//!
77//! router.add_batch(&items)?;
78//!
79//! // Batch query - process multiple queries in parallel
80//! let query_embeddings = vec![
81//! vec![0.15; 768],
82//! vec![0.25; 768],
83//! vec![0.35; 768],
84//! ];
85//!
86//! // More efficient than querying one by one
87//! let batch_results = router.query_batch(&query_embeddings, 10).await?;
88//!
89//! for (i, results) in batch_results.iter().enumerate() {
90//! println!("Query {} found {} results", i, results.len());
91//! }
92//!
93//! // Get batch statistics
94//! let stats = router.batch_stats(&batch_results);
95//! println!("Total queries: {}", stats.total_queries);
96//! println!("Avg results per query: {:.2}", stats.avg_results_per_query);
97//! println!("Avg score: {:.4}", stats.avg_score);
98//! # Ok(())
99//! # }
100//! ```
101//!
102//! ### Hybrid Search with Metadata Filtering
103//!
104//! ```rust
105//! use ipfrs_semantic::{HybridIndex, HybridConfig, HybridQuery, Metadata, MetadataValue, MetadataFilter};
106//! use ipfrs_core::Cid;
107//!
108//! # #[tokio::main]
109//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
110//! // Create hybrid index
111//! let config = HybridConfig::default();
112//! let index = HybridIndex::new(config)?;
113//!
114//! // Index content with metadata
115//! let cid: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
116//! let embedding = vec![0.5; 768];
117//!
118//! let mut metadata = Metadata::new();
119//! metadata.set("type", MetadataValue::String("image".to_string()));
120//! metadata.set("size", MetadataValue::Integer(1024));
121//!
122//! index.insert(&cid, &embedding, Some(metadata))?;
123//!
124//! // Query with filters using builder pattern
125//! let filter = MetadataFilter::eq("type", MetadataValue::String("image".to_string()));
126//! let query = HybridQuery::knn(vec![0.5; 768], 10)
127//! .with_filter(filter);
128//!
129//! let response = index.search(query).await?;
130//! println!("Found {} results", response.results.len());
131//! # Ok(())
132//! # }
133//! ```
134//!
135//! ### Vector Quantization for Memory Efficiency
136//!
137//! ```rust
138//! use ipfrs_semantic::{ProductQuantizer, ScalarQuantizer};
139//!
140//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
141//! // Create Product Quantizer (8-32x compression)
142//! let dimension = 768;
143//! let num_subspaces = 8;
144//! let bits_per_subspace = 8;
145//!
146//! let mut pq = ProductQuantizer::new(dimension, num_subspaces, bits_per_subspace)?;
147//!
148//! // Train on representative data (1000 training samples, max 10 iterations)
149//! let training_data: Vec<Vec<f32>> = vec![vec![0.5; 768]; 1000];
150//! pq.train(&training_data, 10)?;
151//!
152//! // Quantize embeddings
153//! let embedding = vec![0.5; 768];
154//! let quantized = pq.quantize(&embedding)?;
155//!
156//! println!("Original size: {} bytes", dimension * 4);
157//! println!("Quantized size: {} bytes", quantized.codes.len());
158//! # Ok(())
159//! # }
160//! ```
161//!
162//! ### DiskANN for Large-Scale Indexing
163//!
164//! ```rust,no_run
165//! use ipfrs_semantic::{DiskANNIndex, DiskANNConfig};
166//! use ipfrs_core::Cid;
167//!
168//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
169//! // Create DiskANN index for 100M+ vectors
170//! let config = DiskANNConfig {
171//! dimension: 768,
172//! max_degree: 32,
173//! ..Default::default()
174//! };
175//!
176//! let mut index = DiskANNIndex::new(config);
177//! index.create("/tmp/diskann_index")?;
178//!
179//! // Insert vectors (stored on disk, not in RAM)
180//! let cid: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
181//! let embedding = vec![0.5; 768];
182//! index.insert(&cid, &embedding)?;
183//!
184//! // Search with constant memory usage
185//! let results = index.search(&embedding, 10)?;
186//! println!("Found {} results from disk", results.len());
187//! # Ok(())
188//! # }
189//! ```
190//!
191//! ### Learned Index Structures
192//!
193//! ```rust
194//! use ipfrs_semantic::{LearnedIndex, RMIConfig, ModelType};
195//! use ipfrs_core::Cid;
196//!
197//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
198//! // Create a learned index with Recursive Model Index (RMI)
199//! let config = RMIConfig {
200//! num_models: 10, // Number of second-stage models
201//! model_type: ModelType::Linear, // Linear, Polynomial, or NeuralNetwork
202//! training_iterations: 100,
203//! learning_rate: 0.01,
204//! error_threshold: 0.05,
205//! };
206//!
207//! let mut index = LearnedIndex::new(config);
208//!
209//! // Add embeddings - the index learns data distribution
210//! for i in 0..1000 {
211//! let cid = Cid::default();
212//! let embedding = vec![i as f32 / 1000.0; 768];
213//! index.add(cid, embedding)?;
214//! }
215//!
216//! // The index automatically rebuilds and trains models
217//! let query = vec![0.5; 768];
218//! let results = index.search(&query, 10)?;
219//!
220//! // Check statistics
221//! let stats = index.stats();
222//! println!("Indexed {} points using {} models",
223//! stats.data_points, stats.num_models);
224//! # Ok(())
225//! # }
226//! ```
227//!
228//! ### TensorLogic Integration
229//!
230//! ```rust,no_run
231//! use ipfrs_semantic::{LogicSolver, SolverConfig};
232//! use ipfrs_tensorlogic::{Predicate, Term, Constant};
233//! use ipfrs_core::Cid;
234//!
235//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
236//! // Create a logic solver with semantic similarity
237//! let config = SolverConfig {
238//! max_depth: 100,
239//! similarity_threshold: 0.8,
240//! top_k_similar: 10,
241//! embedding_dim: 384,
242//! detect_cycles: true,
243//! };
244//!
245//! let mut solver = LogicSolver::new(config)?;
246//!
247//! // Add facts to the knowledge base
248//! let cid1: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
249//! let fact1 = Predicate::new("likes".to_string(), vec![
250//! Term::Const(Constant::String("alice".to_string())),
251//! Term::Const(Constant::String("rust".to_string())),
252//! ]);
253//! solver.add_fact(fact1, cid1)?;
254//!
255//! let cid2: Cid = "bafybeihpjhkeuiq3k6nqa3fkgeigeri7iebtrsuyuey5y6vy36n345xmbi".parse()?;
256//! let fact2 = Predicate::new("likes".to_string(), vec![
257//! Term::Const(Constant::String("bob".to_string())),
258//! Term::Const(Constant::String("python".to_string())),
259//! ]);
260//! solver.add_fact(fact2, cid2)?;
261//!
262//! // Add a rule for similarity-based matching
263//! // Rule: similar(X, Y) :- likes(X, Lang), likes(Y, Lang)
264//! let head = Predicate::new("similar".to_string(), vec![
265//! Term::Var("X".to_string()),
266//! Term::Var("Y".to_string())
267//! ]);
268//! let body = vec![
269//! Predicate::new("likes".to_string(), vec![
270//! Term::Var("X".to_string()),
271//! Term::Var("Lang".to_string())
272//! ]),
273//! Predicate::new("likes".to_string(), vec![
274//! Term::Var("Y".to_string()),
275//! Term::Var("Lang".to_string())
276//! ]),
277//! ];
278//! solver.add_rule(head, body)?;
279//!
280//! // Query using semantic similarity
281//! let query = Predicate::new("likes".to_string(), vec![
282//! Term::Var("Who".to_string()),
283//! Term::Const(Constant::String("rust".to_string())),
284//! ]);
285//!
286//! let results = solver.query(&query)?;
287//! for substitution in results {
288//! println!("Found substitution: {:?}", substitution);
289//! }
290//!
291//! // Get solver statistics
292//! let stats = solver.stats();
293//! println!("Total facts: {}", stats.num_facts);
294//! println!("Total rules: {}", stats.num_rules);
295//! println!("Indexed predicates: {}", stats.num_indexed_predicates);
296//! # Ok(())
297//! # }
298//! ```
299//!
300//! ### Custom Embedding Model Integration
301//!
302//! ```rust,no_run
303//! use ipfrs_semantic::{SemanticRouter, RouterConfig, DistanceMetric};
304//! use ipfrs_core::Cid;
305//!
306//! # #[tokio::main]
307//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
308//! // Configure router for your embedding model
309//! let config = RouterConfig {
310//! dimension: 768, // BERT-base dimension
311//! metric: DistanceMetric::Cosine,
312//! max_connections: 16,
313//! ef_construction: 200,
314//! ef_search: 50,
315//! cache_size: 1000,
316//! };
317//!
318//! let router = SemanticRouter::new(config)?;
319//!
320//! // Function to generate embeddings from your model
321//! // This is a placeholder - replace with your actual model
322//! fn generate_embedding(text: &str) -> Vec<f32> {
323//! // Example: Use sentence-transformers, Hugging Face transformers, etc.
324//! // let model = SentenceTransformer::new("all-MiniLM-L6-v2");
325//! // model.encode(text)
326//!
327//! // For this example, just return a dummy embedding
328//! vec![0.5; 768]
329//! }
330//!
331//! // Index documents with embeddings
332//! let documents = vec![
333//! ("Rust programming language", "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"),
334//! ("Python machine learning", "bafybeihpjhkeuiq3k6nqa3fkgeigeri7iebtrsuyuey5y6vy36n345xmbi"),
335//! ("Distributed systems", "bafybeif2pall7dybz7vecqka3zo24irdwabwdi4wc55jznaq75q7eaavvu"),
336//! ];
337//!
338//! for (text, cid_str) in documents {
339//! let cid: Cid = cid_str.parse()?;
340//! let embedding = generate_embedding(text);
341//! router.add(&cid, &embedding)?;
342//! }
343//!
344//! // Query with natural language
345//! let query_text = "rust systems programming";
346//! let query_embedding = generate_embedding(query_text);
347//! let results = router.query(&query_embedding, 5).await?;
348//!
349//! println!("Top results for '{}':", query_text);
350//! for result in results {
351//! println!(" CID: {}, Score: {:.3}", result.cid, result.score);
352//! }
353//! # Ok(())
354//! # }
355//! ```
356//!
357//! ### Distributed Semantic Search
358//!
359//! For large-scale deployments across multiple nodes:
360//!
361//! ```rust,no_run
362//! use ipfrs_semantic::{SemanticDHTNode, SemanticDHTConfig, VectorIndex, DistanceMetric};
363//! use ipfrs_network::libp2p::PeerId;
364//! use ipfrs_core::Cid;
365//!
366//! # #[tokio::main]
367//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
368//! // Configure distributed semantic DHT
369//! let config = SemanticDHTConfig {
370//! embedding_dim: 768,
371//! replication_factor: 3, // Replicate to 3 peers
372//! routing_table_size: 20, // Top 20 nearest peers
373//! distance_metric: DistanceMetric::Cosine,
374//! max_hops: 5, // Maximum query propagation hops
375//! query_timeout_ms: 5000, // 5 second timeout
376//! };
377//!
378//! // Create local vector index
379//! let local_index = VectorIndex::new(768, DistanceMetric::Cosine, 16, 200)?;
380//!
381//! // Create DHT node
382//! let local_peer_id = PeerId::random();
383//! let dht_node = SemanticDHTNode::new(config, local_peer_id, local_index);
384//!
385//! // Add peer to routing table
386//! use ipfrs_semantic::SemanticPeer;
387//! let peer_id = PeerId::random();
388//! let peer_embedding = vec![0.5; 768]; // Aggregate embedding of peer's data
389//! let peer = SemanticPeer::new(peer_id, peer_embedding);
390//! dht_node.routing_table().add_peer(peer)?;
391//!
392//! // Insert data (automatically replicated to nearest peers)
393//! let cid: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
394//! let embedding = vec![0.7; 768];
395//! dht_node.insert(&cid, &embedding).await?;
396//!
397//! // Distributed k-NN search across the network
398//! let query_embedding = vec![0.6; 768];
399//! let results = dht_node.search_distributed(&query_embedding, 10).await?;
400//!
401//! println!("Found {} results from distributed search", results.len());
402//! for result in results {
403//! println!(" CID: {}, Score: {:.3}", result.cid, result.score);
404//! }
405//!
406//! // Update peer clusters for locality optimization
407//! dht_node.routing_table().update_clusters(3)?;
408//!
409//! // Get DHT statistics
410//! let stats = dht_node.get_stats();
411//! println!("DHT Stats:");
412//! println!(" Peers: {}", stats.num_peers);
413//! println!(" Clusters: {}", stats.num_clusters);
414//! println!(" Local entries: {}", stats.num_local_entries);
415//! println!(" Queries processed: {}", stats.queries_processed);
416//! println!(" Avg latency: {:.2}ms", stats.avg_query_latency_ms);
417//! # Ok(())
418//! # }
419//! ```
420//!
421//! ### Federated Multi-Index Search
422//!
423//! Query multiple indices simultaneously with heterogeneous distance metrics:
424//!
425//! ```rust
426//! use ipfrs_semantic::{
427//! FederatedQueryExecutor, FederatedConfig, AggregationStrategy,
428//! LocalIndexAdapter, VectorIndex, DistanceMetric
429//! };
430//! use ipfrs_core::Cid;
431//! use parking_lot::RwLock;
432//! use std::sync::Arc;
433//!
434//! # #[tokio::main]
435//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
436//! // Configure federated queries
437//! let mut config = FederatedConfig::default();
438//! config.aggregation_strategy = AggregationStrategy::RankFusion; // Best for heterogeneous metrics
439//! config.privacy_preserving = true; // Enable differential privacy
440//! config.privacy_noise_level = 0.01; // Small noise for privacy
441//!
442//! let executor = FederatedQueryExecutor::new(config);
443//!
444//! // Create multiple indices with different metrics
445//! let index1 = VectorIndex::new(768, DistanceMetric::Cosine, 16, 200)?;
446//! let index2 = VectorIndex::new(768, DistanceMetric::L2, 16, 200)?;
447//! let index3 = VectorIndex::new(768, DistanceMetric::DotProduct, 16, 200)?;
448//!
449//! // Populate indices with data
450//! // (In practice, these might be from different organizations or data sources)
451//! let cid1: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
452//! let embedding1 = vec![0.5; 768];
453//! Arc::new(RwLock::new(index1)).write().insert(&cid1, &embedding1)?;
454//!
455//! // Register indices for federated queries
456//! let adapter1 = LocalIndexAdapter::new(
457//! Arc::new(RwLock::new(VectorIndex::new(768, DistanceMetric::Cosine, 16, 200)?)),
458//! "org1_index".to_string()
459//! );
460//! let adapter2 = LocalIndexAdapter::new(
461//! Arc::new(RwLock::new(VectorIndex::new(768, DistanceMetric::L2, 16, 200)?)),
462//! "org2_index".to_string()
463//! );
464//!
465//! executor.register_index(Arc::new(adapter1))?;
466//! executor.register_index(Arc::new(adapter2))?;
467//!
468//! // Query all registered indices simultaneously
469//! let query_embedding = vec![0.6; 768];
470//! let results = executor.query(&query_embedding, 10).await?;
471//!
472//! println!("Federated search found {} results", results.len());
473//! for result in results {
474//! println!(
475//! " CID: {}, Score: {:.3}, Source: {}, Metric: {:?}",
476//! result.cid, result.score, result.source_index_id, result.source_metric
477//! );
478//! }
479//!
480//! // Query specific indices only
481//! let specific_results = executor.query_indices(
482//! &query_embedding,
483//! 10,
484//! &["org1_index".to_string()]
485//! ).await?;
486//!
487//! // Get federated query statistics
488//! let stats = executor.stats();
489//! println!("Federated Query Stats:");
490//! println!(" Total queries: {}", stats.total_queries);
491//! println!(" Indices queried: {}", stats.total_indices_queried);
492//! println!(" Avg latency: {:.2}ms", stats.avg_latency_ms);
493//! # Ok(())
494//! # }
495//! ```
496//!
497//! ### Multi-Modal Semantic Search
498//!
499//! Search across different data types (text, images, audio, etc.) in a unified embedding space:
500//!
501//! ```rust
502//! use ipfrs_semantic::{MultiModalIndex, MultiModalConfig, MultiModalEmbedding, Modality};
503//! use ipfrs_core::Cid;
504//!
505//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
506//! // Create multi-modal index
507//! let mut config = MultiModalConfig::default();
508//! config.project_to_unified = true; // Enable unified embedding space
509//! config.unified_dim = 512;
510//!
511//! let mut index = MultiModalIndex::new(config);
512//!
513//! // Register different modalities with their native dimensions
514//! index.register_modality(Modality::Text, 768)?; // BERT embeddings
515//! index.register_modality(Modality::Image, 512)?; // ResNet embeddings
516//! index.register_modality(Modality::Audio, 768)?; // Wav2Vec embeddings
517//!
518//! // Add text content
519//! let text_cid: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
520//! let text_embedding = MultiModalEmbedding::new(
521//! vec![0.1; 768], // Text embedding from BERT
522//! Modality::Text
523//! );
524//! index.add(text_cid, text_embedding)?;
525//!
526//! // Add image content
527//! let image_cid: Cid = "bafybeigvgzoolh3cxsculpsjkz3hxfpg37pszqx3j7i5fwzgjmrmtv5wmi".parse()?;
528//! let image_embedding = MultiModalEmbedding::new(
529//! vec![0.2; 512], // Image embedding from ResNet
530//! Modality::Image
531//! );
532//! index.add(image_cid, image_embedding)?;
533//!
534//! // Search within a specific modality
535//! let text_query = MultiModalEmbedding::new(vec![0.15; 768], Modality::Text);
536//! let text_results = index.search_modality(&text_query, 5, None)?;
537//!
538//! // Cross-modal search: find similar content across all modalities
539//! let cross_modal_results = index.search_cross_modal(&text_query, 10, None)?;
540//! for (cid, score, modality) in cross_modal_results {
541//! println!("Found {:?} content: {} (score: {:.3})", modality, cid, score);
542//! }
543//!
544//! // Get statistics
545//! let stats = index.stats();
546//! for (modality, stat) in stats {
547//! println!("{:?}: {} embeddings, {} dims", modality, stat.num_embeddings, stat.dimension);
548//! }
549//! # Ok(())
550//! # }
551//! ```
552//!
553//! ### Privacy-Preserving Search with Differential Privacy
554//!
555//! Protect embedding privacy while maintaining search utility:
556//!
557//! ```rust
558//! use ipfrs_semantic::{PrivacyMechanism, PrivacyBudget, PrivateEmbedding, TradeoffAnalyzer};
559//!
560//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
561//! // Create a privacy mechanism (epsilon-differential privacy)
562//! let epsilon = 1.0; // Privacy budget
563//! let sensitivity = 1.0; // L2 sensitivity of embeddings
564//! let mechanism = PrivacyMechanism::laplacian(epsilon, sensitivity)?;
565//!
566//! // Create a private embedding
567//! let original_embedding = vec![0.5; 768];
568//! let private_emb = PrivateEmbedding::new(original_embedding, mechanism);
569//!
570//! // Use the noisy embedding for public release
571//! let public_embedding = private_emb.public_embedding();
572//! let (epsilon, delta) = private_emb.privacy_params();
573//! println!("Privacy: ε={}, δ={}", epsilon, delta);
574//! println!("Expected utility loss: {:.3}", private_emb.utility_loss());
575//!
576//! // Track privacy budget across multiple queries
577//! let budget = PrivacyBudget::new(10.0, 0.001)?; // Total budget
578//!
579//! // Consume budget for each query
580//! budget.consume(0.5, 0.0001)?;
581//! budget.consume(0.5, 0.0001)?;
582//!
583//! println!("Remaining budget: {:.2}", budget.remaining());
584//!
585//! // Analyze privacy-utility trade-offs
586//! let analyzer = TradeoffAnalyzer::new(sensitivity);
587//! let tradeoffs = analyzer.analyze(768);
588//! for point in tradeoffs {
589//! println!("ε={:.1}: utility loss={:.2}", point.epsilon, point.utility_loss);
590//! }
591//!
592//! // Find best epsilon for target utility
593//! if let Some(best_epsilon) = analyzer.find_epsilon_for_utility(768, 15.0) {
594//! println!("Best ε for utility loss <15.0: {:.2}", best_epsilon);
595//! }
596//! # Ok(())
597//! # }
598//! ```
599//!
600//! ### Dynamic Embedding Updates and Version Migration
601//!
602//! Manage evolving embeddings with version control and online updates:
603//!
604//! ```rust
605//! use ipfrs_semantic::{DynamicIndex, ModelVersion, OnlineUpdater, EmbeddingTransform};
606//! use ipfrs_core::Cid;
607//!
608//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
609//! // Create a dynamic index with version tracking
610//! let v1 = ModelVersion::new(1, 0, 0);
611//! let index = DynamicIndex::new(v1.clone(), 768)?;
612//!
613//! // Add embeddings to version 1.0.0
614//! let cid: Cid = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi".parse()?;
615//! let embedding_v1 = vec![0.5; 768];
616//! index.insert(&cid, &embedding_v1, None)?;
617//!
618//! // Add a new model version with transformation
619//! let v2 = ModelVersion::new(1, 1, 0);
620//! let transform = EmbeddingTransform::identity(v1.clone());
621//! index.add_version(v2.clone(), Some(transform))?;
622//!
623//! // Set the new version as active
624//! index.set_active_version(v2.clone())?;
625//!
626//! // Add new embeddings to v2
627//! let cid2: Cid = "bafybeigvgzoolh3cxsculpsjkz3hxfpg37pszqx3j7i5fwzgjmrmtv5wmi".parse()?;
628//! let embedding_v2 = vec![0.6; 768];
629//! index.insert(&cid2, &embedding_v2, Some(v2))?;
630//!
631//! // Online fine-tuning with momentum
632//! let updater = OnlineUpdater::new(0.01, 0.9); // learning_rate, momentum
633//!
634//! // Apply gradient updates
635//! let gradient = vec![0.001; 768];
636//! let updated_embedding = updater.update(&cid, &embedding_v2, &gradient);
637//!
638//! // Track versions
639//! let stats = index.version_stats();
640//! for (version, stat) in stats {
641//! println!("Version {}: {} embeddings (active: {})",
642//! version, stat.num_embeddings, stat.is_active);
643//! }
644//!
645//! // Online updater statistics
646//! let updater_stats = updater.stats();
647//! println!("Online updater: lr={}, momentum={}, tracking {} embeddings",
648//! updater_stats.learning_rate, updater_stats.momentum, updater_stats.num_tracked);
649//! # Ok(())
650//! # }
651//! ```
652//!
653//! ## Performance
654//!
655//! ### SIMD Acceleration
656//!
657//! The crate includes SIMD-optimized distance computations:
658//!
659//! ```rust
660//! use ipfrs_semantic::{l2_distance, cosine_distance, dot_product};
661//!
662//! let vec1 = vec![1.0, 2.0, 3.0, 4.0];
663//! let vec2 = vec![0.5, 1.5, 2.5, 3.5];
664//!
665//! // Uses ARM NEON or x86 SSE/AVX when available
666//! let l2_dist = l2_distance(&vec1, &vec2);
667//! let cos_dist = cosine_distance(&vec1, &vec2);
668//! let dot_prod = dot_product(&vec1, &vec2);
669//! ```
670//!
671//! ### Performance Targets
672//!
673//! - **Query latency**: < 1ms for 1M vectors (cached)
674//! - **Query latency**: < 5ms for 1M vectors (uncached)
675//! - **Index build time**: < 10min for 1M vectors
676//! - **Memory usage**: < 2GB for 1M × 768-dim vectors
677//! - **Recall@10**: > 95% for k-NN search
678//!
679//! ## Architecture
680//!
681//! ### Core Components
682//!
683//! - **[`VectorIndex`]** - HNSW-based vector search index
684//! - **[`SemanticRouter`]** - High-level routing with caching
685//! - **[`HybridIndex`]** - Hybrid search with metadata filtering
686//! - **[`DiskANNIndex`]** - Disk-based indexing for massive scale
687//!
688//! ### Optimization Layers
689//!
690//! - **Quantization** - [`ProductQuantizer`], [`OptimizedProductQuantizer`], [`ScalarQuantizer`]
691//! - **Caching** - [`HotEmbeddingCache`], [`AlignedVector`]
692//! - **SIMD** - [`l2_distance`], [`cosine_distance`], [`dot_product`]
693//!
694//! ### Logic Integration
695//!
696//! - **[`LogicSolver`]** - TensorLogic reasoning with embeddings
697//! - **[`QueryExecutor`]** - SPARQL-like query language
698//! - **[`ProvenanceTracker`]** - Audit trails and provenance
699//!
700//! ## Use Cases
701//!
702//! ### Semantic Content Discovery
703//!
704//! Find similar content based on embeddings from models like:
705//! - Text: BERT, RoBERTa, Sentence Transformers
706//! - Images: CLIP, ResNet, ViT
707//! - Multi-modal: CLIP, ALIGN
708//!
709//! ### Recommendation Systems
710//!
711//! Build recommendation engines that find similar:
712//! - Documents based on text embeddings
713//! - Images based on visual features
714//! - Users based on behavior embeddings
715//!
716//! ### Distributed AI Model Routing
717//!
718//! Route AI inference requests to:
719//! - Find similar cached results
720//! - Locate relevant model weights
721//! - Discover related training data
722//!
723//! ## Configuration
724//!
725//! ### Index Tuning
726//!
727//! ```rust
728//! use ipfrs_semantic::{VectorIndex, DistanceMetric, ParameterTuner, UseCase};
729//!
730//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
731//! // Get recommended parameters for your use case
732//! let rec = ParameterTuner::recommend(
733//! 100_000, // number of vectors
734//! 768, // dimension
735//! UseCase::HighRecall // optimize for recall
736//! );
737//!
738//! // Create index with recommended parameters
739//! let index = VectorIndex::new(
740//! 768,
741//! DistanceMetric::Cosine,
742//! rec.m,
743//! rec.ef_construction
744//! )?;
745//!
746//! println!("M: {}, efConstruction: {}", rec.m, rec.ef_construction);
747//! println!("Estimated recall@10: {:.2}%", rec.estimated_recall * 100.0);
748//! # Ok(())
749//! # }
750//! ```
751//!
752//! ## Query Language
753//!
754//! The crate provides a SPARQL-like query language for complex knowledge base queries:
755//!
756//! ```rust,no_run
757//! use ipfrs_semantic::{Query, QueryPattern, QueryExecutor, FilterExpr, TermPattern};
758//! use ipfrs_tensorlogic::{KnowledgeBase, Predicate, Term, Constant};
759//!
760//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
761//! // Create knowledge base
762//! let mut kb = KnowledgeBase::new();
763//!
764//! // Add some facts
765//! let fact1 = Predicate::new("person".to_string(), vec![
766//! Term::Const(Constant::String("alice".to_string())),
767//! ]);
768//! kb.add_fact(fact1);
769//!
770//! let fact2 = Predicate::new("age".to_string(), vec![
771//! Term::Const(Constant::String("alice".to_string())),
772//! Term::Const(Constant::Int(30)),
773//! ]);
774//! kb.add_fact(fact2);
775//!
776//! // Create query executor
777//! let executor = QueryExecutor::new(kb);
778//!
779//! // Build a query using the builder pattern
780//! let query = Query::new()
781//! .select("name")
782//! .select("age_val")
783//! .where_pattern(QueryPattern::Pattern {
784//! name: Some("person".to_string()),
785//! args: vec![TermPattern::Variable("name".to_string())],
786//! })
787//! .where_pattern(QueryPattern::Pattern {
788//! name: Some("age".to_string()),
789//! args: vec![
790//! TermPattern::Variable("name".to_string()),
791//! TermPattern::Variable("age_val".to_string()),
792//! ],
793//! })
794//! .limit(10);
795//!
796//! // Execute the query
797//! let result = executor.execute(query)?;
798//!
799//! println!("Found {} results", result.bindings.len());
800//! for binding in result.bindings {
801//! println!(" Name: {:?}, Age: {:?}", binding.get("name"), binding.get("age_val"));
802//! }
803//!
804//! // Query statistics
805//! println!("Patterns evaluated: {}", result.stats.patterns_evaluated);
806//! println!("Execution time: {} ms", result.stats.execution_time_ms);
807//! # Ok(())
808//! # }
809//! ```
810//!
811//! ### Query Features
812//!
813//! - **SELECT clause**: Specify variables to return
814//! - **WHERE patterns**: Pattern matching with wildcards and variables
815//! - **FILTER expressions**: Filter results with boolean logic
816//! - **LIMIT/OFFSET**: Pagination support
817//! - **Query optimization**: Automatic join order optimization and filter pushdown
818//!
819//! ### Boolean Queries
820//!
821//! ```rust,no_run
822//! use ipfrs_semantic::{BooleanQuery, Query, FilterExpr};
823//!
824//! # fn main() {
825//! // AND query: match both conditions
826//! let and_query = BooleanQuery::And(vec![
827//! Query::new().select("x"),
828//! Query::new().select("y"),
829//! ]);
830//!
831//! // OR query: match either condition
832//! let or_query = BooleanQuery::Or(vec![
833//! Query::new().select("x"),
834//! Query::new().select("y"),
835//! ]);
836//!
837//! // NOT query: negate a query
838//! let not_query = BooleanQuery::Not(Box::new(
839//! Query::new().select("x")
840//! ));
841//! # }
842//! ```
843//!
844//! ## Error Handling
845//!
846//! All operations return `Result<T, ipfrs_core::Error>`:
847//!
848//! ```rust
849//! use ipfrs_semantic::SemanticRouter;
850//! use ipfrs_core::Error;
851//!
852//! # #[tokio::main]
853//! # async fn main() {
854//! match SemanticRouter::with_defaults() {
855//! Ok(router) => println!("Router created successfully"),
856//! Err(Error::InvalidInput(msg)) => eprintln!("Invalid input: {}", msg),
857//! Err(e) => eprintln!("Error: {}", e),
858//! }
859//! # }
860//! ```
861//!
862//! ## Advanced Features
863//!
864//! ### Vector Quality Analysis
865//!
866//! Validate embeddings and detect anomalies:
867//!
868//! ```rust
869//! use ipfrs_semantic::{analyze_quality, detect_anomaly, compute_batch_stats};
870//!
871//! # fn main() {
872//! // Analyze a single vector
873//! let embedding = vec![0.1, 0.2, 0.3, 0.4, 0.5];
874//! let quality = analyze_quality(&embedding);
875//!
876//! println!("Quality score: {:.2}", quality.quality_score);
877//! println!("Is valid: {}", quality.is_valid);
878//! println!("Is normalized: {}", quality.is_normalized);
879//! println!("Sparsity: {:.1}%", quality.sparsity * 100.0);
880//!
881//! // Detect anomalies
882//! let report = detect_anomaly(
883//! &embedding,
884//! 0.3, // expected mean
885//! 0.15, // expected std dev
886//! 1.0, // expected L2 norm
887//! 0.1, // mean tolerance
888//! 0.1, // std dev tolerance
889//! 0.2, // norm tolerance
890//! );
891//!
892//! if report.is_anomaly {
893//! println!("Anomaly detected: {}", report.description);
894//! println!("Confidence: {:.1}%", report.confidence * 100.0);
895//! }
896//!
897//! // Analyze batch of vectors
898//! let vectors = vec![
899//! vec![0.1, 0.2, 0.3],
900//! vec![0.4, 0.5, 0.6],
901//! vec![0.7, 0.8, 0.9],
902//! ];
903//! let batch_stats = compute_batch_stats(&vectors);
904//!
905//! println!("Average quality: {:.2}", batch_stats.avg_quality);
906//! println!("Valid vectors: {}/{}", batch_stats.valid_count, batch_stats.count);
907//! # }
908//! ```
909//!
910//! ### Index Diagnostics and Health Monitoring
911//!
912//! Monitor index health and performance:
913//!
914//! ```rust
915//! use ipfrs_semantic::{VectorIndex, diagnose_index, HealthMonitor, SearchProfiler};
916//! use std::time::Duration;
917//!
918//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
919//! let mut index = VectorIndex::with_defaults(128)?;
920//!
921//! // Run diagnostics
922//! let report = diagnose_index(&index);
923//!
924//! println!("Health status: {:?}", report.status);
925//! println!("Index size: {} vectors", report.size);
926//! println!("Memory usage: ~{:.2} MB", report.memory_usage as f64 / 1e6);
927//!
928//! for issue in &report.issues {
929//! println!("Issue ({:?}): {}", issue.severity, issue.description);
930//! if let Some(fix) = &issue.suggested_fix {
931//! println!(" Suggested fix: {}", fix);
932//! }
933//! }
934//!
935//! for rec in &report.recommendations {
936//! println!("Recommendation: {}", rec);
937//! }
938//!
939//! // Set up periodic health monitoring
940//! let mut monitor = HealthMonitor::new(Duration::from_secs(60));
941//!
942//! if monitor.should_check() {
943//! let report = monitor.check(&index);
944//! println!("Health check: {:?}", report.status);
945//! }
946//!
947//! // Profile search performance
948//! let mut profiler = SearchProfiler::new();
949//!
950//! // Simulate queries
951//! profiler.record_query(Duration::from_millis(5));
952//! profiler.record_query(Duration::from_millis(3));
953//! profiler.record_query(Duration::from_millis(4));
954//!
955//! let stats = profiler.stats();
956//! println!("Total queries: {}", stats.total_queries);
957//! println!("Average latency: {:?}", stats.avg_latency);
958//! println!("QPS: {:.2}", stats.qps);
959//! # Ok(())
960//! # }
961//! ```
962//!
963//! ### Index Optimization
964//!
965//! Automatically tune index parameters:
966//!
967//! ```rust
968//! use ipfrs_semantic::{analyze_optimization, OptimizationGoal, QueryOptimizer, MemoryOptimizer};
969//! use std::time::Duration;
970//!
971//! # fn main() {
972//! // Analyze and get optimization recommendations
973//! let result = analyze_optimization(
974//! 50_000, // index size
975//! 768, // dimension
976//! 16, // current M
977//! 200, // current ef_construction
978//! OptimizationGoal::Balanced,
979//! );
980//!
981//! println!("Current quality score: {:.2}", result.current_score);
982//! println!("Recommended M: {}", result.recommended_m);
983//! println!("Recommended ef_construction: {}", result.recommended_ef_construction);
984//! println!("Recommended ef_search: {}", result.recommended_ef_search);
985//! println!("Estimated improvement: {:.1}%", result.estimated_improvement * 100.0);
986//!
987//! for reason in &result.reasoning {
988//! println!(" - {}", reason);
989//! }
990//!
991//! // Adaptive query optimization
992//! let mut query_optimizer = QueryOptimizer::new(
993//! 50, // initial ef_search
994//! Duration::from_millis(10), // target latency
995//! );
996//!
997//! // The optimizer adjusts ef_search based on observed latency
998//! for _ in 0..20 {
999//! query_optimizer.record_query(Duration::from_millis(15));
1000//! }
1001//!
1002//! println!("Optimized ef_search: {}", query_optimizer.get_ef_search());
1003//!
1004//! // Memory budget optimization
1005//! let mut memory_optimizer = MemoryOptimizer::new(1024 * 1024 * 1024); // 1GB
1006//!
1007//! let (m, ef_c, max_vectors) = memory_optimizer.recommend_config(768);
1008//! println!("For 1GB budget:");
1009//! println!(" Recommended M: {}", m);
1010//! println!(" Recommended ef_construction: {}", ef_c);
1011//! println!(" Max vectors: {}", max_vectors);
1012//! # }
1013//! ```
1014
1015pub mod adapters;
1016pub mod analytics;
1017pub mod auto_scaling;
1018pub mod benchmark_comparison;
1019pub mod cache;
1020pub mod dht;
1021pub mod dht_node;
1022pub mod diagnostics;
1023pub mod diskann;
1024pub mod dynamic;
1025pub mod federated;
1026pub mod hnsw;
1027pub mod hybrid;
1028pub mod kb_query;
1029pub mod learned;
1030pub mod metadata;
1031pub mod migration;
1032pub mod multimodal;
1033pub mod optimization;
1034pub mod privacy;
1035pub mod prod_tests;
1036pub mod provenance;
1037pub mod quantization;
1038pub mod regression;
1039pub mod reranking;
1040pub mod router;
1041pub mod simd;
1042pub mod solver;
1043pub mod stats;
1044pub mod utils;
1045pub mod vector_quality;
1046
1047// Core vector index exports
1048pub use hnsw::{
1049 BuildHealthStats, DistanceMetric, IncrementalBuildStats, ParameterRecommendation,
1050 ParameterTuner, RebuildStats, SearchResult, UseCase, VectorIndex,
1051};
1052
1053// Router exports
1054pub use router::{BatchStats, CacheStats, QueryFilter, RouterConfig, RouterStats, SemanticRouter};
1055
1056// Hybrid search exports
1057pub use hybrid::{
1058 FilterStrategy, HybridConfig, HybridIndex, HybridQuery, HybridResponse, HybridResult,
1059 PruningStats,
1060};
1061
1062// Metadata exports
1063pub use metadata::{Metadata, MetadataFilter, MetadataStore, MetadataValue, TemporalOptions};
1064
1065// Quantization exports
1066pub use quantization::{
1067 OptimizedProductQuantizer, PQCode, ProductQuantizer, QuantizationBenchmark,
1068 QuantizationBenchmarker, QuantizationComparison, QuantizedVector, ScalarQuantizer,
1069};
1070
1071// Statistics exports
1072pub use stats::{IndexHealth, IndexStats, MemoryUsage, PerfTimer, StatsSnapshot};
1073
1074// DiskANN exports
1075pub use diskann::SearchResult as DiskANNSearchResult;
1076pub use diskann::{CompactionStats, DiskANNConfig, DiskANNIndex, DiskANNStats};
1077
1078// Solver exports (Logic Integration)
1079pub use solver::{
1080 LogicSolver, PredicateEmbedder, ProofSearch, ProofTreeNode, SolverConfig, SolverStats,
1081};
1082
1083// Knowledge Base Query exports
1084pub use kb_query::{
1085 BooleanQuery, FilterExpr, Query, QueryExecutor, QueryPattern, QueryResult, QueryStats,
1086 TermPattern, TermType,
1087};
1088
1089// Provenance exports
1090pub use provenance::{
1091 AuditLogEntry, AuditOperation, EmbeddingMetadata, EmbeddingSource, EmbeddingVersion,
1092 FeatureAttribution, ProvenanceStats, ProvenanceTracker, SearchExplanation, VersionHistory,
1093};
1094
1095// SIMD exports (Performance optimization)
1096pub use simd::{cosine_distance, dot_product, l2_distance};
1097
1098// Cache exports (Advanced caching)
1099pub use cache::{
1100 AdaptiveCacheStrategy, AlignedVector, CacheInvalidator, HotCacheStats, HotEmbeddingCache,
1101 InvalidationPolicy,
1102};
1103
1104// Multi-modal exports (Multi-Modal Search)
1105pub use multimodal::{
1106 Modality, ModalityAlignment, ModalityStats, MultiModalConfig, MultiModalEmbedding,
1107 MultiModalIndex,
1108};
1109
1110// Privacy exports (Differential Privacy)
1111pub use privacy::{
1112 NoiseDistribution, PrivacyBudget, PrivacyBudgetStats, PrivacyMechanism, PrivateEmbedding,
1113 QueryRecord, TradeoffAnalyzer, TradeoffPoint,
1114};
1115
1116// Dynamic embedding exports (Dynamic Updates)
1117pub use dynamic::{
1118 DynamicIndex, EmbeddingTransform, ModelVersion, OnlineUpdater, OnlineUpdaterStats, VersionStats,
1119};
1120
1121// Distributed DHT exports (Distributed Semantic Search)
1122pub use dht::{
1123 DHTQuery, DHTQueryResponse, ReplicationStrategy, SemanticDHTConfig, SemanticDHTStats,
1124 SemanticPeer, SemanticRoutingTable,
1125};
1126pub use dht_node::{SemanticDHTNode, SyncStats};
1127
1128// Federated Query exports (Multi-Index Search)
1129pub use federated::{
1130 AggregationStrategy, FederatedConfig, FederatedQueryExecutor, FederatedQueryStats,
1131 FederatedSearchResult, LocalIndexAdapter, QueryableIndex,
1132};
1133
1134// Re-ranking exports (Query Result Re-ranking)
1135pub use reranking::{ReRanker, ReRankingConfig, ReRankingStrategy, ScoreComponent, ScoredResult};
1136
1137// Analytics exports (Query Analytics and Performance Tracking)
1138pub use analytics::{
1139 AnalyticsSummary, AnalyticsTracker, DetectedPattern, QueryMetrics, QueryTimer,
1140};
1141
1142// Auto-Scaling Advisor exports (Production Operations)
1143pub use auto_scaling::{
1144 ActionType, AdvisorConfig, AutoScalingAdvisor, ScalingAction, ScalingRecommendations,
1145 TrendReport, WorkloadMetrics,
1146};
1147
1148// Learned Index exports (ML-Based Indexing)
1149pub use learned::{LearnedIndex, LearnedIndexStats, ModelType, RMIConfig};
1150
1151// Vector Database Adapter exports (External Integration)
1152pub use adapters::{
1153 BackendConfig, BackendMigration, BackendRegistry, BackendSearchResult, BackendStats,
1154 IpfrsBackend, MigrationStats, VectorBackend,
1155};
1156
1157// Vector Quality Analysis exports (Quality Validation and Anomaly Detection)
1158pub use vector_quality::{
1159 analyze_quality, compute_batch_stats, compute_diversity, compute_stats, cosine_similarity,
1160 detect_anomaly, find_outliers, AnomalyReport, AnomalyType, VectorQuality, VectorStats,
1161};
1162
1163// Diagnostics exports (Index Health Monitoring and Performance Profiling)
1164pub use diagnostics::{
1165 diagnose_index, DiagnosticIssue, DiagnosticReport, HealthMonitor, HealthStatus, IssueCategory,
1166 IssueSeverity, PerformanceMetrics, ProfilerStats, SearchProfiler,
1167};
1168
1169// Optimization exports (Index Optimization and Resource Management)
1170pub use optimization::{
1171 analyze_optimization, MemoryOptimizer, OptimizationGoal, OptimizationResult, QueryOptimizer,
1172};
1173
1174// Utility exports (Helper Functions and Common Workflows)
1175pub use utils::{
1176 average_embedding, create_hybrid_index_from_map, health_check, index_with_quality_check,
1177 normalize_vector, normalize_vectors, validate_embeddings, BatchEmbeddingStats,
1178 BatchIndexResult, HealthCheckResult,
1179};
1180
1181// Production Testing exports (Stress Testing and Endurance Testing)
1182pub use prod_tests::{
1183 EnduranceTest, EnduranceTestConfig, EnduranceTestResults, StressTest, StressTestConfig,
1184 StressTestResults,
1185};
1186
1187// Performance Regression Detection exports (Regression Testing)
1188pub use regression::{
1189 MetricSummary, RegressionConfig, RegressionDetector, RegressionIssue, RegressionReport,
1190};
1191
1192// Benchmark Comparison exports (Configuration Comparison and Parameter Tuning)
1193pub use benchmark_comparison::{
1194 BenchmarkResult, BenchmarkSuite, ComparisonReport, IndexConfig, ParameterSweep,
1195};
1196
1197// Index Migration exports (Index Type Migration and Configuration Updates)
1198pub use migration::{
1199 BatchMigration, ConfigMigration, DimensionMigration, IndexMigration, MetricMigration,
1200 MigrationConfig, MigrationProgress,
1201};