flutter_hybrid_search 1.2.0
flutter_hybrid_search: ^1.2.0 copied to clipboard
Offline hybrid search for Flutter: HNSW vector similarity, FTS5 full-text, typo-tolerant matching, and pluggable reranking — no cloud required.
1.2.0 #
Added #
ScoreBreakdown— new model that exposes the individual contribution of each ranking signal (vectorScore,ftsScore,typoScore,conciseScore,totalScore). EverySearchResultproduced byHeuristicRerankernow carries a populatedbreakdownfield, making it easy to debug rankings and build explainability UI.SearchResult.breakdown— optionalScoreBreakdown?field onSearchResult.nullfor custom rerankers that don't opt in; non-null for the defaultHeuristicReranker.SearchResult.copyWith()— create a modified copy of a result without touching other fields.HybridSearchEngine.addEntries()— add new entries and their embeddings to a live engine without recreating it. Automatically rebuilds the HNSW index when the corpus crosseshnswThreshold.HybridSearchEngine.removeEntries()— remove entries by id from a live engine. Rebuilds or clears the HNSW index as needed. Unknown ids are silently ignored.HybridSearchConfig.minScore— minimum composite score threshold (default0.0). Results below this value are discarded after reranking, letting you enforce a quality floor without post-processing the list yourself.SearchEntry.metadata— arbitraryMap<String, Object?>for domain-specific key-value data (priority, tags, dates, etc.). Defaults to an empty map — fully backward compatible. Persists as JSON when you pass ametadataColumntoSearchEntry.fromMap()/SearchEntry.toMap().
Improved #
- Internal embedding storage refactored from a contiguous
Listto a sparseMap<int, Embedding>keyed by SQLite id. This makes incremental adds and removes correct in all cases (non-contiguous ids, gaps after deletion) without any SQLite ID remapping. - HNSW items are now tagged by their SQLite id instead of a list index,
removing the
index + 1offset that would have become incorrect after removals.
1.1.0 #
Added #
- Structured logging via
package:logging— the engine logs initialization timing, per-query phase breakdown, FTS errors, and cache hits. Attach a handler toLogger('HybridSearchEngine')to see diagnostics. SearchMetadata— new model with per-phase timing (embed, vector, FTS, typo, rerank, total) and candidate counts.searchWithMetadata()— returns({List<SearchResult> results, SearchMetadata metadata})for performance profiling.searchBatch()— search multiple queries in one call, reusing engine state and embed cache.Embeddingtypedef —typedef Embedding = Float32Listfor improved API readability.- Embed cache — LRU cache for
Embedder.embed()results. Configurable viaembedCacheSizeconstructor parameter (default: 32, set 0 to disable).
Improved #
- Embedding dimension validation — constructor now eagerly validates that
every embedding vector matches
config.embeddingDim, throwing a clearArgumentErroron mismatch instead of crashing later in cosine computation. - Config validation —
HybridSearchConfignow asserts that numeric parameters are positive and thathnswSearchK >= candidatePoolSize. - Float16Store validation —
decode()now throwsFormatExceptionwhen the header declares zero vectors or zero dimensions. - Race-safe initialization — concurrent
initialize()calls are now safe: uses aCompleterso only one init runs and others await it. - FTS error handling —
_ftsSearch()now catches specificDatabaseExceptionandStateErrortypes and logs them viapackage:logginginstead of silently swallowing all exceptions withcatch (_). - Loop-unrolled cosine & L2 norm — inner loops process 4 elements per iteration for better throughput on large vectors (128+ dims).
1.0.2 #
Added #
HybridSearchEngine.isInitializedgetter — check engine state without try/catch.HybridSearchEngine.entryCountgetter — number of embeddings managed by the engine, available immediately after construction.HybridSearchConfig.copyWith()— create a tweaked copy without repeating every field.
Improved #
dispose()is now idempotent (safe to call multiple times) and guards against use-after-dispose: callingsearch()orinitialize()afterdispose()throws a clearStateError.- Typo-tolerance
_canDroprewritten from O(n²) substring concatenation to O(n) two-pointer scan — eliminates temporary string allocations. SearchRankingRegExp instances are now compiled once and cached as static finals instead of being re-created on every call.
1.0.1 #
Improvements in documentation and metadata
1.0.0 #
Initial release.
Added #
HybridSearchEngine— offline hybrid search combining vector similarity, FTS5 full-text search, typo-tolerant matching, and heuristic reranking.Embedder— abstract interface for plugging in any embedding model (BERT, sentence-transformers, TF-IDF, etc.).SearchEntry— immutable Q&A entry with configurable column mapping.SearchResult— search match carrying entry, score, and method identifier.HybridSearchConfig— all engine parameters in one place (pool sizes, HNSW thresholds, database schema column names).SearchRanking— pure static utilities: FTS query building, typo tolerance, concise-match boost, perfect-match shortcutting.HeuristicReranker— rule-based reranker (FTS + typo + concise boosts, deduplication by question text).RerankerInterface— contract for custom reranker implementations.Float16Store— decoder for the compact Float16 binary embedding format produced by the companion Python training pipeline.