relay-knowledge 1.1.16

Graph-database-based knowledge graph project.
Documentation
use crate::domain::{RerankMode, RetrieverSource};

use super::*;

#[test]
fn local_rerank_promotes_stronger_query_and_entity_match() {
    let hits = vec![
        hit(
            "ev-older",
            "generic runtime notes",
            &["Runtime"],
            vec![RetrieverSource::Bm25],
            0.12,
        ),
        hit(
            "ev-target",
            "SQLite worker isolates blocking writes from async query execution",
            &["SQLiteWorker"],
            vec![RetrieverSource::GraphEvidence, RetrieverSource::Semantic],
            0.10,
        ),
    ];

    let (reranked, diagnostics) = rerank_hits("SQLite async worker", hits, &RerankConfig::local());

    assert_eq!(reranked[0].evidence_id, "ev-target");
    assert_eq!(diagnostics.effective_mode, RerankMode::Local);
    assert!(reranked[0].rerank.is_some());
}

#[test]
fn local_rerank_matches_identifier_parts_in_entity_labels() {
    let hits = vec![
        hit(
            "ev-generic",
            "generic context pack note",
            &["Runtime"],
            vec![RetrieverSource::Bm25],
            0.12,
        ),
        hit(
            "ev-label",
            "opaque retrieval note",
            &["GraphRAGContextPack"],
            vec![RetrieverSource::Semantic, RetrieverSource::Vector],
            0.10,
        ),
    ];

    let (reranked, _) = rerank_hits("graph rag context pack", hits, &RerankConfig::local());

    assert_eq!(reranked[0].evidence_id, "ev-label");
}

#[test]
fn disabled_rerank_preserves_rrf_order_without_item_signal() {
    let config = RerankConfig {
        mode: RerankMode::Disabled,
        model: None,
        timeout: crate::retrieval::DEFAULT_RERANK_TIMEOUT,
        candidate_multiplier: 4,
        max_candidates: 64,
    };
    let hits = vec![
        hit("ev-a", "alpha", &[], vec![RetrieverSource::Bm25], 0.20),
        hit("ev-b", "beta", &[], vec![RetrieverSource::Bm25], 0.10),
    ];

    let (reranked, diagnostics) = rerank_hits("beta", hits, &config);

    assert_eq!(reranked[0].evidence_id, "ev-a");
    assert_eq!(diagnostics.effective_mode, RerankMode::Disabled);
    assert!(reranked.iter().all(|hit| hit.rerank.is_none()));
}

#[test]
fn external_rerank_explanation_reports_effective_local_model() {
    let config = RerankConfig {
        mode: RerankMode::External,
        model: Some("bge-reranker-v2".to_owned()),
        timeout: crate::retrieval::DEFAULT_RERANK_TIMEOUT,
        candidate_multiplier: 4,
        max_candidates: 64,
    };
    let hits = vec![hit(
        "ev-a",
        "rerank diagnostics",
        &[],
        vec![RetrieverSource::Bm25],
        0.20,
    )];

    let (reranked, diagnostics) = rerank_hits("rerank", hits, &config);
    let explanation = &reranked[0]
        .rerank
        .as_ref()
        .expect("external fallback should still attach a local rerank signal")
        .explanation;

    assert_eq!(diagnostics.requested_mode, RerankMode::External);
    assert_eq!(diagnostics.effective_mode, RerankMode::Local);
    assert!(explanation.contains(LOCAL_RERANK_MODEL));
    assert!(!explanation.contains("bge-reranker-v2"));
}

fn hit(
    evidence_id: &str,
    content: &str,
    labels: &[&str],
    sources: Vec<RetrieverSource>,
    score: f64,
) -> RetrievalHit {
    RetrievalHit {
        evidence_id: evidence_id.to_owned(),
        source_scope: "docs".to_owned(),
        source_path: None,
        source_span: None,
        content: content.to_owned(),
        entity_labels: labels.iter().map(|label| (*label).to_owned()).collect(),
        entities: Vec::new(),
        graph_facts: Vec::new(),
        code_artifact: None,
        retriever_sources: sources,
        ranking: Vec::new(),
        rerank: None,
        score,
    }
}