use super::*;
const MAX_GRAMMAR_CLOSE_BYTES: usize = 32;
pub(crate) fn emit_grammar_close(
a: &mut ActiveSeq,
io: &crate::scheduler::io::SchedIo,
budget_close: bool,
) {
if a.inside_thinking || !budget_close {
return;
}
let close = {
let Some(gs) = a.grammar_state.as_mut() else {
return;
};
if gs.is_terminated() || gs.stop_legal(&a.eos_tokens) {
return;
}
match gs.completion_token_ids(MAX_GRAMMAR_CLOSE_BYTES) {
Some(tokens) if !tokens.is_empty() => tokens,
_ => return,
}
};
tracing::info!(
close_len = close.len(),
output_len = a.output_tokens.len(),
"grammar budget-close: emitting graceful close so length-stop yields parseable output"
);
for tok in close {
let tok = tok as u32;
a.output_tokens.push(tok);
if !io
.req
.emit(&a.sink, StreamEvent::Token(tok), "token stream")
{
break;
}
}
}
pub fn compile_grammar_state(
engine: &mut Option<GrammarEngine>,
grammar_spec: &Option<GrammarSpec>,
eos_tokens: &[u32],
) -> Option<GrammarState> {
let spec = grammar_spec.as_ref()?;
let engine = engine.as_mut()?;
let compiled = match spec {
GrammarSpec::ToolCall {
tools,
parser,
use_triggers,
} => match parser.compile_tool_grammar(engine, tools, *use_triggers) {
Some(result) => result,
None => {
tracing::debug!(
"Grammar: parser '{}' opted out of constrained decoding for this request",
parser.name(),
);
return None;
}
},
GrammarSpec::JsonObject => engine.compile_json_grammar(),
GrammarSpec::JsonSchema { schema } => engine.compile_json_schema(schema),
};
let label = match spec {
GrammarSpec::ToolCall { parser, tools, .. } => {
format!("parser={}, tools={}", parser.name(), tools.len())
}
GrammarSpec::JsonObject => "response_format=json_object".to_string(),
GrammarSpec::JsonSchema { .. } => "response_format=json_schema".to_string(),
};
match compiled {
Ok(grammar) => {
let vocab_size = engine.vocab_size();
let on_warm = engine.mask_snapshot_hook();
match GrammarState::new_with_hook(&grammar, vocab_size, on_warm) {
Ok(state) => {
tracing::info!("Grammar constrained decoding active: {label}");
Some(state.with_stop_tokens(eos_tokens))
}
Err(e) => {
tracing::warn!("Grammar state creation failed: {e}");
None
}
}
}
Err(e) => {
tracing::warn!("Grammar compilation failed: {e}");
None
}
}
}
pub enum StartPrefillResult {
Active(ActiveSeq),
InProgress(PrefillInProgress),
Finished,
}