Skip to main content

_diffctx/config/
scoring.rs

1use once_cell::sync::Lazy;
2
3use super::env_overrides::{read_env_f64, read_env_fraction, read_env_open_fraction};
4
5pub struct EgoScoringConfig {
6    pub identifier_overlap_epsilon: f64,
7    pub identifier_overlap_cap: usize,
8    pub per_hop_decay: f64,
9}
10
11impl Default for EgoScoringConfig {
12    fn default() -> Self {
13        Self {
14            identifier_overlap_epsilon: read_env_fraction("DIFFCTX_EGO_LEXICAL_EPS", 0.1),
15            identifier_overlap_cap: 10,
16            per_hop_decay: read_env_open_fraction("DIFFCTX_EGO_PER_HOP_DECAY", 0.5),
17        }
18    }
19}
20
21pub static EGO: Lazy<EgoScoringConfig> = Lazy::new(EgoScoringConfig::default);
22
23pub struct RrfConfig {
24    pub k: f64,
25}
26
27impl Default for RrfConfig {
28    fn default() -> Self {
29        Self {
30            // k=60 is the Cormack et al. 2009 constant; it damps the top of
31            // each component list so a rank-1 hit in one signal cannot alone
32            // outrank an item both signals agree on at ranks 2-3.
33            k: read_env_f64("DIFFCTX_RRF_K", 60.0).max(1.0),
34        }
35    }
36}
37
38pub fn rrf() -> RrfConfig {
39    RrfConfig::default()
40}
41
42pub struct PitConfig {
43    /// Weight on the structural component. `1 - blend` goes to the lexical one.
44    pub blend: f64,
45    /// Bonus added when both components place a fragment inside their own
46    /// top-`agreement_top_k`.
47    pub agreement_bonus: f64,
48    pub agreement_top_k: usize,
49}
50
51impl Default for PitConfig {
52    fn default() -> Self {
53        Self {
54            // Structural-leaning, because EGO is the measured stronger arm: it
55            // sits 79 cases ahead of RRF on the oracle corpus. An even blend
56            // would start the successor behind the mode it is replacing.
57            blend: read_env_f64("DIFFCTX_PIT_BLEND", 0.65).clamp(0.0, 1.0),
58            // Agreement is worth something but must not dominate a percentile:
59            // both components are in [0, 1], so a bonus above ~0.2 would let
60            // agreement alone outrank a fragment either signal ranks highly.
61            agreement_bonus: read_env_f64("DIFFCTX_PIT_AGREEMENT_BONUS", 0.10).clamp(0.0, 1.0),
62            agreement_top_k: read_env_f64("DIFFCTX_PIT_AGREEMENT_TOP_K", 20.0).max(1.0) as usize,
63        }
64    }
65}
66
67pub fn pit() -> PitConfig {
68    PitConfig::default()
69}