use token_sampling::{
ChainConfig, Dry, MinP, Penalties, SamplerChain, SplitMix64, TailFree, Temperature, TopK, TopP,
Typical, Xtc,
};
#[test]
fn arbitrary_inputs_finish_with_a_token_or_typed_error() {
let mut state = 0x243f_6a88_85a3_08d3_u64;
for case in 0..=512 {
let size = if case == 512 { 4096 } else { case % 257 };
let mut logits = (0..size)
.map(|index| match (case + index) % 41 {
0 => f32::NAN,
1 => f32::INFINITY,
2 => f32::NEG_INFINITY,
_ => {
state = state
.wrapping_mul(6_364_136_223_846_793_005)
.wrapping_add(1);
((state >> 40) as f32 / (1_u32 << 24) as f32) * 40.0 - 20.0
}
})
.collect::<Vec<_>>();
let history = (0..case % 384)
.map(|value| (value % 311) as u32)
.collect::<Vec<_>>();
let config = ChainConfig {
penalties: Penalties {
last_n: case as i32 - 100,
repeat: (case as f32 - 200.0) / 50.0,
freq: (case as f32 - 256.0) / 30.0,
presence: (case as f32 - 128.0) / 20.0,
},
dry: Dry {
multiplier: 0.5 + (case % 13) as f32 / 10.0,
base: 1.0 + (case % 9) as f32 / 20.0,
allowed_length: (case % 7) as i32,
last_n: 8 + (case % 96) as i32,
breakers: vec![vec![], vec![1], vec![2, 3]],
},
top_k: TopK {
k: case as i32 - 64,
},
tail_free: TailFree {
z: (case as f32 - 128.0) / 128.0,
min_keep: case % 8,
},
typical: Typical {
p: (case as f32 - 128.0) / 128.0,
min_keep: case % 8,
},
top_p: TopP {
p: (case as f32 - 128.0) / 128.0,
min_keep: case % 8,
},
min_p: MinP {
p: (case as f32 - 128.0) / 128.0,
min_keep: case % 8,
},
xtc: Xtc {
probability: (case as f32 - 128.0) / 128.0,
threshold: (case as f32 - 64.0) / 128.0,
min_keep: case % 8,
},
temperature: token_sampling::DynTemperature {
t: (case as f32 - 100.0) / 50.0,
delta: (case as f32 - 200.0) / 100.0,
exponent: (case as f32 - 128.0) / 64.0,
},
};
let mut chain = SamplerChain::llama_default(config);
let mut rng = SplitMix64::new(case as u64);
let result = chain.sample(&mut logits, &history, &mut rng);
if let Ok(token) = result {
assert!((token as usize) < size);
}
}
}
#[test]
fn non_finite_stage_parameters_do_not_panic() {
let mut chain = SamplerChain::new()
.push(Temperature { t: f32::NAN })
.push(TopP {
p: f32::NAN,
min_keep: usize::MAX,
})
.push(Xtc {
probability: f32::NAN,
threshold: f32::NAN,
min_keep: usize::MAX,
})
.push(token_sampling::Dist);
let mut logits = [0.0, 1.0];
let mut rng = SplitMix64::new(1);
assert!(chain.sample(&mut logits, &[], &mut rng).is_ok());
}