style: Apply cargo fmt and clippy fixes across codebase
Automated formatting and lint corrections from parallel agent work: - cargo fmt: import reordering (alphabetical), line wrapping to respect max width, trailing comma normalization, destructuring alignment, function signature reformatting, match arm formatting - clippy (pedantic): Range::contains() instead of manual comparisons, i64::from() instead of `as i64` casts, .clamp() instead of .max().min() chains, let-chain refactors (if-let with &&), #[allow(clippy::too_many_arguments)] and #[allow(clippy::field_reassign_with_default)] where warranted - Removed trailing blank lines and extra whitespace No behavioral changes. All existing tests pass unmodified. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -138,10 +138,7 @@ pub fn apply_filters(
|
||||
}
|
||||
|
||||
let limit = filters.clamp_limit();
|
||||
sql.push_str(&format!(
|
||||
" ORDER BY j.key LIMIT ?{}",
|
||||
param_idx
|
||||
));
|
||||
sql.push_str(&format!(" ORDER BY j.key LIMIT ?{}", param_idx));
|
||||
params.push(Box::new(limit as i64));
|
||||
|
||||
let param_refs: Vec<&dyn rusqlite::types::ToSql> = params.iter().map(|p| p.as_ref()).collect();
|
||||
|
||||
@@ -39,13 +39,13 @@ pub fn to_fts_query(raw: &str, mode: FtsQueryMode) -> String {
|
||||
.split_whitespace()
|
||||
.map(|token| {
|
||||
// Check if token ends with * and the rest is alphanumeric
|
||||
if token.ends_with('*') {
|
||||
let stem = &token[..token.len() - 1];
|
||||
if !stem.is_empty() && stem.chars().all(|c| c.is_alphanumeric() || c == '_') {
|
||||
// Preserve prefix search: "stem"*
|
||||
let escaped = stem.replace('"', "\"\"");
|
||||
return format!("\"{}\"*", escaped);
|
||||
}
|
||||
if let Some(stem) = token.strip_suffix('*')
|
||||
&& !stem.is_empty()
|
||||
&& stem.chars().all(|c| c.is_alphanumeric() || c == '_')
|
||||
{
|
||||
// Preserve prefix search: "stem"*
|
||||
let escaped = stem.replace('"', "\"\"");
|
||||
return format!("\"{}\"*", escaped);
|
||||
}
|
||||
// Default: wrap in quotes, escape internal quotes
|
||||
let escaped = token.replace('"', "\"\"");
|
||||
|
||||
@@ -4,8 +4,8 @@ use rusqlite::Connection;
|
||||
|
||||
use crate::core::error::Result;
|
||||
use crate::embedding::ollama::OllamaClient;
|
||||
use crate::search::{rank_rrf, search_fts, search_vector, FtsQueryMode};
|
||||
use crate::search::filters::{apply_filters, SearchFilters};
|
||||
use crate::search::filters::{SearchFilters, apply_filters};
|
||||
use crate::search::{FtsQueryMode, rank_rrf, search_fts, search_vector};
|
||||
|
||||
const BASE_RECALL_MIN: usize = 50;
|
||||
const FILTERED_RECALL_MIN: usize = 200;
|
||||
@@ -65,9 +65,9 @@ pub async fn search_hybrid(
|
||||
// Adaptive recall
|
||||
let requested = filters.clamp_limit();
|
||||
let top_k = if filters.has_any_filter() {
|
||||
(requested * 50).max(FILTERED_RECALL_MIN).min(RECALL_CAP)
|
||||
(requested * 50).clamp(FILTERED_RECALL_MIN, RECALL_CAP)
|
||||
} else {
|
||||
(requested * 10).max(BASE_RECALL_MIN).min(RECALL_CAP)
|
||||
(requested * 10).clamp(BASE_RECALL_MIN, RECALL_CAP)
|
||||
};
|
||||
|
||||
let (fts_tuples, vec_tuples) = match mode {
|
||||
@@ -88,10 +88,7 @@ pub async fn search_hybrid(
|
||||
};
|
||||
|
||||
let query_embedding = client.embed_batch(vec![query.to_string()]).await?;
|
||||
let embedding = query_embedding
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap_or_default();
|
||||
let embedding = query_embedding.into_iter().next().unwrap_or_default();
|
||||
|
||||
if embedding.is_empty() {
|
||||
return Err(crate::core::error::LoreError::Other(
|
||||
@@ -115,41 +112,34 @@ pub async fn search_hybrid(
|
||||
.collect();
|
||||
|
||||
match client {
|
||||
Some(client) => {
|
||||
match client.embed_batch(vec![query.to_string()]).await {
|
||||
Ok(query_embedding) => {
|
||||
let embedding = query_embedding
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap_or_default();
|
||||
Some(client) => match client.embed_batch(vec![query.to_string()]).await {
|
||||
Ok(query_embedding) => {
|
||||
let embedding = query_embedding.into_iter().next().unwrap_or_default();
|
||||
|
||||
let vec_tuples = if embedding.is_empty() {
|
||||
warnings.push(
|
||||
"Ollama returned empty embedding, using FTS only.".into(),
|
||||
);
|
||||
Vec::new()
|
||||
} else {
|
||||
let vec_results = search_vector(conn, &embedding, top_k)?;
|
||||
vec_results
|
||||
.iter()
|
||||
.map(|r| (r.document_id, r.distance))
|
||||
.collect()
|
||||
};
|
||||
let vec_tuples = if embedding.is_empty() {
|
||||
warnings
|
||||
.push("Ollama returned empty embedding, using FTS only.".into());
|
||||
Vec::new()
|
||||
} else {
|
||||
let vec_results = search_vector(conn, &embedding, top_k)?;
|
||||
vec_results
|
||||
.iter()
|
||||
.map(|r| (r.document_id, r.distance))
|
||||
.collect()
|
||||
};
|
||||
|
||||
(fts_tuples, vec_tuples)
|
||||
}
|
||||
Err(e) => {
|
||||
warnings.push(
|
||||
format!("Embedding failed ({}), falling back to lexical search.", e),
|
||||
);
|
||||
(fts_tuples, Vec::new())
|
||||
}
|
||||
(fts_tuples, vec_tuples)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warnings.push(format!(
|
||||
"Embedding failed ({}), falling back to lexical search.",
|
||||
e
|
||||
));
|
||||
(fts_tuples, Vec::new())
|
||||
}
|
||||
},
|
||||
None => {
|
||||
warnings.push(
|
||||
"Ollama unavailable, falling back to lexical search.".into(),
|
||||
);
|
||||
warnings.push("Ollama unavailable, falling back to lexical search.".into());
|
||||
(fts_tuples, Vec::new())
|
||||
}
|
||||
}
|
||||
@@ -217,7 +207,7 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
let requested = filters.clamp_limit();
|
||||
let top_k = (requested * 10).max(BASE_RECALL_MIN).min(RECALL_CAP);
|
||||
let top_k = (requested * 10).clamp(BASE_RECALL_MIN, RECALL_CAP);
|
||||
assert_eq!(top_k, 200);
|
||||
}
|
||||
|
||||
@@ -229,7 +219,7 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
let requested = filters.clamp_limit();
|
||||
let top_k = (requested * 50).max(FILTERED_RECALL_MIN).min(RECALL_CAP);
|
||||
let top_k = (requested * 50).clamp(FILTERED_RECALL_MIN, RECALL_CAP);
|
||||
assert_eq!(top_k, 1000);
|
||||
}
|
||||
|
||||
@@ -241,7 +231,7 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
let requested = filters.clamp_limit();
|
||||
let top_k = (requested * 50).max(FILTERED_RECALL_MIN).min(RECALL_CAP);
|
||||
let top_k = (requested * 50).clamp(FILTERED_RECALL_MIN, RECALL_CAP);
|
||||
assert_eq!(top_k, RECALL_CAP); // 5000 capped to 1500
|
||||
}
|
||||
|
||||
@@ -252,7 +242,7 @@ mod tests {
|
||||
..Default::default()
|
||||
};
|
||||
let requested = filters.clamp_limit();
|
||||
let top_k = (requested * 10).max(BASE_RECALL_MIN).min(RECALL_CAP);
|
||||
let top_k = (requested * 10).clamp(BASE_RECALL_MIN, RECALL_CAP);
|
||||
assert_eq!(top_k, BASE_RECALL_MIN); // 10 -> 50
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,11 @@ mod hybrid;
|
||||
mod rrf;
|
||||
mod vector;
|
||||
|
||||
pub use filters::{PathFilter, SearchFilters, apply_filters};
|
||||
pub use fts::{
|
||||
generate_fallback_snippet, get_result_snippet, search_fts, to_fts_query, FtsQueryMode,
|
||||
FtsResult,
|
||||
FtsQueryMode, FtsResult, generate_fallback_snippet, get_result_snippet, search_fts,
|
||||
to_fts_query,
|
||||
};
|
||||
pub use filters::{apply_filters, PathFilter, SearchFilters};
|
||||
pub use rrf::{rank_rrf, RrfResult};
|
||||
pub use vector::{search_vector, VectorResult};
|
||||
pub use hybrid::{search_hybrid, HybridResult, SearchMode};
|
||||
pub use hybrid::{HybridResult, SearchMode, search_hybrid};
|
||||
pub use rrf::{RrfResult, rank_rrf};
|
||||
pub use vector::{VectorResult, search_vector};
|
||||
|
||||
@@ -22,10 +22,7 @@ pub struct RrfResult {
|
||||
/// Ranks are 1-indexed (first result = rank 1).
|
||||
///
|
||||
/// Score = sum of 1/(k + rank) for each list containing the document.
|
||||
pub fn rank_rrf(
|
||||
vector_results: &[(i64, f64)],
|
||||
fts_results: &[(i64, f64)],
|
||||
) -> Vec<RrfResult> {
|
||||
pub fn rank_rrf(vector_results: &[(i64, f64)], fts_results: &[(i64, f64)]) -> Vec<RrfResult> {
|
||||
if vector_results.is_empty() && fts_results.is_empty() {
|
||||
return Vec::new();
|
||||
}
|
||||
@@ -63,14 +60,16 @@ pub fn rank_rrf(
|
||||
.collect();
|
||||
|
||||
// Sort descending by rrf_score
|
||||
results.sort_by(|a, b| b.rrf_score.partial_cmp(&a.rrf_score).unwrap_or(std::cmp::Ordering::Equal));
|
||||
results.sort_by(|a, b| {
|
||||
b.rrf_score
|
||||
.partial_cmp(&a.rrf_score)
|
||||
.unwrap_or(std::cmp::Ordering::Equal)
|
||||
});
|
||||
|
||||
// Normalize: best = 1.0
|
||||
if let Some(max_score) = results.first().map(|r| r.rrf_score) {
|
||||
if max_score > 0.0 {
|
||||
for result in &mut results {
|
||||
result.normalized_score = result.rrf_score / max_score;
|
||||
}
|
||||
if let Some(max_score) = results.first().map(|r| r.rrf_score).filter(|&s| s > 0.0) {
|
||||
for result in &mut results {
|
||||
result.normalized_score = result.rrf_score / max_score;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,8 +91,16 @@ mod tests {
|
||||
|
||||
// Doc 1 score should be higher than doc 2 and doc 3
|
||||
let doc1 = &results[0];
|
||||
let doc2_score = results.iter().find(|r| r.document_id == 2).unwrap().rrf_score;
|
||||
let doc3_score = results.iter().find(|r| r.document_id == 3).unwrap().rrf_score;
|
||||
let doc2_score = results
|
||||
.iter()
|
||||
.find(|r| r.document_id == 2)
|
||||
.unwrap()
|
||||
.rrf_score;
|
||||
let doc3_score = results
|
||||
.iter()
|
||||
.find(|r| r.document_id == 3)
|
||||
.unwrap()
|
||||
.rrf_score;
|
||||
assert!(doc1.rrf_score > doc2_score);
|
||||
assert!(doc1.rrf_score > doc3_score);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ pub fn search_vector(
|
||||
FROM embeddings
|
||||
WHERE embedding MATCH ?1
|
||||
AND k = ?2
|
||||
ORDER BY distance"
|
||||
ORDER BY distance",
|
||||
)?;
|
||||
|
||||
let rows: Vec<(i64, f64)> = stmt
|
||||
@@ -137,11 +137,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_dedup_respects_limit() {
|
||||
let rows = vec![
|
||||
(1000_i64, 0.1_f64),
|
||||
(2000, 0.2),
|
||||
(3000, 0.3),
|
||||
];
|
||||
let rows = vec![(1000_i64, 0.1_f64), (2000, 0.2), (3000, 0.3)];
|
||||
let results = search_vector_dedup(rows, 2);
|
||||
assert_eq!(results.len(), 2);
|
||||
}
|
||||
@@ -161,7 +157,10 @@ mod tests {
|
||||
}
|
||||
let mut results: Vec<VectorResult> = best
|
||||
.into_iter()
|
||||
.map(|(document_id, distance)| VectorResult { document_id, distance })
|
||||
.map(|(document_id, distance)| VectorResult {
|
||||
document_id,
|
||||
distance,
|
||||
})
|
||||
.collect();
|
||||
results.sort_by(|a, b| a.distance.total_cmp(&b.distance));
|
||||
results.truncate(limit);
|
||||
|
||||
Reference in New Issue
Block a user