#![warn(missing_docs)]
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(unexpected_cfgs)]
pub mod circuit_breaker;
pub mod config;
pub mod connection_pool;
#[cfg(feature = "distillation")]
pub mod distillation;
pub mod error;
#[cfg(feature = "hidden-states")]
pub mod hidden_states;
pub mod hybrid_search;
pub mod index_management;
pub mod layer1_echo;
pub mod layer2_speculator;
pub mod layer3_judge;
#[cfg(feature = "graphrag")]
pub mod layer4_graph;
#[cfg(feature = "native")]
pub mod load_testing;
pub mod memory;
pub mod metrics;
pub mod pipeline;
pub mod pipeline_debug;
#[cfg(feature = "prefix-cache")]
pub mod prefix_cache;
#[cfg(feature = "quantization")]
pub mod quantization;
pub mod query_builder;
pub mod query_expansion;
pub mod relevance_feedback;
pub mod reranker;
pub mod retry;
pub mod simd_similarity;
pub mod streaming;
pub mod types;
#[cfg(feature = "wasm")]
pub mod wasm;
pub mod prelude {
pub use crate::circuit_breaker::{
CircuitBreaker, CircuitBreakerConfig, CircuitBreakerOrOperationError,
CircuitBreakerRegistry, CircuitBreakerStats, CircuitPermit, CircuitState,
with_circuit_breaker, with_service_circuit_breaker,
};
pub use crate::config::{
EchoConfig, JudgeConfig as JudgeCfg, OxiRagConfig, PipelineConfig as PipelineCfg,
RetryConfig, SimilarityMetricConfig, SpeculatorConfig as SpeculatorCfg,
};
pub use crate::connection_pool::{
Connection, ConnectionError, ConnectionPool, MockConnection, PoolConfig, PoolError,
PoolStats, PooledConnection,
};
pub use crate::error::{
EmbeddingError, JudgeError, OxiRagError, PipelineError, SpeculatorError, VectorStoreError,
};
pub use crate::layer1_echo::{
Echo, EchoLayer, EmbeddingProvider, InMemoryVectorStore, IndexedDocument, MetadataFilter,
MockEmbeddingProvider, SimilarityMetric, VectorStore,
};
pub use crate::layer2_speculator::{RuleBasedSpeculator, Speculator, SpeculatorConfig};
pub use crate::layer3_judge::{
AdvancedClaimExtractor, ClaimExtractor, Judge, JudgeConfig, JudgeImpl, MockSmtVerifier,
SmtVerifier,
};
pub use crate::memory::{
MemoryBreakdown, MemoryBudget, MemoryComponent, MemoryError, MemoryGuard, MemoryMonitor,
MemoryStats,
};
pub use crate::metrics::{LayerTiming, MetricsCollector, PipelineMetrics, TimedOperation};
pub use crate::pipeline::{Pipeline, PipelineBuilder, PipelineConfig, RagPipeline};
pub use crate::query_builder::{ExtendedQuery, LayerHints, QueryBuilder};
pub use crate::retry::RetryPolicy;
pub use crate::simd_similarity::{
SimdBackend, SimilarityEngine, detect_backend, simd_batch_cosine, simd_cosine_similarity,
simd_dot_product, simd_euclidean_distance, simd_l2_norm,
};
pub use crate::types::{
ClaimStructure, ClaimVerificationResult, ComparisonOp, Document, DocumentId, Draft,
LogicalClaim, PipelineOutput, Quantifier, Query, SearchResult, SpeculationDecision,
SpeculationResult, VerificationResult, VerificationStatus,
};
pub use crate::index_management::{
IndexManagement, IndexManager, IndexSnapshot, IndexStats, MergeResult, OptimizeConfig,
OptimizeResult, SerializedDocument, SerializedIndex, VacuumResult,
};
#[cfg(feature = "native")]
pub use crate::streaming::ProgressReporter;
pub use crate::streaming::{
ChunkMetadata, ChunkType, PipelineChunk, StreamingPipeline, StreamingPipelineResult,
StreamingPipelineWrapper,
};
#[cfg(feature = "speculator")]
pub use crate::layer1_echo::CandleEmbeddingProvider;
#[cfg(feature = "speculator")]
pub use crate::layer2_speculator::CandleSlmSpeculator;
#[cfg(feature = "judge")]
pub use crate::layer3_judge::OxizVerifier;
#[cfg(feature = "graphrag")]
pub use crate::config::GraphConfig;
#[cfg(feature = "graphrag")]
pub use crate::error::GraphError;
#[cfg(feature = "graphrag")]
pub use crate::layer4_graph::{
Direction, EntityExtractor, EntityId, EntityType, Graph, GraphEntity, GraphLayer,
GraphLayerBuilder, GraphPath, GraphQuery, GraphRelationship, GraphStore,
HybridSearchResult, InMemoryGraphStore, MockEntityExtractor, MockRelationshipExtractor,
PatternEntityExtractor, PatternRelationshipExtractor, RelationshipExtractor,
RelationshipType, bfs_traverse, find_entities_within_hops, find_shortest_path,
};
#[cfg(feature = "graphrag")]
pub use crate::query_builder::GraphContext;
#[cfg(feature = "distillation")]
pub use crate::distillation::{
CandidateDetector, CandidateEvaluation, CollectorStatistics, DistillationCandidate,
DistillationConfig, DistillationStats, DistillationTracker, InMemoryDistillationTracker,
NearReadyReason, QAPair, QAPairCollector, QueryFrequencyTracker, QueryPattern,
TrainingExample,
};
#[cfg(feature = "distillation")]
pub use crate::error::DistillationError;
#[cfg(feature = "prefix-cache")]
pub use crate::error::PrefixCacheError;
#[cfg(feature = "prefix-cache")]
pub use crate::prefix_cache::{
CacheKey, CacheLookupResult, CacheStats, ContextFingerprint, ContextFingerprintGenerator,
Fingerprintable, InMemoryPrefixCache, KVCacheEntry, PrefixCacheConfig, PrefixCacheExt,
PrefixCacheStore, RollingHasher,
};
#[cfg(feature = "hidden-states")]
pub use crate::error::HiddenStateError;
#[cfg(feature = "hidden-states")]
pub use crate::hidden_states::{
AdaptiveReuseStrategy, CachedHiddenState, DType, Device, HiddenStateCache,
HiddenStateCacheConfig, HiddenStateCacheStats, HiddenStateConfig, HiddenStateProvider,
HiddenStateProviderExt, HiddenStateTensor, HybridReuseStrategy, KVCache, LayerExtractor,
LayerHiddenState, LengthAwareReuseStrategy, MockHiddenStateProvider, ModelHiddenStates,
ModelKVCache, PrefixReuseStrategy, SemanticReuseStrategy, StatePooling, StateReuseStrategy,
StateSimilarity, TensorShape,
};
#[cfg(feature = "native")]
pub use crate::load_testing::{
LoadTest, LoadTestBuilder, LoadTestConfig, LoadTestResult, LoadTestStats,
MockQueryExecutor, MockQueryGenerator, QueryExecutor, QueryGenerator, RequestResult,
};
pub use crate::reranker::{
CrossEncoderReranker, FusionStrategy, HybridReranker, KeywordReranker,
MockCrossEncoderReranker, MockReranker, Reranker, RerankerConfig, RerankerPipeline,
RerankerPipelineBuilder, SemanticReranker,
};
pub use crate::pipeline_debug::{
DebugConfig, GanttTraceFormatter, JsonTraceFormatter, LayerTraceGuard,
MermaidTraceFormatter, PipelineDebugger, PipelineTrace, SharedPipelineDebugger,
TextTraceFormatter, TraceEntry, TraceFormatter, TraceId, create_shared_debugger,
};
pub use crate::relevance_feedback::{
FeedbackAdjuster, FeedbackConfig, FeedbackEntry, FeedbackStore, InMemoryFeedbackStore,
RelevanceFeedback, RelevanceModel, RocchioFeedbackAdjuster, SimpleBoostAdjuster,
};
pub use crate::query_expansion::{
CompositeExpander, ExpandedQuery, ExpansionConfig, ExpansionMethod, NGramExpander,
PseudoRelevanceFeedback, QueryExpander, QueryReformulator, StemExpander, SynonymExpander,
};
pub use crate::hybrid_search::{
BM25Encoder, BM25Params, FusionStrategy as HybridFusionStrategy, HybridConfig,
HybridResult, HybridSearcher, InMemorySparseStore, SparseVector, SparseVectorStore,
};
#[cfg(feature = "quantization")]
pub use crate::quantization::{
BinaryQuantizer, Int4Quantizer, Int8Quantizer, MockQuantizedVectorStore,
QuantizationConfig, QuantizationType, QuantizedDocument, QuantizedTensor,
QuantizedVectorStore, Quantizer, compute_quantization_error, compute_snr_db,
hamming_distance, int4_dot_product, int8_dot_product,
};
}
pub use error::{OxiRagError, Result};
#[cfg(test)]
mod tests {
use super::prelude::*;
#[tokio::test]
async fn test_full_pipeline_integration() {
let echo = EchoLayer::new(MockEmbeddingProvider::new(64), InMemoryVectorStore::new(64));
let speculator = RuleBasedSpeculator::default();
let judge = JudgeImpl::new(
AdvancedClaimExtractor::new(),
MockSmtVerifier::default(),
JudgeConfig::default(),
);
let mut pipeline = PipelineBuilder::new()
.with_echo(echo)
.with_speculator(speculator)
.with_judge(judge)
.with_config(PipelineConfig {
enable_fast_path: false,
..Default::default()
})
.build()
.expect("Failed to build pipeline");
let documents = vec![
Document::new(
"Rust is a systems programming language focused on safety and performance.",
),
Document::new("The Rust compiler prevents data races at compile time."),
Document::new("Cargo is Rust's package manager and build system."),
];
pipeline
.index_batch(documents)
.await
.expect("Failed to index documents");
let query = Query::new("What is Rust?").with_top_k(3);
let result = pipeline
.process(query)
.await
.expect("Failed to process query");
assert!(
!result.search_results.is_empty(),
"Should have search results"
);
assert!(
!result.final_answer.is_empty(),
"Should have a final answer"
);
assert!(result.confidence > 0.0, "Should have positive confidence");
assert!(
result.layers_used.len() >= 2,
"Should use at least Echo and Speculator"
);
}
#[tokio::test]
async fn test_document_lifecycle() {
let mut echo = EchoLayer::new(MockEmbeddingProvider::new(32), InMemoryVectorStore::new(32));
let doc = Document::new("Test document content").with_title("Test");
let id = echo.index(doc).await.expect("Failed to index");
let retrieved = echo
.get(&id)
.await
.expect("Failed to get")
.expect("Document not found");
assert_eq!(retrieved.title, Some("Test".to_string()));
let results = echo
.search("test document", 5, None)
.await
.expect("Failed to search");
assert!(!results.is_empty());
let deleted = echo.delete(&id).await.expect("Failed to delete");
assert!(deleted);
let retrieved = echo.get(&id).await.expect("Failed to get");
assert!(retrieved.is_none());
}
#[tokio::test]
async fn test_query_filtering() {
let mut echo = EchoLayer::new(MockEmbeddingProvider::new(32), InMemoryVectorStore::new(32));
echo.index(Document::new("High relevance content"))
.await
.unwrap();
echo.index(Document::new("Medium relevance")).await.unwrap();
echo.index(Document::new("Low relevance")).await.unwrap();
let results = echo
.search("high relevance", 10, Some(0.8))
.await
.expect("Failed to search");
for result in &results {
assert!(result.score >= 0.8);
}
}
#[test]
fn test_types_serialization() {
let doc = Document::new("Test content")
.with_title("Title")
.with_metadata("key", "value");
let json = serde_json::to_string(&doc).expect("Failed to serialize");
let parsed: Document = serde_json::from_str(&json).expect("Failed to deserialize");
assert_eq!(parsed.content, doc.content);
assert_eq!(parsed.title, doc.title);
}
#[test]
fn test_claim_structure_smtlib() {
let claim = LogicalClaim::new(
"test",
ClaimStructure::Comparison {
left: "a".to_string(),
operator: ComparisonOp::GreaterThan,
right: "b".to_string(),
},
);
let extractor = AdvancedClaimExtractor::new();
let smt = extractor
.to_smtlib(&claim)
.expect("Failed to generate SMT-LIB");
assert!(smt.contains("assert"));
assert!(smt.contains('>'));
}
}