Skip to content
Closed
Show file tree
Hide file tree
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
48 changes: 48 additions & 0 deletions packages/transformers-llguidance/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# @huggingface/transformers-llguidance

Experimental constrained-generation helpers for Transformers.js.

This package exports `LlguidanceConstraint`, which turns an llguidance response format into the `logits_processor` and `stopping_criteria` objects accepted by Transformers.js generation.

```js
import { LlguidanceConstraint } from "@huggingface/transformers-llguidance";

const { logits_processor, stopping_criteria } =
await LlguidanceConstraint.fromResponseFormat(tokenizer, {
type: "json_schema",
json_schema: {
type: "object",
properties: {
answer: { type: "string" },
},
required: ["answer"],
additionalProperties: false,
},
});

await model.generate({
...inputs,
logits_processor,
stopping_criteria,
});
```

## Regex constraints

Use `type: "regex"` to constrain generation to a regular expression. For example, this only allows ISO-like dates in `YYYY-MM-DD` format:

```js
import { LlguidanceConstraint } from "@huggingface/transformers-llguidance";

const { logits_processor, stopping_criteria } =
await LlguidanceConstraint.fromResponseFormat(tokenizer, {
type: "regex",
regex: "\\d{4}-\\d{2}-\\d{2}",
});

const output = await model.generate({
...inputs,
logits_processor,
stopping_criteria,
});
```
11 changes: 11 additions & 0 deletions packages/transformers-llguidance/jest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** @type {import('jest').Config} */
export default {
clearMocks: true,
collectCoverage: true,
coverageDirectory: "coverage",
coveragePathIgnorePatterns: ["node_modules", "tests"],
coverageProvider: "v8",
roots: ["./tests/"],
testTimeout: 32000,
transform: {},
};
68 changes: 68 additions & 0 deletions packages/transformers-llguidance/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "@huggingface/transformers-llguidance",
"version": "0.0.0",
"description": "llguidance integration helpers for Transformers.js constrained generation",
"main": "./dist/index.cjs",
"types": "./types/index.d.ts",
"type": "module",
"exports": {
"import": {
"types": "./types/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./types/index.d.ts",
"default": "./dist/index.cjs"
}
},
"scripts": {
"format": "prettier --write . --ignore-path ../../.prettierignore",
"format:check": "prettier --check . --ignore-path ../../.prettierignore",
"typegen": "tsc --build",
"dev": "node scripts/dev.mjs",
"build": "node scripts/build.mjs && pnpm typegen",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --verbose"
},
"repository": {
"type": "git",
"url": "git+https://github.com/huggingface/transformers.js.git"
},
"keywords": [
"transformers",
"transformers.js",
"huggingface",
"llguidance",
"constrained-generation"
],
"author": "Hugging Face",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/huggingface/transformers.js/issues"
},
"homepage": "https://github.com/huggingface/transformers.js#readme",
"peerDependencies": {
"@huggingface/transformers": "^4.2.0"
},
"devDependencies": {
"@huggingface/transformers": "workspace:*",
"@types/jest": "^30.0.0",
"@types/node": "^24.1.0",
"esbuild": "^0.27.2",
"jest": "^30.2.0",
"typescript": "5.9.3"
},
"files": [
"src",
"dist",
"types",
"README.md",
"LICENSE",
"!**/*.tsbuildinfo"
],
"publishConfig": {
"access": "public"
},
"dependencies": {
"llguidance": "^0.1.8"
}
}
26 changes: 26 additions & 0 deletions packages/transformers-llguidance/scripts/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { build } from "esbuild";
import { rmSync } from "node:fs";

rmSync("dist", { recursive: true, force: true });

const common = {
entryPoints: ["src/index.ts"],
bundle: true,
platform: "neutral",
target: "es2022",
sourcemap: true,
external: ["@huggingface/transformers", "llguidance"],
};

await Promise.all([
build({
...common,
format: "esm",
outfile: "dist/index.js",
}),
build({
...common,
format: "cjs",
outfile: "dist/index.cjs",
}),
]);
65 changes: 65 additions & 0 deletions packages/transformers-llguidance/scripts/dev.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { context } from "esbuild";
import { spawn } from "node:child_process";
import { rmSync } from "node:fs";

rmSync("dist", { recursive: true, force: true });
rmSync("types", { recursive: true, force: true });

const watchLogger = {
name: "watch-logger",
setup(build) {
let startTime = 0;

build.onStart(() => {
startTime = performance.now();
console.log(`[transformers-llguidance] rebuilding ${build.initialOptions.outfile}...`);
});

build.onEnd((result) => {
const duration = (performance.now() - startTime).toFixed(2);
if (result.errors.length > 0) {
console.log(`[transformers-llguidance] rebuild failed in ${duration}ms`);
} else {
console.log(`[transformers-llguidance] rebuilt ${build.initialOptions.outfile} in ${duration}ms`);
}
});
},
};

const common = {
entryPoints: ["src/index.ts"],
bundle: true,
platform: "neutral",
target: "es2022",
sourcemap: true,
external: ["@huggingface/transformers", "llguidance"],
plugins: [watchLogger],
};

const contexts = await Promise.all([
context({
...common,
format: "esm",
outfile: "dist/index.js",
}),
context({
...common,
format: "cjs",
outfile: "dist/index.cjs",
}),
]);

await Promise.all(contexts.map((ctx) => ctx.watch()));

const tscWatch = spawn("tsc", ["--build", "--watch", "--preserveWatchOutput"], {
stdio: "inherit",
shell: true,
});

console.log("Watching @huggingface/transformers-llguidance...");

process.on("SIGINT", async () => {
tscWatch.kill();
await Promise.all(contexts.map((ctx) => ctx.dispose()));
process.exit(0);
});
Loading
Loading