Add Generation Extension Points for Constrained Decoding#1720
Open
nico-martin wants to merge 4 commits into
Open
Add Generation Extension Points for Constrained Decoding#1720nico-martin wants to merge 4 commits into
nico-martin wants to merge 4 commits into
Conversation
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In this PR I keep structured/constrained generation out of core and expose the same kind of generation extension points that Python
transformersalready uses:logits_processorfor transforming token scores before sampling.stopping_criteriafor deciding when generation should stop.The main idea is that JSON Schema / llguidance-style decoding should be possible from an external package, without adding WASM, tokenizer bridge code, or schema validation to Transformers.js itself.
API Shape
The core API stays small: callers pass custom generation pieces through the existing
generate()path.I keep
logits_processorlist-like, matching Pythontransformersusage. A single custom processor can be wrapped inLogitsProcessorList, or an external helper can return the list directly.I also keep
stopping_criteriaseparate from logits processing. That preserves the upstream split: processors modify scores, criteria stops generation.createLlguidanceConstraint()is only an example external-package helper. The Transformers.js API surface is thegenerate()arguments, not the helper name.Python
transformersCompatibilityPython
transformersalready models constrained generation as composable generation hooks:This PR follows that shape instead of adding a pipeline-specific
response_formatoption to core. The important portable part stays the same:LogitsProcessor.__call__(input_ids, scores) -> scores.The only Transformers.js-specific piece is an optional batch-level
onTokensSampled(tokenIds, inputIds)hook on processors inside aLogitsProcessorList. I added that for stateful decoders that need to commit the sampled token after sampling. It runs once per generation step after the full batch step has been appended, so processors do not see a partially updated batch.Minimal External Constraint Example
This is not real llguidance. It is a small, visible toy constraint: generated tokens may not decode to emoji. The behavior is easy to verify, but it uses the same shape an external llguidance package would use.
Usage:
Benefits of this direction:
transformerssplit between score processing and stopping.