pub mod dedup;
pub mod types;
use tracing::info;
use crate::agent::Evidence;
use crate::query::QueryIntent;
use types::RerankOutput;
pub async fn process(
_query: &str,
evidence: &[Evidence],
_multi_doc: bool,
intent: QueryIntent,
confidence: f32,
) -> crate::error::Result<RerankOutput> {
let deduped = dedup::dedup(evidence);
if deduped.is_empty() {
info!("No evidence after dedup");
return Ok(RerankOutput {
answer: String::new(),
llm_calls: 0,
confidence: 0.0,
});
}
info!(
evidence = deduped.len(),
intent = %intent,
"Evidence after dedup"
);
let answer = match intent {
QueryIntent::Navigational => format_locations(&deduped),
_ => format_evidence_as_answer(&deduped),
};
info!(
evidence = deduped.len(),
answer_len = answer.len(),
confidence,
"Rerank complete"
);
Ok(RerankOutput {
answer,
llm_calls: 0,
confidence,
})
}
fn format_locations(evidence: &[Evidence]) -> String {
if evidence.is_empty() {
return "No matching locations found.".to_string();
}
let mut result = "Found at:\n".to_string();
for e in evidence {
let doc = e.doc_name.as_deref().unwrap_or("unknown");
result.push_str(&format!(
"- **{}** in {} at {}\n",
e.node_title, doc, e.source_path
));
}
result
}
fn format_evidence_as_answer(evidence: &[Evidence]) -> String {
evidence
.iter()
.map(|e| {
let doc = e.doc_name.as_deref().unwrap_or("");
if doc.is_empty() {
format!("[{}]\n{}", e.node_title, e.content)
} else {
format!("[{} — {}]\n{}", e.node_title, doc, e.content)
}
})
.collect::<Vec<_>>()
.join("\n\n")
}