use crate::candidates::{Candidates, Error};
use crate::rng::Rng;
use crate::samplers::{
Dist, Dry, DynTemperature, MinP, Penalties, Sampler, SamplerCtx, TailFree, TopK, TopP, Typical,
Xtc,
};
use core::fmt;
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ChainConfig {
pub penalties: Penalties,
pub dry: Dry,
pub top_k: TopK,
pub tail_free: TailFree,
pub typical: Typical,
pub top_p: TopP,
pub min_p: MinP,
pub xtc: Xtc,
pub temperature: DynTemperature,
}
pub struct SamplerChain {
stages: Vec<Box<dyn Sampler>>,
candidates: Candidates,
}
impl SamplerChain {
pub const fn new() -> Self {
Self {
stages: Vec::new(),
candidates: Candidates::new(),
}
}
pub fn push(mut self, sampler: impl Sampler + 'static) -> Self {
self.stages.push(Box::new(sampler));
self
}
pub fn push_dyn(&mut self, sampler: Box<dyn Sampler>) {
self.stages.push(sampler);
}
pub fn llama_default(config: ChainConfig) -> Self {
Self::new()
.push(config.penalties)
.push(config.dry)
.push(config.top_k)
.push(config.tail_free)
.push(config.typical)
.push(config.top_p)
.push(config.min_p)
.push(config.xtc)
.push(config.temperature)
.push(Dist)
}
pub fn sample(
&mut self,
logits: &mut [f32],
history: &[u32],
rng: &mut dyn Rng,
) -> Result<u32, Error> {
self.candidates.load(logits)?;
let mut context = SamplerCtx { rng, history };
for stage in &mut self.stages {
stage.apply(&mut self.candidates, &mut context)?;
}
self.candidates.selected().ok_or(Error::NoSelection)
}
pub fn candidates(&self) -> &Candidates {
&self.candidates
}
pub fn reset(&mut self) {
for stage in &mut self.stages {
stage.reset();
}
self.candidates.selected = None;
}
}
impl fmt::Debug for SamplerChain {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("SamplerChain")
.field("stage_count", &self.stages.len())
.field("candidates", &self.candidates)
.finish()
}
}
impl Default for SamplerChain {
fn default() -> Self {
Self::new()
}
}