Add llguidance-based constrained generation (@huggingface/transformers-llguidance) - #1733
Add llguidance-based constrained generation (@huggingface/transformers-llguidance)#1733nico-martin wants to merge 15 commits into
@huggingface/transformers-llguidance)#1733Conversation
|
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. |
There was a problem hiding this comment.
Pull request overview
This PR adds an opt-in llguidance integration for grammar-constrained generation in Transformers.js, supported by a new core post-sampling hook so constraint engines can advance state based on the actually-sampled token.
Changes:
- Core: add
LogitsProcessorList.onTokensSampled(token_ids, input_ids)and invoke it once per generation step after tokens are appended. - Core: export
loggerfrom the main entry point and add generation tests for the new hook + custom stopping criteria. - New package: introduce
@huggingface/transformers-llguidance(TypeScript) implementingLlguidanceConstraintwith masking, stopping criteria, stats, and unit tests; addllguidance@0.2.0dependency.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds the packages/transformers-llguidance workspace importer and llguidance@0.2.0 dependency lock. |
| packages/transformers/tests/utils/generation.test.js | Adds tests validating the post-sample hook behavior and custom StoppingCriteria usage. |
| packages/transformers/src/transformers.js | Exports logger from the public entry point for external integrations. |
| packages/transformers/src/models/modeling_utils.js | Invokes the new post-sampling hook after appending sampled tokens each step. |
| packages/transformers/src/generation/logits_process.js | Adds LogitsProcessorList.onTokensSampled dispatcher to call processor hooks. |
| packages/transformers-llguidance/tsconfig.json | New TS build config to emit declaration files for the new package. |
| packages/transformers-llguidance/tests/llguidance-constraint.test.js | Adds unit tests for the constraint logic (masking, stopping, disposal, failure modes). |
| packages/transformers-llguidance/src/utils/types.ts | Defines shared state/stat types for the llguidance integration. |
| packages/transformers-llguidance/src/utils/mask.ts | Implements packed mask application and EOS-forcing utilities. |
| packages/transformers-llguidance/src/LlguidanceConstraint.ts | Implements LlguidanceConstraint with logits processor hook integration, stopping criteria, and stats. |
| packages/transformers-llguidance/src/index.ts | Exposes package public exports/types. |
| packages/transformers-llguidance/scripts/dev.mjs | Adds a watch-mode build script (esbuild + tsc watch) for local development. |
| packages/transformers-llguidance/scripts/build.mjs | Adds esbuild bundle script for ESM/CJS outputs. |
| packages/transformers-llguidance/README.md | Documents package usage and constraint modes (json_object/json_schema/regex). |
| packages/transformers-llguidance/package.json | Adds the new package manifest, build/test scripts, deps/peerDeps, and publish metadata. |
| packages/transformers-llguidance/jest.config.mjs | Adds Jest config for the new package tests and coverage settings. |
| .gitignore | Ignores *.local.* files repository-wide. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…sponse-constraint
|
@xenova, I've completely rewritten the response-constraints. gemma-4-E2Bsimple JSON schemaregexcomplex JSON schemaunconstrainedLFM2.5-2.6Bsimple JSON schemaregexcomplex JSON schemaunconstrainedgranite-4.0-h-350m-ONNXsimple JSON schemaregexcomplex JSON schemaunconstrainedTiming (median ms/token, steady state)
|


Adds grammar-constrained generation to Transformers.js via a pure JavaScript implementation of llguidance, so model output can be forced to match a JSON schema, a regex, or generic JSON guaranteed at the token level, not by prompting.
The integration is split into a minimal core hook and a separate opt-in package, so the core stays free of any llguidance dependency:
1. Core: post-sampling hook (
@huggingface/transformers)LogitsProcessorList.onTokensSampled(token_ids, input_ids)hook, dispatched after each generation step to every processor that implements it. This lets a logits processor observe which token was actually sampled. Required for grammar engines that advance their state per committed token.modeling_utils.jsappends the sampled tokens for the full batch, then fires the hook with the post-append state. Behavior is unchanged for existing users. Processors without the hook are unaffected.loggeris now exported from the main entry point.StoppingCriteriasupport.2. New package:
@huggingface/transformers-llguidanceLlguidanceConstraint.fromResponseFormat(tokenizer, response_format)acceptsjson_object,json_schema, orregexformats and returns{ logits_processor, stopping_criteria, stats, dispose }ready to pass togenerate():computeMaskIntointo a reusedUint32Array), and disallowed tokens are banned by writing-Infinityinto the logits. The mask application is optimized for skewed grammar masks: fully-allowed 32-token words are skipped, fully-banned words usefill, and only mixed words pay per-bit cost.dead_end), requested backtracking, missing vocab/EOS metadata, and batch sizes other than 1 all throw clear errors instead of silently producing invalid output.dispose()(idempotent) covers early exits such asmax_new_tokens.statsexposes per-run timings (computeMaskMs,applyMaskMs,commitTokenMs), step count, stop reason, and llguidance mask-cache instrumentation.Demo