///|
/// Advance Mirostat feedback after an external sampler chooses a token from
/// this library's candidate set. The token is checked against the same
/// adaptive truncation that `sample` would use. This lets a host own the RNG
/// and categorical draw while MoonBit maintains the feedback state.
pub fn Sampler::observe_token(
self : Sampler,
logits : Array[Double],
token : Int,
) -> Result[Step, SamplingError] {
let p = match probabilities(logits) {
Ok(value) => value
Err(error) => return Err(error)
}
self.observe_distribution(p, token)
}
///|
pub fn Sampler::observe_weighted_token(
self : Sampler,
weights : Array[Double],
token : Int,
) -> Result[Step, SamplingError] {
let p = match normalize_weights(weights) {
Ok(value) => value
Err(error) => return Err(error)
}
self.observe_distribution(p, token)
}
///|
fn Sampler::observe_distribution(
self : Sampler,
p : Array[Double],
token : Int,
) -> Result[Step, SamplingError] {
let candidates = match self.select_candidates(p) {
Ok(value) => value
Err(error) => return Err(error)
}
self.observe_candidates(p, candidates, token)
}
///|
/// Validate an externally chosen token against a precomputed model row.
pub fn Sampler::observe_prepared_token(
self : Sampler,
row : PreparedRow,
token : Int,
) -> Result[Step, SamplingError] {
let keep = match self.prepared_keep(row) {
Ok(value) => value
Err(error) => return Err(error)
}
let candidates : Array[Int] = []
for index in 0.. Result[Step, SamplingError] {
if token < 0 || token >= p.length() {
return Err(InvalidParameter("observed token outside vocabulary"))
}
let mut allowed = false
for candidate in candidates {
if candidate == token {
allowed = true
break
}
}
if !allowed || p[token] <= 0.0 {
return Err(
InvalidParameter("observed token outside Mirostat candidate set"),
)
}
self.commit_step(p, token, candidates.length())
}