Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions python/sglang/srt/sampling/custom_logit_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,31 @@ def __call__(
logits[batch_idx, indices] = -float("inf")

return logits


class ForcedSequenceLogitProcessor(CustomLogitProcessor):
"""Teacher-forcing: pin each decode step to a per-request recorded token sequence.

Per-request custom_params: {"forced_output_ids": [int, ...]}. At decode step t
(t = tokens already generated for the req), forces the next token to
forced_output_ids[t] by masking every other logit. Lets two servers replay an
IDENTICAL recorded trajectory so the only variable is a server flag (e.g.
--no-cache-thoughts); the reasoning parser still sees the forced </think>, so the
split fires as in a live generation. Past the end of the list it samples normally.
"""

def __call__(self, logits, custom_param_list=None):
if not custom_param_list:
return logits
for i, params in enumerate(custom_param_list):
if not params:
continue
forced = params.get("forced_output_ids")
if not forced:
continue
req = params.get("__req__")
t = len(req.output_ids) if req is not None else 0
if t < len(forced):
logits[i, :] = float("-inf")
logits[i, forced[t]] = 0.0
return logits
Loading