metrale_model_layers/speculative/
draft_stop.rs1static PUBLISHED_TAU: std::sync::OnceLock<f32> = std::sync::OnceLock::new();
19
20pub fn set_draft_confidence_stop(tau: f32) -> anyhow::Result<()> {
23 anyhow::ensure!(
24 tau > 0.0 && tau < 1.0,
25 "--draft-confidence-stop must be in (0, 1), got {tau}"
26 );
27 let got = *PUBLISHED_TAU.get_or_init(|| tau);
28 anyhow::ensure!(
29 got.to_bits() == tau.to_bits(),
30 "draft confidence stop already published as {got}, refusing {tau}"
31 );
32 Ok(())
33}
34
35pub fn draft_stop_logprob() -> Option<f32> {
38 PUBLISHED_TAU.get().map(|t| t.ln())
39}
40
41pub fn chain_depth(lps: &[f32], ln_tau: f32) -> usize {
46 lps.iter()
47 .position(|&lp| lp < ln_tau)
48 .map_or(lps.len(), |j| j + 1)
49}
50
51pub fn chain_continues(lp: f32, ln_tau: f32) -> bool {
53 lp >= ln_tau
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 const LN_HALF: f32 = -std::f32::consts::LN_2;
61
62 #[test]
63 fn a_confident_chain_keeps_every_draft() {
64 assert_eq!(chain_depth(&[-0.1, -0.2, -0.3], LN_HALF), 3);
65 }
66
67 #[test]
68 fn the_chain_ends_with_its_first_unconfident_draft() {
69 assert_eq!(chain_depth(&[-0.1, -2.0, -0.1], LN_HALF), 2);
70 assert_eq!(chain_depth(&[-2.0, -0.1, -0.1], LN_HALF), 1);
71 }
72
73 #[test]
74 fn the_threshold_itself_continues() {
75 assert!(chain_continues(LN_HALF, LN_HALF));
76 assert!(!chain_continues(LN_HALF - 1e-6, LN_HALF));
77 assert_eq!(chain_depth(&[LN_HALF, LN_HALF], LN_HALF), 2);
78 }
79
80 #[test]
81 fn an_empty_chain_is_zero_and_a_lone_draft_is_one() {
82 assert_eq!(chain_depth(&[], LN_HALF), 0);
83 assert_eq!(chain_depth(&[-9.0], LN_HALF), 1);
84 }
85
86 #[test]
87 fn depth_agrees_with_continuation_at_every_position() {
88 let lps = [-0.05, -0.4, -0.3, -1.5, -0.01];
91 let ln_tau = (0.6f32).ln();
92 let mut drafted = 0;
93 for &lp in &lps {
94 drafted += 1;
95 if !chain_continues(lp, ln_tau) {
96 break;
97 }
98 }
99 assert_eq!(drafted, chain_depth(&lps, ln_tau));
100 }
101
102 #[test]
103 fn publication_refuses_out_of_range_values() {
104 for bad in [0.0, 1.0, -0.5, 1.5, f32::NAN] {
105 assert!(set_draft_confidence_stop(bad).is_err(), "{bad} accepted");
106 }
107 }
108}