coding_agent_search/search/fastembed_reranker.rs
1//! FastEmbed-based cross-encoder reranker (ms-marco-MiniLM-L-6-v2).
2//!
3//! Re-exports [`FastEmbedReranker`] from `frankensearch::rerank::fastembed_reranker`.
4//! The implementation lives in the `frankensearch-rerank` crate.
5//!
6//! # `semantic` feature gate (cass#256)
7//!
8//! When the `semantic` Cargo feature is **disabled** (i.e. baseline build), the
9//! upstream `frankensearch::FastEmbedReranker` is not available because
10//! `frankensearch/fastembed-reranker` is the feature path that drags in
11//! `fastembed` and the prebuilt Microsoft ONNX Runtime binary. In that build a
12//! local stub `FastEmbedReranker` is exposed: it has the same public surface
13//! the rest of the crate relies on (`default_model_dir`, `load_from_dir`,
14//! `reranker_id_static`) but the loader returns a stable
15//! `RerankerError::RerankerUnavailable` and the reranker cannot be
16//! instantiated. Lexical search remains fully available.
17
18#[cfg(feature = "semantic")]
19pub use frankensearch::FastEmbedReranker;
20
21#[cfg(not(feature = "semantic"))]
22pub use stub::FastEmbedReranker;
23
24#[cfg(not(feature = "semantic"))]
25mod stub {
26 use std::path::{Path, PathBuf};
27
28 use crate::search::reranker::{Reranker, RerankerError, RerankerResult};
29 use frankensearch::{RerankDocument, RerankScore};
30
31 const MS_MARCO_RERANKER_ID: &str = "ms-marco-minilm-l6-v2";
32 const MS_MARCO_DIR_NAME: &str = "ms-marco-MiniLM-L-6-v2";
33
34 /// Baseline-build stub for the cross-encoder reranker.
35 ///
36 /// `FastEmbedReranker` cannot actually be instantiated in this build -
37 /// [`load_from_dir`] always returns `RerankerError::RerankerUnavailable`.
38 /// The struct and `Reranker` impl exist purely so existing
39 /// `Arc<dyn Reranker>` plumbing (`reranker_registry`, `daemon::models`, etc.)
40 /// keeps compiling.
41 pub struct FastEmbedReranker {
42 _private: (),
43 }
44
45 impl FastEmbedReranker {
46 /// Stable reranker identifier (matches the upstream constant so
47 /// metadata/JSON contracts remain stable across baseline and full
48 /// builds).
49 pub fn reranker_id_static() -> &'static str {
50 MS_MARCO_RERANKER_ID
51 }
52
53 /// Default model directory relative to the cass data dir. Mirrors
54 /// the layout used by the full build so the model_manager's
55 /// "is this on disk?" probes return the same answer either way.
56 pub fn default_model_dir(data_dir: &Path) -> PathBuf {
57 data_dir.join("models").join(MS_MARCO_DIR_NAME)
58 }
59
60 /// Baseline-build stub: see the module-level note on cass#256.
61 pub fn load_from_dir(_model_dir: &Path) -> RerankerResult<Self> {
62 Err(RerankerError::RerankerUnavailable {
63 model: MS_MARCO_RERANKER_ID.to_string(),
64 })
65 }
66 }
67
68 impl Reranker for FastEmbedReranker {
69 fn rerank_sync(
70 &self,
71 _query: &str,
72 _documents: &[RerankDocument],
73 ) -> RerankerResult<Vec<RerankScore>> {
74 Err(RerankerError::RerankerUnavailable {
75 model: MS_MARCO_RERANKER_ID.to_string(),
76 })
77 }
78
79 fn id(&self) -> &str {
80 MS_MARCO_RERANKER_ID
81 }
82
83 fn model_name(&self) -> &str {
84 MS_MARCO_DIR_NAME
85 }
86
87 fn is_available(&self) -> bool {
88 false
89 }
90 }
91}