Structured output generation for transformer.js using llguidance.
This library enables constrained text generation in the browser and Node.js by integrating the high-performance llguidance Rust library with transformer.js via WebAssembly.
npm install transformers-llguidance
import { pipeline } from '@huggingface/transformers';
import {
GuidanceParser,
GuidanceLogitsProcessor,
extractTokenizerData,
} from 'transformers-llguidance';
// Load a model
const generator = await pipeline('text-generation', 'Xenova/gpt2');
// Extract tokenizer data
const tokenizerData = extractTokenizerData(generator.tokenizer);
// Create a parser with JSON schema constraint
const parser = await GuidanceParser.create({
type: 'json_schema',
schema: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' }
},
required: ['name', 'age']
}
}, tokenizerData);
// Create logits processor
const processor = new GuidanceLogitsProcessor(parser);
// Generate constrained output
const output = await generator('Generate a person:', {
max_new_tokens: 50,
logits_processor: [processor],
});
console.log(output[0].generated_text);
// Output will always be valid JSON matching the schema
const grammar = {
type: 'json_schema',
schema: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'age']
}
};
const grammar = {
type: 'regex',
pattern: '[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}'
};
const grammar = {
type: 'lark',
grammar: `
start: expr
expr: term (("+"|"-") term)*
term: NUMBER
NUMBER: /[0-9]+/
`,
startSymbol: 'start'
};
GuidanceParserThe core parser that wraps the llguidance WASM module.
class GuidanceParser {
// Create a new parser instance
static async create(grammar: Grammar, tokenizer: TokenizerData): Promise<GuidanceParser>;
// Fast O(1) check if a token is allowed
isTokenAllowed(tokenId: number): boolean;
// Get full token mask (slower, use for fallback)
getTokenMask(): Uint8Array;
// Advance parser state after token selection
advance(tokenId: number): void;
// Check if generation can terminate
isComplete(): boolean;
// Reset parser for reuse
reset(): void;
// Get vocabulary size
get vocabSize(): number;
}
GuidanceLogitsProcessorLogits processor compatible with transformer.js.
class GuidanceLogitsProcessor {
constructor(parser: GuidanceParser, options?: ProcessorOptions);
// Process logits (called by transformer.js)
process(inputIds: number[], logits: Float32Array): Float32Array;
// Advance state after sampling (call after each token)
onToken(tokenId: number): void;
// Check if generation can stop
canStop(): boolean;
// Reset for new generation
reset(): void;
}
interface ProcessorOptions {
// Number of top tokens to try before full mask (default: 5)
speculationDepth?: number;
// Enable debug logging (default: false)
debug?: boolean;
}
// Extract tokenizer data from transformer.js tokenizer
function extractTokenizerData(tokenizer: TransformersTokenizer): TokenizerData;
// Load tokenizer data directly from HuggingFace Hub
async function loadTokenizerData(modelId: string, options?: {
token?: string;
baseUrl?: string;
}): Promise<TokenizerData>;
wasm32-unknown-unknown target# Install dependencies
npm install
# Build WASM module
npm run build:wasm
# Build TypeScript
npm run build
# Run tests
npm test
Use speculative decoding: The default speculationDepth: 5 works well for most cases. Increase for models with more uncertain predictions.
Reuse parsers: Create the parser once and call reset() between generations instead of creating new instances.
Batch processing: When generating multiple outputs with the same grammar, reuse the same parser instance.
MIT
24 commits
TypeScript
81.4%
Rust
17.5%
JavaScript
1.1%
Structured output generation for transformer.js using llguidance.
This library enables constrained text generation in the browser and Node.js by integrating the high-performance llguidance Rust library with transformer.js via WebAssembly.
npm install transformers-llguidance
import { pipeline } from '@huggingface/transformers';
import {
GuidanceParser,
GuidanceLogitsProcessor,
extractTokenizerData,
} from 'transformers-llguidance';
// Load a model
const generator = await pipeline('text-generation', 'Xenova/gpt2');
// Extract tokenizer data
const tokenizerData = extractTokenizerData(generator.tokenizer);
// Create a parser with JSON schema constraint
const parser = await GuidanceParser.create({
type: 'json_schema',
schema: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' }
},
required: ['name', 'age']
}
}, tokenizerData);
// Create logits processor
const processor = new GuidanceLogitsProcessor(parser);
// Generate constrained output
const output = await generator('Generate a person:', {
max_new_tokens: 50,
logits_processor: [processor],
});
console.log(output[0].generated_text);
// Output will always be valid JSON matching the schema
const grammar = {
type: 'json_schema',
schema: {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'age']
}
};
const grammar = {
type: 'regex',
pattern: '[a-zA-Z]+@[a-zA-Z]+\\.[a-zA-Z]{2,}'
};
const grammar = {
type: 'lark',
grammar: `
start: expr
expr: term (("+"|"-") term)*
term: NUMBER
NUMBER: /[0-9]+/
`,
startSymbol: 'start'
};
GuidanceParserThe core parser that wraps the llguidance WASM module.
class GuidanceParser {
// Create a new parser instance
static async create(grammar: Grammar, tokenizer: TokenizerData): Promise<GuidanceParser>;
// Fast O(1) check if a token is allowed
isTokenAllowed(tokenId: number): boolean;
// Get full token mask (slower, use for fallback)
getTokenMask(): Uint8Array;
// Advance parser state after token selection
advance(tokenId: number): void;
// Check if generation can terminate
isComplete(): boolean;
// Reset parser for reuse
reset(): void;
// Get vocabulary size
get vocabSize(): number;
}
GuidanceLogitsProcessorLogits processor compatible with transformer.js.
class GuidanceLogitsProcessor {
constructor(parser: GuidanceParser, options?: ProcessorOptions);
// Process logits (called by transformer.js)
process(inputIds: number[], logits: Float32Array): Float32Array;
// Advance state after sampling (call after each token)
onToken(tokenId: number): void;
// Check if generation can stop
canStop(): boolean;
// Reset for new generation
reset(): void;
}
interface ProcessorOptions {
// Number of top tokens to try before full mask (default: 5)
speculationDepth?: number;
// Enable debug logging (default: false)
debug?: boolean;
}
// Extract tokenizer data from transformer.js tokenizer
function extractTokenizerData(tokenizer: TransformersTokenizer): TokenizerData;
// Load tokenizer data directly from HuggingFace Hub
async function loadTokenizerData(modelId: string, options?: {
token?: string;
baseUrl?: string;
}): Promise<TokenizerData>;
wasm32-unknown-unknown target# Install dependencies
npm install
# Build WASM module
npm run build:wasm
# Build TypeScript
npm run build
# Run tests
npm test
Use speculative decoding: The default speculationDepth: 5 works well for most cases. Increase for models with more uncertain predictions.
Reuse parsers: Create the parser once and call reset() between generations instead of creating new instances.
Batch processing: When generating multiple outputs with the same grammar, reuse the same parser instance.
MIT
24 commits
TypeScript
81.4%
Rust
17.5%
JavaScript
1.1%