use super::*;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(in crate::scheduler) enum PositionKind {
FinalDecode,
Verify,
}
impl PositionKind {
pub(in crate::scheduler) fn adadec_label(self) -> &'static str {
match self {
PositionKind::FinalDecode => "decode",
PositionKind::Verify => "verify",
}
}
}
pub(in crate::scheduler) fn penalty_history_scope(
output_tokens: &[u32],
tool_call_end_token: Option<u32>,
) -> &[u32] {
match tool_call_end_token.and_then(|t| output_tokens.iter().rposition(|&x| x == t)) {
Some(p) => &output_tokens[p + 1..],
None => output_tokens,
}
}
pub(in crate::scheduler) fn strip_in_tool_opener_bias(
logit_bias: &mut Vec<(u32, f32)>,
in_tool: bool,
opener: Option<u32>,
) {
if !in_tool {
return;
}
let Some(tc_open) = opener else {
return;
};
logit_bias.retain(|&(id, delta)| id != tc_open || delta <= 0.0);
}
pub(in crate::scheduler) fn effective_min_p(
min_p: f32,
levers: &crate::scheduler::logit_processors::SamplingLevers,
) -> f32 {
if levers.mtp_minp { min_p } else { 0.0 }
}
pub(in crate::scheduler) fn penalty_params_for(
a: &ActiveSeq,
kind: PositionKind,
temperature: f32,
seed: Option<u64>,
base_logit_bias: Vec<(u32, f32)>,
min_reasoning_floor: u32,
) -> SamplingParams {
debug_assert!(
kind != PositionKind::Verify
|| (temperature == 0.0 && seed.is_none() && base_logit_bias.is_empty()),
"Verify positions must pass temperature=0.0, seed=None, empty base bias"
);
let in_tool = a.inside_tool_body && !a.inside_thinking;
let mut logit_bias = base_logit_bias;
strip_in_tool_opener_bias(&mut logit_bias, in_tool, a.tool_call_start_token);
let floor = min_reasoning_floor;
if floor > 0
&& a.inside_thinking
&& a.thinking_tokens < floor
&& a.thinking_budget.unwrap_or(floor) >= floor
&& let Some(end_tok) = a.think_end_token
{
logit_bias.push((end_tok, -8.0f32));
}
SamplingParams {
temperature,
top_k: a.top_k,
top_p: a.top_p,
top_n_sigma: a.top_n_sigma,
min_p: a.min_p,
logit_bias,
repetition_penalty: a.repetition_penalty,
repetition_penalty_window: a.repetition_penalty_window,
presence_penalty: a.presence_penalty,
frequency_penalty: a.frequency_penalty,
lz_penalty: if a.grammar_state.is_some() {
0.0
} else {
a.lz_penalty
},
dry_multiplier: if in_tool { 0.0 } else { a.dry_multiplier },
dry_base: a.dry_base,
dry_allowed_length: a.dry_allowed_length,
dry_sequence_breakers: a.dry_sequence_breakers.clone(),
max_tokens: 0,
stop_token_ids: Vec::new(),
seed,
}
}