Commit
Message
Changed Files (8)
-
modified Cargo.lock
diff --git a/Cargo.lock b/Cargo.lock index 38f71c0..c20e828 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,33 +29,25 @@ dependencies = [ "actix-rt", "actix-service", "actix-utils", - "base64 0.22.1", "bitflags", - "brotli", "bytes", "bytestring", "derive_more 2.1.1", "encoding_rs", - "flate2", "foldhash 0.1.5", "futures-core", - "h2 0.3.27", "http 0.2.12", "httparse", "httpdate", "itoa", "language-tags", - "local-channel", "mime", "percent-encoding", "pin-project-lite", - "rand 0.10.1", - "sha1", "smallvec", "tokio", "tokio-util", "tracing", - "zstd", ] [[package]] @@ -77,7 +69,6 @@ dependencies = [ "bytestring", "cfg-if", "http 0.2.12", - "regex", "regex-lite", "serde", "tracing", @@ -148,7 +139,6 @@ dependencies = [ "bytes", "bytestring", "cfg-if", - "cookie 0.16.2", "derive_more 2.1.1", "encoding_rs", "foldhash 0.1.5", @@ -161,7 +151,6 @@ dependencies = [ "mime", "once_cell", "pin-project-lite", - "regex", "regex-lite", "serde", "serde_json", @@ -232,21 +221,6 @@ dependencies = [ "equator", ] -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195" -dependencies = [ - "alloc-no-stdlib", -] - [[package]] name = "allocator-api2" version = "0.2.21" @@ -473,36 +447,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-buffer" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "brotli" -version = "8.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc91aac060a7a1e25823bdccbfb6af1875b88f17c6daac97894eed8207166b3" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "5.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - [[package]] name = "bstr" version = "1.12.1" @@ -591,17 +535,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chacha20" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "rand_core 0.10.1", -] - [[package]] name = "chrono" version = "0.4.45" @@ -740,12 +673,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "const-oid" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" - [[package]] name = "convert_case" version = "0.10.0" @@ -755,17 +682,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - [[package]] name = "cookie" version = "0.18.1" @@ -783,7 +699,7 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" dependencies = [ - "cookie 0.18.1", + "cookie", "document-features", "idna", "indexmap", @@ -830,15 +746,6 @@ dependencies = [ "libc", ] -[[package]] -name = "cpufeatures" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.5.0" @@ -889,15 +796,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "crypto-common" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" -dependencies = [ - "hybrid-array", -] - [[package]] name = "cssparser" version = "0.31.2" @@ -1058,19 +956,8 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", - "crypto-common 0.1.7", -] - -[[package]] -name = "digest" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" -dependencies = [ - "block-buffer 0.12.1", - "const-oid", - "crypto-common 0.2.2", + "block-buffer", + "crypto-common", ] [[package]] @@ -1505,7 +1392,6 @@ dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "rand_core 0.10.1", ] [[package]] @@ -1542,25 +1428,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "h2" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.15" @@ -1761,15 +1628,6 @@ dependencies = [ "libm", ] -[[package]] -name = "hybrid-array" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" -dependencies = [ - "typenum", -] - [[package]] name = "hyper" version = "1.10.1" @@ -1780,7 +1638,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.15", + "h2", "http 1.4.2", "http-body", "httparse", @@ -2216,17 +2074,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" -[[package]] -name = "local-channel" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" -dependencies = [ - "futures-core", - "futures-sink", - "local-waker", -] - [[package]] name = "local-waker" version = "0.1.4" @@ -3140,17 +2987,6 @@ dependencies = [ "rand_core 0.9.5", ] -[[package]] -name = "rand" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" -dependencies = [ - "chacha20", - "getrandom 0.4.3", - "rand_core 0.10.1", -] - [[package]] name = "rand_chacha" version = "0.3.1" @@ -3189,12 +3025,6 @@ dependencies = [ "getrandom 0.3.4", ] -[[package]] -name = "rand_core" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" - [[package]] name = "rav1e" version = "0.8.1" @@ -3348,7 +3178,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.4.15", + "h2", "http 1.4.2", "http-body", "http-body-util", @@ -3706,17 +3536,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "sha1" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "digest 0.11.3", -] - [[package]] name = "sha2" version = "0.10.9" @@ -3724,8 +3543,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures 0.2.17", - "digest 0.10.7", + "cpufeatures", + "digest", ] [[package]] @@ -5038,34 +4857,6 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.16+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" -dependencies = [ - "cc", - "pkg-config", -] - [[package]] name = "zune-core" version = "0.5.1" -
modified Cargo.toml
diff --git a/Cargo.toml b/Cargo.toml index bff7293..d4ea96f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,15 +4,19 @@ version = "0.5.2" edition = "2021" rust-version = "1.88.0" +[features] +default = ["tagging"] +tagging = ["fastembed"] + [dependencies] -actix-web = "4" +actix-web = { version = "4", default-features = false, features = ["macros", "compat-routing-macros-force-pub"] } anyhow = "1.0" async-trait = "0.1" chrono = { version = "0.4", features = ["serde"] } clap = { version = "4.5", features = ["derive"] } colored = "2" directories = "6" -fastembed = "5" +fastembed = { version = "5", optional = true } figment = { version = "0.10", features = ["toml"] } htmd = "0.5" scraper = "0.20" @@ -25,7 +29,7 @@ serde_json = "1.0" tempfile = "3" tera = "1.8" toml = "0.8" -tokio = { version = "1.0", features = ["full"] } +tokio = { version = "1.0", features = ["rt-multi-thread", "macros", "signal", "sync", "time", "fs"] } futures = "0.3" tracing = "0.1" tracing-subscriber = "0.3" -
modified README.md
diff --git a/README.md b/README.md index 19542e9..4b825f3 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ A local search engine for your browser bookmarks and history. Import bookmarks/history from Firefox, Zen, Chrome, or Chromium, search them with full-text queries, and optionally forward searches to external engines like wikipedia or SearXNG (aggregates results from dozens of backends). Content can be automatically tagged via local ONNX embeddings (opt-in; set `tagging_enabled = true` in config). +The ONNX tagging model is embedded via the optional `tagging` feature (included by default). If you don't need auto-tagging, you can build a ~30% smaller binary by excluding it. + ## Install **Binaries** are available at [vit.am/~ololduck/search_hub/latest](https://vit.am/~ololduck/search_hub/latest/). Download the binary for your architecture, extract, and run. @@ -18,6 +20,14 @@ cargo install --path . This installs the `search_hub` binary to `~/.cargo/bin/search_hub`. +**Smaller binary (no ONNX tagging):** If you don't need auto-tagging, skip the ~12 MiB ONNX Runtime dependency: + +```sh +cargo install --path . --no-default-features +``` + +The resulting binary still supports all features except semantic tagging. Any `search_hub retag` or auto-tagging operation will advise you to rebuild with `--features tagging`. + To update later, pull the latest code and reinstall. ## First steps @@ -69,7 +79,7 @@ Without `?js=true`, the server waits for all external engines before sending the All commands use `~/.local/share/search_hub/bookmarks.db` by default. Override with `--db-path` or set `db_path` in the config file. -The first time you use a search or insert command, SearchHub downloads an ONNX embedding model to `$XDG_CACHE_DIR` (defaults to `~/.cache/search_hub`) (about 127 MB). +The first time you use a tagging-enabled command (`search_hub insert`, `search_hub retag`, or import with `tagging_enabled = true`), SearchHub downloads an ONNX embedding model to `$XDG_CACHE_DIR` (defaults to `~/.cache/search_hub`) (about 127 MB). This only applies if the binary was built with the `tagging` feature (default: on). ## Configuration -
modified src/main.rs
diff --git a/src/main.rs b/src/main.rs index c7909aa..c5a4b26 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,9 @@ use search_hub::importer::zen::ZenImporter; use search_hub::importer::Importer; use search_hub::models::Bookmark; use search_hub::storage; -use search_hub::tagging::{default_tags, TagDef, TaggingEngine}; +use search_hub::tagging::{default_tags, TagDef}; +#[cfg(feature = "tagging")] +use search_hub::tagging::TaggingEngine; use search_hub::web; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, VecDeque}; @@ -314,12 +316,12 @@ async fn main() { None => Config::load(), }; let engines = config.engines.clone(); - let tagging_enabled = config.tagging_enabled.unwrap_or(false); - let tag_threshold: f32 = config.tagging_threshold.map(|t| t as f32).unwrap_or(0.60); + let _tagging_enabled = config.tagging_enabled.unwrap_or(false); + let _tag_threshold: f32 = config.tagging_threshold.map(|t| t as f32).unwrap_or(0.60); let exclude_hosts: Vec<String> = config.exclude_urls.clone().unwrap_or_else(|| { vec!["localhost".into(), "127.0.0.1".into(), "::1".into()] }); - let tags: Vec<TagDef> = if config.tags.is_empty() { + let _tags: Vec<TagDef> = if config.tags.is_empty() { default_tags() } else { config.tags.clone() @@ -327,9 +329,9 @@ async fn main() { let bind_address = config.bind_address.clone().unwrap_or_else(|| "127.0.0.1".into()); let page_size = config.page_size.unwrap_or(20); let workers = config.workers.unwrap_or(2); - let onnx_model = config.onnx_model.clone().unwrap_or_else(|| "BGESmallENV15".into()); - let truncation = config.truncation.unwrap_or(2000); - let max_tags = config.max_tags.unwrap_or(5); + let _onnx_model = config.onnx_model.clone().unwrap_or_else(|| "BGESmallENV15".into()); + let _truncation = config.truncation.unwrap_or(2000); + let _max_tags = config.max_tags.unwrap_or(5); let cache_dir = directories::ProjectDirs::from("com", "search_hub", "search_hub") .map(|d| d.cache_dir().to_path_buf()) .unwrap_or_else(|| { @@ -405,21 +407,22 @@ async fn main() { } else { fetch_and_convert(&mut fetcher, &url, None) }; - let md = content.as_ref().and_then(|c| { - if !tagging_enabled { + #[cfg(feature = "tagging")] + let tags_val = content.as_ref().and_then(|c| { + if !_tagging_enabled { info!("tagging disabled via config"); return None; } info!("tagging content..."); - match TaggingEngine::new(&tags, tag_threshold, max_tags, truncation, &onnx_model) { + match TaggingEngine::new(&_tags, _tag_threshold, _max_tags, _truncation, &_onnx_model) { Ok(mut engine) => { - let tags = engine.tags_for(c).unwrap_or_default(); - if tags.is_empty() { + let t = engine.tags_for(c).unwrap_or_default(); + if t.is_empty() { info!("no tags matched"); None } else { - info!("tags: {}", tags.join(", ")); - Some(tags.join(", ")) + info!("tags: {}", t.join(", ")); + Some(t.join(", ")) } } Err(e) => { @@ -429,6 +432,14 @@ async fn main() { } }); + #[cfg(not(feature = "tagging"))] + let tags_val: Option<String> = { + if _tagging_enabled { + eprintln!("Warning: tagging not available in this build. Rebuild with 'cargo install --features tagging' to enable it."); + } + None + }; + let bookmark = Bookmark { id: 0, title, @@ -436,7 +447,7 @@ async fn main() { description, source: "bookmark".into(), content, - tags: md, + tags: tags_val, created_at: Utc::now(), }; storage::insert_bookmark(&conn, &bookmark).expect("Failed to insert bookmark"); @@ -472,8 +483,9 @@ async fn main() { print_bookmark(&b); } } + #[cfg(feature = "tagging")] Command::Retag { id, all, db_path } => { - if !tagging_enabled { + if !_tagging_enabled { println!("Tagging is disabled in config. Enable it with tagging_enabled = true."); return; } @@ -481,7 +493,7 @@ async fn main() { let db_path = resolve_db_path(db_path, config.db_path.as_deref()); let conn = storage::init_db(&db_path.to_string_lossy()).expect("Failed to open database"); - let mut engine = match TaggingEngine::new(&tags, tag_threshold, max_tags, truncation, &onnx_model) { + let mut engine = match TaggingEngine::new(&_tags, _tag_threshold, _max_tags, _truncation, &_onnx_model) { Ok(e) => e, Err(e) => { eprintln!("Warning: failed to initialize tagger: {e}"); @@ -589,6 +601,11 @@ async fn main() { pb.finish_with_message(format!("{} {} tagged, {} {} skipped", "✔", tagged, "✘", skipped)); } + + #[cfg(not(feature = "tagging"))] + Command::Retag { .. } => { + println!("Tagging is not available in this build. Rebuild with 'cargo install --features tagging' to enable it."); + } Command::InitConfig => { let path = config_path.clone().unwrap_or_else(config_file_path); if path.exists() { @@ -724,15 +741,15 @@ fn resolve_profiles(importer: &(impl Importer + ?Sized), profile: Option<String> } async fn run_import(source: &str, profile: Option<String>, db_path: &str, config: &Config, kind: ImportKind, cache_path: PathBuf) { - let tagging_enabled = config.tagging_enabled.unwrap_or(false); - let tag_threshold: f32 = config.tagging_threshold.map(|t| t as f32).unwrap_or(0.60); - let tags: Vec<TagDef> = if config.tags.is_empty() { default_tags() } else { config.tags.clone() }; + let _tagging_enabled = config.tagging_enabled.unwrap_or(false); + let _tag_threshold: f32 = config.tagging_threshold.map(|t| t as f32).unwrap_or(0.60); + let _tags: Vec<TagDef> = if config.tags.is_empty() { default_tags() } else { config.tags.clone() }; let exclude_hosts: Vec<String> = config.exclude_urls.clone().unwrap_or_else(|| { vec!["localhost".into(), "127.0.0.1".into(), "::1".into()] }); - let max_tags = config.max_tags.unwrap_or(5); - let truncation = config.truncation.unwrap_or(2000); - let onnx_model = config.onnx_model.clone().unwrap_or_else(|| "BGESmallENV15".into()); + let _max_tags = config.max_tags.unwrap_or(5); + let _truncation = config.truncation.unwrap_or(2000); + let _onnx_model = config.onnx_model.clone().unwrap_or_else(|| "BGESmallENV15".into()); let importer: Box<dyn Importer> = match source { "firefox" => Box::new(FirefoxImporter), @@ -847,12 +864,16 @@ async fn run_import(source: &str, profile: Option<String>, db_path: &str, config let tx = tx.clone(); let bar = bar.clone(); let db = db.clone(); - let task_tags = tags.clone(); - let task_threshold = tag_threshold; let task_exclude = exclude_hosts.to_vec(); - let task_tagging_enabled = tagging_enabled; let task_cache = cache_path.clone(); - let task_onnx = onnx_model.clone(); + #[cfg(feature = "tagging")] + let task_tags = _tags.clone(); + #[cfg(feature = "tagging")] + let task_threshold = _tag_threshold; + #[cfg(feature = "tagging")] + let task_tagging_enabled = _tagging_enabled; + #[cfg(feature = "tagging")] + let task_onnx = _onnx_model.clone(); tokio::task::spawn_blocking(move || { let mut fetcher = match Fetcher::new(task_cache) { Ok(f) => f, @@ -861,8 +882,9 @@ async fn run_import(source: &str, profile: Option<String>, db_path: &str, config return; } }; + #[cfg(feature = "tagging")] let mut tagger = if task_tagging_enabled { - TaggingEngine::new(&task_tags, task_threshold, max_tags, truncation, &task_onnx).ok() + TaggingEngine::new(&task_tags, task_threshold, _max_tags, _truncation, &task_onnx).ok() } else { None }; @@ -875,9 +897,12 @@ async fn run_import(source: &str, profile: Option<String>, db_path: &str, config continue; } if let Some(md) = fetch_and_convert(&mut fetcher, url, Some(task_id)) { + #[cfg(feature = "tagging")] let entry_tags = tagger.as_mut() .and_then(|e| e.tags_for(&md).ok()) .unwrap_or_default(); + #[cfg(not(feature = "tagging"))] + let entry_tags: Vec<String> = Vec::new(); let tags_str = if entry_tags.is_empty() { None } else { Some(entry_tags.join(", ")) }; storage::update_bookmark_content_tags( &conn, *rowid, Some(&md), tags_str.as_deref(), -
modified src/tagging.rs
diff --git a/src/tagging.rs b/src/tagging.rs index 27ee9cb..6778a09 100644 --- a/src/tagging.rs +++ b/src/tagging.rs @@ -1,9 +1,13 @@ -use fastembed::{EmbeddingModel, TextEmbedding, TextInitOptions}; -use fastembed::similarity::cosine_similarity; use serde::Deserialize; +#[cfg(feature = "tagging")] use std::path::PathBuf; -/// Return the standard cache directory for ONNX embedding models. +#[cfg(feature = "tagging")] +use fastembed::{EmbeddingModel, TextEmbedding, TextInitOptions}; +#[cfg(feature = "tagging")] +use fastembed::similarity::cosine_similarity; + +#[cfg(feature = "tagging")] fn cache_dir_for_models() -> PathBuf { let dirs = directories::ProjectDirs::from("com", "search_hub", "search_hub") .expect("no valid cache directory"); @@ -12,6 +16,7 @@ fn cache_dir_for_models() -> PathBuf { cache_dir } +#[cfg(feature = "tagging")] fn parse_model(name: &str) -> anyhow::Result<EmbeddingModel> { Ok(match name { "AllMiniLML6V2" => EmbeddingModel::AllMiniLML6V2, @@ -182,18 +187,7 @@ pub fn default_tags() -> Vec<TagDef> { ] } -/// Engine that embeds content and scores it against tag prototypes using cosine similarity. -/// -/// # Example -/// -/// ```ignore -/// let tags = search_hub::tagging::default_tags(); -/// let mut engine = search_hub::tagging::TaggingEngine::new(&tags, 0.40, 5, 2000, "BGESmallENV15") -/// .expect("failed to init tagging engine"); -/// let matched = engine.tags_for("the rust programming language borrow checker") -/// .expect("tagging failed"); -/// assert!(matched.contains(&"rust".to_string())); -/// ``` +#[cfg(feature = "tagging")] pub struct TaggingEngine { model: TextEmbedding, tag_examples: Vec<(String, Vec<Vec<f32>>)>, @@ -202,6 +196,7 @@ pub struct TaggingEngine { truncation: usize, } +#[cfg(feature = "tagging")] impl TaggingEngine { /// Create a new tagging engine. /// -
modified src/web/handlers.rs
diff --git a/src/web/handlers.rs b/src/web/handlers.rs index 66f5559..007a5b2 100644 --- a/src/web/handlers.rs +++ b/src/web/handlers.rs @@ -149,6 +149,7 @@ async fn index(templates: web::Data<Tera>, cfg: web::Data<ServerConfig>) -> impl let mut ctx = tera::Context::new(); ctx.insert("version", VERSION); ctx.insert("port", &cfg.port); + ctx.insert("tagging_feature", &cfg!(feature = "tagging")); match templates.render("index.html", &ctx) { Ok(rendered) => HttpResponse::Ok().content_type("text/html").body(rendered), Err(e) => { @@ -267,6 +268,7 @@ async fn search( ctx.insert("external_results", &external_results); ctx.insert("external_engines", &external_engines); ctx.insert("shortcuts", &shortcuts_help); + ctx.insert("tagging_feature", &cfg!(feature = "tagging")); match templates.render("index.html", &ctx) { Ok(rendered) => HttpResponse::Ok().content_type("text/html").body(rendered), -
modified templates/index.html
diff --git a/templates/index.html b/templates/index.html index ddc54d3..abe752e 100644 --- a/templates/index.html +++ b/templates/index.html @@ -492,6 +492,10 @@ {% endif %} <h2>browser integration</h2> <div class="help-row"><span class="help-key">?js=true</span><span class="help-desc">add to your browser's search engine URL for faster loading</span></div> +{% if not tagging_feature %} + <h2>build</h2> + <div class="help-row"><span class="help-key">--features tagging</span><span class="help-desc">rebuild with ONNX tagging support</span></div> +{% endif %} </div> </div> -
modified tests/tagging_thresholds.rs
diff --git a/tests/tagging_thresholds.rs b/tests/tagging_thresholds.rs index c0889db..6f6b6a0 100644 --- a/tests/tagging_thresholds.rs +++ b/tests/tagging_thresholds.rs @@ -1,3 +1,5 @@ +#![cfg(feature = "tagging")] + use search_hub::tagging::{default_tags, TaggingEngine}; struct Sample {