use super::{
Sampler,
upstream::{Candidate, Candidates, Config, State},
};
use crate::{Result, invalid};
#[derive(Clone)]
pub struct SwiftSampler {
distribution: State,
}
impl SwiftSampler {
pub const VOCABULARY: usize = 248_320;
pub fn new(seed: u32) -> Result<Self> {
if seed == u32::MAX {
return Err(invalid(
"Swift sampling requires an explicit non-sentinel seed",
));
}
Ok(Self {
distribution: State::new(Config::Distribution(seed))?,
})
}
pub fn reset(&mut self) {
self.distribution.reset();
}
}
impl Sampler for SwiftSampler {
fn sample(&mut self, logits: &[f32]) -> Result<u32> {
if logits.len() != Self::VOCABULARY || logits.iter().any(|value| !value.is_finite()) {
return Err(invalid(
"Swift sampling requires the complete finite pinned vocabulary",
));
}
let mut backing = Vec::new();
backing.try_reserve_exact(logits.len())?;
for (index, &logit) in logits.iter().enumerate() {
backing.push(Candidate {
id: i32::try_from(index)?,
logit,
probability: 0.0,
});
}
let mut candidates = Candidates::new(backing, -1, false)?;
for config in [
Config::TopK(20),
Config::TopP {
probability: 0.95,
min_keep: 1,
},
Config::MinP {
probability: 0.0,
min_keep: 1,
},
Config::Temperature(1.0),
] {
State::new(config)?.apply(&mut candidates)?;
}
self.distribution.apply(&mut candidates)?;
let selected = usize::try_from(candidates.selected())?;
let token = candidates
.data()
.get(selected)
.ok_or_else(|| invalid("Swift sampler selected an invalid candidate"))?;
Ok(u32::try_from(token.id)?)
}
}