@@ -89,6 +89,26 @@ const HYBRID: Mode = Mode {
|
|||||||
keyword_weight: 0.3,
|
keyword_weight: 0.3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Every 0.1 step of vector weight, keyword weight taking the remainder.
|
||||||
|
///
|
||||||
|
/// Labels are leaked to `&'static str` because `Mode::label` is a `&'static
|
||||||
|
/// str` for the eleven named modes and a sweep is a short-lived process; the
|
||||||
|
/// alternative is threading a lifetime through the whole report path for a
|
||||||
|
/// diagnostic mode.
|
||||||
|
#[cfg(feature = "embeddings")]
|
||||||
|
fn sweep_modes() -> Vec<Mode> {
|
||||||
|
(0..=10)
|
||||||
|
.map(|i| {
|
||||||
|
let v = i as f32 / 10.0;
|
||||||
|
Mode {
|
||||||
|
label: Box::leak(format!("sweep v={v:.1} / k={:.1}", 1.0 - v).into_boxed_str()),
|
||||||
|
vector_weight: v,
|
||||||
|
keyword_weight: 1.0 - v,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Text -> embedding, built once for the whole corpus.
|
/// Text -> embedding, built once for the whole corpus.
|
||||||
type EmbeddingMap = HashMap<String, Vec<f32>>;
|
type EmbeddingMap = HashMap<String, Vec<f32>>;
|
||||||
|
|
||||||
@@ -651,6 +671,7 @@ fn main() {
|
|||||||
let mut json_path: Option<String> = None;
|
let mut json_path: Option<String> = None;
|
||||||
let mut limit: Option<usize> = None;
|
let mut limit: Option<usize> = None;
|
||||||
let mut weights_dir: Option<String> = None;
|
let mut weights_dir: Option<String> = None;
|
||||||
|
let mut sweep = false;
|
||||||
let mut args = std::env::args().skip(1);
|
let mut args = std::env::args().skip(1);
|
||||||
while let Some(arg) = args.next() {
|
while let Some(arg) = args.next() {
|
||||||
match arg.as_str() {
|
match arg.as_str() {
|
||||||
@@ -658,6 +679,7 @@ fn main() {
|
|||||||
let v = args.next().expect("--limit needs a value");
|
let v = args.next().expect("--limit needs a value");
|
||||||
limit = Some(v.parse().expect("--limit must be a positive integer"));
|
limit = Some(v.parse().expect("--limit must be a positive integer"));
|
||||||
}
|
}
|
||||||
|
"--sweep" => sweep = true,
|
||||||
"--embeddings" => {
|
"--embeddings" => {
|
||||||
weights_dir = Some(args.next().expect("--embeddings needs a directory"));
|
weights_dir = Some(args.next().expect("--embeddings needs a directory"));
|
||||||
}
|
}
|
||||||
@@ -675,7 +697,10 @@ fn main() {
|
|||||||
and tokenizer.json. Enables the vector stage and reports\n\
|
and tokenizer.json. Enables the vector stage and reports\n\
|
||||||
BM25-only, vector-only, and hybrid separately. Requires\n\
|
BM25-only, vector-only, and hybrid separately. Requires\n\
|
||||||
--features embeddings; without it the vector stage is\n\
|
--features embeddings; without it the vector stage is\n\
|
||||||
inert and only the BM25 row is produced."
|
inert and only the BM25 row is produced.\n\
|
||||||
|
--sweep instead of the three named modes, sweep vector_weight\n\
|
||||||
|
from 0.0 to 1.0 in 0.1 steps. The 0.7/0.3 default was\n\
|
||||||
|
never searched; this is what searches it."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -736,13 +761,20 @@ fn main() {
|
|||||||
let modes: Vec<Mode> = if embeddings.is_some() {
|
let modes: Vec<Mode> = if embeddings.is_some() {
|
||||||
#[cfg(feature = "embeddings")]
|
#[cfg(feature = "embeddings")]
|
||||||
{
|
{
|
||||||
vec![BM25_ONLY, VECTOR_ONLY, HYBRID]
|
if sweep {
|
||||||
|
sweep_modes()
|
||||||
|
} else {
|
||||||
|
vec![BM25_ONLY, VECTOR_ONLY, HYBRID]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "embeddings"))]
|
#[cfg(not(feature = "embeddings"))]
|
||||||
{
|
{
|
||||||
vec![BM25_ONLY]
|
vec![BM25_ONLY]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if sweep {
|
||||||
|
eprintln!("warning: --sweep needs --embeddings; running BM25 only");
|
||||||
|
}
|
||||||
vec![BM25_ONLY]
|
vec![BM25_ONLY]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user