#[cfg(all(feature = "fts5", not(feature = "storage")))]
compile_error!("feature `fts5` requires feature `storage`");
#[cfg(all(
feature = "persistent",
not(all(feature = "hybrid", feature = "storage"))
))]
compile_error!("feature `persistent` requires both `hybrid` and `storage`");
#[cfg(all(
feature = "durable",
not(all(feature = "persistent", feature = "durability"))
))]
compile_error!("feature `durable` requires both `persistent` and `durability`");
#[cfg(all(feature = "full-fts5", not(all(feature = "full", feature = "fts5"))))]
compile_error!("feature `full-fts5` requires both `full` and `fts5`");
pub use frankensearch_core as core;
pub use frankensearch_embed as embed;
pub use frankensearch_fusion as fusion;
pub use frankensearch_index as index;
#[cfg(feature = "lexical")]
pub use frankensearch_lexical as lexical;
#[cfg(feature = "rerank")]
pub use frankensearch_rerank as rerank;
#[cfg(feature = "storage")]
pub use frankensearch_storage as storage;
#[cfg(feature = "durability")]
pub use frankensearch_durability as durability;
#[cfg(feature = "storage")]
pub use frankensearch_storage::{
BatchResult, ContentHasher, DeduplicationDecision, DocumentRecord, IndexMetadata, IngestAction,
IngestResult, JobQueueConfig, JobQueueMetrics, PersistentJobQueue, StalenessCheck,
StalenessReason, Storage, StorageBackedJobRunner, StorageConfig,
};
#[cfg(feature = "fts5")]
pub use frankensearch_storage::{
Fts5AdapterConfig as Fts5Config, Fts5ContentMode, Fts5LexicalSearch,
Fts5TokenizerChoice as Fts5Tokenizer,
};
#[cfg(feature = "durability")]
pub use frankensearch_durability::{
DefaultSymbolCodec, DurabilityConfig, DurabilityMetrics, FileHealth,
FileProtectionResult as ProtectionResult, FileProtector, FileRepairOutcome as RepairResult,
FsviProtector, RepairCodec, RepairCodecConfig, VerifyResult as RepairCodecVerifyResult,
};
pub use asupersync::Cx;
pub use frankensearch_core::error::{SearchError, SearchResult};
pub use frankensearch_core::config::{TwoTierConfig, TwoTierMetrics};
pub use frankensearch_core::types::{
FusedHit, IndexableDocument, PhaseMetrics, RankChanges, ScoreSource, ScoredResult, SearchMode,
SearchPhase, VectorHit,
};
pub use frankensearch_core::types::{EmbeddingMetrics, IndexMetrics, SearchMetrics};
pub use frankensearch_core::traits::{
Embedder, LexicalSearch, MetricsExporter, ModelCategory, ModelInfo, ModelTier,
NoOpMetricsExporter, Reranker, SearchFuture, SharedMetricsExporter, SyncEmbed,
SyncEmbedderAdapter, SyncRerank, SyncRerankerAdapter,
};
pub use frankensearch_core::{DaemonClient, DaemonError, DaemonRetryConfig};
pub use frankensearch_core::traits::{RerankDocument, RerankScore};
pub use frankensearch_core::query_class::QueryClass;
pub use frankensearch_core::canonicalize::{Canonicalizer, DefaultCanonicalizer};
pub use frankensearch_core::fingerprint::{
DEFAULT_SEMANTIC_CHANGE_THRESHOLD, DocumentFingerprint, SIGNIFICANT_CHAR_COUNT_CHANGE_THRESHOLD,
};
pub use frankensearch_core::metrics_eval::{
BootstrapCi, BootstrapComparison, QualityComparison, QualityMetric, QualityMetricComparison,
QualityMetricSamples, bootstrap_ci, bootstrap_compare, map_at_k, mrr, ndcg_at_k,
quality_comparison, recall_at_k,
};
pub use frankensearch_core::traits::{cosine_similarity, l2_normalize, truncate_embedding};
pub use frankensearch_embed::auto_detect::{DimReduceEmbedder, EmbedderStack, TwoTierAvailability};
pub use frankensearch_embed::model_registry::{EmbedderRegistry, RegisteredEmbedder};
pub use frankensearch_index::{
InMemoryTwoTierIndex, InMemoryVectorIndex, TwoTierIndex, TwoTierIndexBuilder, VectorIndex,
VectorIndexWriter,
};
#[cfg(feature = "ann")]
pub use frankensearch_index::{AnnSearchStats, HnswConfig, HnswIndex};
pub use frankensearch_fusion::{
DaemonFallbackEmbedder, DaemonFallbackReranker, FederatedConfig, FederatedFusion, FederatedHit,
FederatedSearcher, NoopDaemonClient, RrfConfig, SyncLexicalSearch, SyncSearchIterator,
SyncTwoTierSearcher, TwoTierSearcher, blend_two_tier, candidate_count, rrf_fuse,
};
#[cfg(feature = "graph")]
pub use frankensearch_fusion::GraphRanker;
#[cfg(feature = "hash")]
pub use frankensearch_embed::hash_embedder::{HashAlgorithm, HashEmbedder};
#[cfg(feature = "model2vec")]
pub use frankensearch_embed::model2vec_embedder::Model2VecEmbedder;
#[cfg(feature = "fastembed")]
pub use frankensearch_embed::fastembed_embedder::FastEmbedEmbedder;
#[cfg(feature = "lexical")]
pub use frankensearch_lexical::TantivyIndex;
#[cfg(feature = "rerank")]
pub use frankensearch_rerank::{FlashRankReranker, rerank_step};
#[cfg(feature = "fastembed-reranker")]
pub use frankensearch_rerank::FastEmbedReranker;
mod index_builder;
pub use index_builder::{IndexBuildStats, IndexBuilder, IndexProgress};
pub mod prelude {
pub use asupersync::Cx;
pub use crate::{
DocumentFingerprint, Embedder, FederatedConfig, FederatedSearcher, LexicalSearch, Reranker,
ScoreSource, ScoredResult, SearchError, SearchPhase, SearchResult, SyncTwoTierSearcher,
TwoTierConfig, TwoTierMetrics, TwoTierSearcher,
};
#[cfg(feature = "storage")]
pub use crate::{IngestAction, IngestResult, Storage, StorageBackedJobRunner};
#[cfg(feature = "durability")]
pub use crate::{FileProtector, FsviProtector, RepairCodec};
#[cfg(feature = "graph")]
pub use crate::GraphRanker;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn core_types_accessible() {
let _config = TwoTierConfig::default();
let _metrics = TwoTierMetrics::default();
let _rrf = RrfConfig::default();
}
#[test]
fn error_types_accessible() {
let err: SearchError = SearchError::DurabilityDisabled;
let result: SearchResult<()> = Err(err);
assert!(result.is_err());
}
#[test]
fn prelude_provides_essentials() {
fn _takes_cx(_cx: &Cx) {}
use crate::prelude::*;
let _config = TwoTierConfig::default();
let _metrics = TwoTierMetrics::default();
}
#[test]
fn score_source_accessible() {
assert_ne!(ScoreSource::Hybrid, ScoreSource::Lexical);
}
#[test]
fn query_class_accessible() {
let class = QueryClass::classify("hello world");
assert!(matches!(
class,
QueryClass::NaturalLanguage | QueryClass::ShortKeyword
));
}
#[test]
fn traits_are_object_safe() {
fn _takes_embedder(_: &dyn Embedder) {}
fn _takes_reranker(_: &dyn Reranker) {}
fn _takes_lexical(_: &dyn LexicalSearch) {}
fn _takes_metrics(_: &dyn MetricsExporter) {}
}
#[test]
fn utility_functions_accessible() {
let v = l2_normalize(&[3.0, 4.0]);
let norm: f32 = v.iter().map(|x| x * x).sum::<f32>().sqrt();
assert!((norm - 1.0).abs() < 1e-6);
let sim = cosine_similarity(&[1.0, 0.0], &[1.0, 0.0]);
assert!((sim - 1.0).abs() < 1e-6);
}
#[test]
fn indexable_document_accessible() {
let doc = IndexableDocument::new("id", "content").with_title("title");
assert_eq!(doc.id, "id");
}
#[test]
fn embedder_stack_accessible() {
assert!(matches!(
TwoTierAvailability::HashOnly,
TwoTierAvailability::HashOnly
));
}
#[test]
fn sub_crate_modules_accessible() {
let _ = core::error::SearchError::DurabilityDisabled;
let _ = fusion::rrf::RrfConfig::default();
}
#[cfg(feature = "hash")]
#[test]
fn hash_embedder_accessible() {
assert!(matches!(
HashAlgorithm::FnvModular,
HashAlgorithm::FnvModular
));
}
#[cfg(feature = "storage")]
#[test]
fn storage_reexports_accessible() {
let schema_version = storage::SCHEMA_VERSION;
assert!(schema_version >= 1);
let _cfg = StorageConfig::default();
let _queue = JobQueueConfig::default();
assert!(matches!(IngestAction::New, IngestAction::New));
let _ = std::mem::size_of::<StorageBackedJobRunner>();
}
#[cfg(feature = "durability")]
#[test]
fn durability_reexports_accessible() {
let trailer_version = durability::REPAIR_TRAILER_VERSION;
assert!(trailer_version >= 1);
let _ = std::mem::size_of::<DurabilityConfig>();
let _ = std::mem::size_of::<ProtectionResult>();
let _ = std::mem::size_of::<RepairResult>();
let _ = std::mem::size_of::<RepairCodecVerifyResult>();
}
}
#[cfg(test)]
mod feature_matrix_smoke {
use super::*;
fn assert_core_facade_contract() {
let _config = TwoTierConfig::default();
let _metrics = TwoTierMetrics::default();
assert_ne!(ScoreSource::Hybrid, ScoreSource::Lexical);
assert!(matches!(
QueryClass::classify("hybrid search ranking"),
QueryClass::NaturalLanguage | QueryClass::ShortKeyword
));
}
#[cfg(feature = "hash")]
fn assert_hash_exports() {
let embedder = HashEmbedder::default_256();
assert_eq!(embedder.dimension(), 256);
assert!(!embedder.is_semantic());
}
#[cfg(feature = "semantic")]
fn assert_semantic_exports() {
assert_hash_exports();
assert!(std::mem::size_of::<Model2VecEmbedder>() > 0);
assert!(std::mem::size_of::<FastEmbedEmbedder>() > 0);
}
#[cfg(feature = "hybrid")]
fn assert_hybrid_exports() {
assert_semantic_exports();
assert!(std::mem::size_of::<TantivyIndex>() > 0);
}
#[cfg(feature = "persistent")]
fn assert_persistent_exports() {
assert_hybrid_exports();
let _storage_config = StorageConfig::default();
let _job_queue_config = JobQueueConfig::default();
assert!(matches!(IngestAction::New, IngestAction::New));
assert!(std::mem::size_of::<StorageBackedJobRunner>() > 0);
}
#[cfg(feature = "durable")]
fn assert_durable_exports() {
assert_persistent_exports();
let _durability_config = DurabilityConfig::default();
assert!(std::mem::size_of::<FsviProtector>() > 0);
}
#[cfg(feature = "full")]
fn assert_full_exports() {
assert_durable_exports();
let hnsw_config = HnswConfig::default();
assert!(hnsw_config.m > 0);
let _graph_ranker = GraphRanker::new();
assert!(std::mem::size_of::<FlashRankReranker>() > 0);
}
#[cfg(feature = "fts5")]
fn assert_fts5_exports() {
let config = Fts5Config::default();
assert!(config.title_boost > 0.0);
assert!(matches!(Fts5Tokenizer::default(), Fts5Tokenizer::Unicode61));
}
#[cfg(feature = "hash")]
#[test]
fn default_lane_behavior() {
assert_core_facade_contract();
assert_hash_exports();
}
#[cfg(feature = "semantic")]
#[test]
fn semantic_lane_behavior() {
assert_core_facade_contract();
assert_semantic_exports();
}
#[cfg(feature = "hybrid")]
#[test]
fn hybrid_lane_behavior() {
assert_core_facade_contract();
assert_hybrid_exports();
}
#[cfg(feature = "persistent")]
#[test]
fn persistent_lane_behavior() {
assert_core_facade_contract();
assert_persistent_exports();
}
#[cfg(feature = "durable")]
#[test]
fn durable_lane_behavior() {
assert_core_facade_contract();
assert_durable_exports();
}
#[cfg(feature = "full")]
#[test]
fn full_lane_behavior() {
assert_core_facade_contract();
assert_full_exports();
}
#[cfg(feature = "full-fts5")]
#[test]
fn full_fts5_lane_behavior() {
assert_core_facade_contract();
assert_full_exports();
assert_fts5_exports();
}
}