llguidance 0.7.27__tar.gz → 0.7.30__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {llguidance-0.7.27 → llguidance-0.7.30}/CHANGELOG.md +13 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/Cargo.lock +6 -6
- {llguidance-0.7.27 → llguidance-0.7.30}/PKG-INFO +5 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/README.md +4 -0
- llguidance-0.7.30/docs/parametric.md +134 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/docs/syntax.md +18 -4
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/Cargo.toml +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/from_guidance.rs +4 -3
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/grammar.rs +730 -56
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/mod.rs +4 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/parser.rs +162 -55
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/slicer.rs +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/grammar_builder.rs +146 -32
- llguidance-0.7.30/parser/src/hashcons.rs +84 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/ast.rs +8 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/compiler.rs +81 -18
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/lexer.rs +83 -10
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/parser.rs +279 -27
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lib.rs +1 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/pyproject.toml +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/Cargo.toml +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_lark.rs +369 -2
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_raw_parser.rs +16 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/install-deps.sh +2 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/Cargo.toml +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/toktree.rs +27 -9
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_downloader/Cargo.toml +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_tokenizers/Cargo.toml +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_tiktoken/Cargo.toml +1 -1
- {llguidance-0.7.27 → llguidance-0.7.30}/.github/workflows/rust.yml +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/.github/workflows/wheels.yml +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/.gitignore +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/CODE_OF_CONDUCT.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/Cargo.toml +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/LICENSE +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/SECURITY.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/SUPPORT.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/c_sample/Makefile +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/c_sample/README.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/c_sample/c_sample.cpp +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/docs/fast_forward.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/docs/json_schema.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/docs/mask_plot.png +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/docs/optimizations.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/docs/special_tokens.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/docs/toktrie.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/Cargo.toml +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/expected_maskbench.json +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/jstats.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/scripts/split-stats.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/scripts/split_plot.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/src/json_stats.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/src/lib.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/src/stats.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/LICENSE +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/README.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/build.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/cbindgen.toml +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/grammars/character.json +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/grammars/json.json +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/llguidance.h +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/api.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/constraint.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/lexer.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/lexerspec.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/perf.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/regexvec.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/factory.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/ffi.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/ffi_par.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/README.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/compiler.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_ref.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_simple/context.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_simple/draft.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_simple/mod.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/formats.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/mod.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/numeric.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/schema.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/shared_context.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json_validation.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/README.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/common.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/mod.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/logging.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/matcher.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/output.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/panic_utils.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/regex_rewrite.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/stop_controller.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/substring.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/tokenizer_json.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/tokenparser.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/plan.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/__init__.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_grammar_from.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_lib.pyi +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_struct_tag.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_tokenizer.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_util.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/cli.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/gbnf_to_lark.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/hf.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/llamacpp.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/mlx.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/numpy.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/py.typed +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/tiktoken.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/torch.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/mypy.ini +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/__init__.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_bitmask.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_hf.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_llamacpp.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_matcher.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_tiktoken.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/lib.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/llamatokenizer.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/llinterpreter.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/llmatcher.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/parserlimits.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/py.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/pyjson.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/Cargo.toml +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/README.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/cli.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/blog.sample.json +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/blog.schema.json +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/blog.schema.ll.json +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/README.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/arithmetic.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/c.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/chess.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/english.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/japanese.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/json.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/json_arr.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/list.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/vllm-sql.gbnf +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/lark.lark +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/rfc.lark +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/rfc.xml +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/ulysses.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/gtest.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/lark.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/run.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/src/lib.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/src/minimal.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/src/sample_parser.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_ll.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_stop.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/annotate_asm.js +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/bump.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/cbindgen.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/checklinks.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/checklinks.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/ci-publish.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/disasm.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/gbnf_to_lark.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/gen-testcase.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/git-version.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/jsonschema-stats.js +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/remote-guidance-test.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/rust-size.js +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/rust_size.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/test-guidance.sh +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/tokenizer_test.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/scripts/update-git.py +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/LICENSE +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/README.md +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/bytes.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/lib.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/recognizer.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/rng.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/svob.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/tokenv.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/tests/test_svob.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_downloader/LICENSE +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_downloader/src/lib.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_tokenizers/LICENSE +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_tokenizers/src/lib.rs +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_tiktoken/LICENSE +0 -0
- {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_tiktoken/src/lib.rs +0 -0
|
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
If a release doesn't introduce any interesting changes (build fixes etc.), it's skipped.
|
|
6
6
|
|
|
7
|
+
#### [0.7.30](https://github.com/guidance-ai/llguidance/compare/v0.7.29...0.7.30) 2025-06-23
|
|
8
|
+
|
|
9
|
+
- parametric grammars [`#192`](https://github.com/guidance-ai/llguidance/pull/192)
|
|
10
|
+
- allow for tokens up to ~2k bytes; fixes #188 [`#188`](https://github.com/guidance-ai/llguidance/issues/188)
|
|
11
|
+
|
|
12
|
+
#### [0.7.29](https://github.com/guidance-ai/llguidance/compare/v0.7.28...0.7.29) 2025-06-06
|
|
13
|
+
|
|
14
|
+
- cargo fmt
|
|
15
|
+
|
|
16
|
+
#### [0.7.28](https://github.com/guidance-ai/llguidance/compare/v0.7.27...0.7.28) 2025-06-06
|
|
17
|
+
|
|
18
|
+
- fix lexer_stack=... panic with numeric tokens [`4e91b0f`](https://github.com/guidance-ai/llguidance/commit/4e91b0fa0c03572a5fc221ac0e0b05035af9dcfa)
|
|
19
|
+
|
|
7
20
|
#### [0.7.27](https://github.com/guidance-ai/llguidance/compare/v0.7.26...0.7.27) 2025-06-04
|
|
8
21
|
|
|
9
22
|
- add toktrie_tiktoken and llguidance.tiktoken.lltokenizer_from_encoding [`#154`](https://github.com/guidance-ai/llguidance/issues/154)
|
|
@@ -1211,7 +1211,7 @@ checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
|
|
|
1211
1211
|
|
|
1212
1212
|
[[package]]
|
|
1213
1213
|
name = "llguidance"
|
|
1214
|
-
version = "0.7.
|
|
1214
|
+
version = "0.7.30"
|
|
1215
1215
|
dependencies = [
|
|
1216
1216
|
"anyhow",
|
|
1217
1217
|
"derivre",
|
|
@@ -1230,7 +1230,7 @@ dependencies = [
|
|
|
1230
1230
|
|
|
1231
1231
|
[[package]]
|
|
1232
1232
|
name = "llguidance_py"
|
|
1233
|
-
version = "0.7.
|
|
1233
|
+
version = "0.7.30"
|
|
1234
1234
|
dependencies = [
|
|
1235
1235
|
"anyhow",
|
|
1236
1236
|
"bytemuck",
|
|
@@ -2395,7 +2395,7 @@ dependencies = [
|
|
|
2395
2395
|
|
|
2396
2396
|
[[package]]
|
|
2397
2397
|
name = "toktrie"
|
|
2398
|
-
version = "0.7.
|
|
2398
|
+
version = "0.7.30"
|
|
2399
2399
|
dependencies = [
|
|
2400
2400
|
"anyhow",
|
|
2401
2401
|
"bytemuck",
|
|
@@ -2406,7 +2406,7 @@ dependencies = [
|
|
|
2406
2406
|
|
|
2407
2407
|
[[package]]
|
|
2408
2408
|
name = "toktrie_hf_downloader"
|
|
2409
|
-
version = "0.7.
|
|
2409
|
+
version = "0.7.30"
|
|
2410
2410
|
dependencies = [
|
|
2411
2411
|
"anyhow",
|
|
2412
2412
|
"hf-hub",
|
|
@@ -2417,7 +2417,7 @@ dependencies = [
|
|
|
2417
2417
|
|
|
2418
2418
|
[[package]]
|
|
2419
2419
|
name = "toktrie_hf_tokenizers"
|
|
2420
|
-
version = "0.7.
|
|
2420
|
+
version = "0.7.30"
|
|
2421
2421
|
dependencies = [
|
|
2422
2422
|
"anyhow",
|
|
2423
2423
|
"log",
|
|
@@ -2429,7 +2429,7 @@ dependencies = [
|
|
|
2429
2429
|
|
|
2430
2430
|
[[package]]
|
|
2431
2431
|
name = "toktrie_tiktoken"
|
|
2432
|
-
version = "0.7.
|
|
2432
|
+
version = "0.7.30"
|
|
2433
2433
|
dependencies = [
|
|
2434
2434
|
"anyhow",
|
|
2435
2435
|
"log",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llguidance
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.30
|
|
4
4
|
License-File: LICENSE
|
|
5
5
|
Summary: Bindings for the Low-level Guidance (llguidance) Rust library for use within Guidance
|
|
6
6
|
Author: Michal Moskal
|
|
@@ -20,6 +20,7 @@ Project-URL: issue_tracker, https://github.com/microsoft/llguidance/issues
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
+
* 2025-06-11 [Making Structured Outputs Go Brrr](https://guidance-ai.github.io/llguidance/llg-go-brrr) blog post released
|
|
23
24
|
* 2025-05-20 LLGuidance [shipped](https://x.com/OpenAIDevs/status/1924915341052019166) in [OpenAI](https://x.com/OpenAIDevs/status/1924915343677653014) for JSON Schema
|
|
24
25
|
* 2025-04-11 integration [merged](https://github.com/chromium/chromium/commit/07ca6337c2f714ba0477202414bd2b1692e70594) into Chromium
|
|
25
26
|
* 2025-03-25 integration [merged](https://github.com/vllm-project/vllm/pull/14779) into vLLM (v0.8.2)
|
|
@@ -76,6 +77,9 @@ The library is currently integrated in:
|
|
|
76
77
|
|
|
77
78
|
## Technical details
|
|
78
79
|
|
|
80
|
+
See [Making Structured Outputs Go Brrr](https://guidance-ai.github.io/llguidance/llg-go-brrr) for an overview of the library,
|
|
81
|
+
including the design decisions, performance, and how it compares to other approaches.
|
|
82
|
+
|
|
79
83
|
Given a context-free grammar, a tokenizer, and a prefix of tokens, llguidance computes a token mask - a set of tokens from the tokenizer - that, when added to the current token prefix, can lead to a valid string in the language defined by the grammar. Mask computation takes approximately 50μs of single-core CPU time for a tokenizer with 128k tokens. While this timing depends on the exact grammar, it holds, for example, for grammars derived from JSON schemas. There is no significant startup cost.
|
|
80
84
|
|
|
81
85
|
The library implements a context-free grammar parser using Earley’s algorithm on top of a lexer based on [derivatives of regular expressions](https://github.com/microsoft/derivre). Mask computation is achieved by traversing the [prefix tree (trie)](./docs/toktrie.md) of all possible tokens, leveraging [highly optimized](./docs/optimizations.md) code.
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
* 2025-06-11 [Making Structured Outputs Go Brrr](https://guidance-ai.github.io/llguidance/llg-go-brrr) blog post released
|
|
11
12
|
* 2025-05-20 LLGuidance [shipped](https://x.com/OpenAIDevs/status/1924915341052019166) in [OpenAI](https://x.com/OpenAIDevs/status/1924915343677653014) for JSON Schema
|
|
12
13
|
* 2025-04-11 integration [merged](https://github.com/chromium/chromium/commit/07ca6337c2f714ba0477202414bd2b1692e70594) into Chromium
|
|
13
14
|
* 2025-03-25 integration [merged](https://github.com/vllm-project/vllm/pull/14779) into vLLM (v0.8.2)
|
|
@@ -64,6 +65,9 @@ The library is currently integrated in:
|
|
|
64
65
|
|
|
65
66
|
## Technical details
|
|
66
67
|
|
|
68
|
+
See [Making Structured Outputs Go Brrr](https://guidance-ai.github.io/llguidance/llg-go-brrr) for an overview of the library,
|
|
69
|
+
including the design decisions, performance, and how it compares to other approaches.
|
|
70
|
+
|
|
67
71
|
Given a context-free grammar, a tokenizer, and a prefix of tokens, llguidance computes a token mask - a set of tokens from the tokenizer - that, when added to the current token prefix, can lead to a valid string in the language defined by the grammar. Mask computation takes approximately 50μs of single-core CPU time for a tokenizer with 128k tokens. While this timing depends on the exact grammar, it holds, for example, for grammars derived from JSON schemas. There is no significant startup cost.
|
|
68
72
|
|
|
69
73
|
The library implements a context-free grammar parser using Earley’s algorithm on top of a lexer based on [derivatives of regular expressions](https://github.com/microsoft/derivre). Mask computation is achieved by traversing the [prefix tree (trie)](./docs/toktrie.md) of all possible tokens, leveraging [highly optimized](./docs/optimizations.md) code.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Parametric grammars
|
|
2
|
+
|
|
3
|
+
In llguidance [grammar rules](./syntax.md) can be parameterized by a 64-bit integer.
|
|
4
|
+
This allows for expressing concepts like "permutation of N elements", "unique selection of N elements",
|
|
5
|
+
and other combinatorial structures in a concise way.
|
|
6
|
+
|
|
7
|
+
The parametrized grammars are technically still context-free, just very large:
|
|
8
|
+
each parametrized rule is treated as if it was expanded for each 64-bit integer value.
|
|
9
|
+
Of course, the grammar is only materialized lazily, during Earley parsing.
|
|
10
|
+
|
|
11
|
+
For example, this grammar describes permutations of 3 elements `a`, `b`, and `c`:
|
|
12
|
+
|
|
13
|
+
```lark
|
|
14
|
+
start : perm::0x0
|
|
15
|
+
perm::_ : "" %if is_ones([0:3])
|
|
16
|
+
| "a" perm::set_bit(0) %if bit_clear(0)
|
|
17
|
+
| "b" perm::set_bit(1) %if bit_clear(1)
|
|
18
|
+
| "c" perm::set_bit(2) %if bit_clear(2)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The `start` rule starts with an empty set of bits (`0x0`), and the `perm` rule expands to either an empty string
|
|
22
|
+
(if all bits are set, i.e., all elements have been seen)
|
|
23
|
+
or a choice of one of the remaining elements followed by a recursive call to `perm`
|
|
24
|
+
with the corresponding bit set in the parameter (using `set_bit(k)`).
|
|
25
|
+
|
|
26
|
+
Think of the `perm::_ : ...` syntax as:
|
|
27
|
+
|
|
28
|
+
```lark
|
|
29
|
+
perm(p) : "" %if p[0:3] == 0b111
|
|
30
|
+
| "a" perm(p | (1 << 0)) %if p[0:1] == 0b0
|
|
31
|
+
| "b" perm(p | (1 << 1)) %if p[1:2] == 0b0
|
|
32
|
+
| "c" perm(p | (1 << 2)) %if p[2:3] == 0b0
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Where `p[x:y]` is the bit range from `x` inclusive to `y` exclusive in the parameter `p`, that is `(p >> x) & ((1 << y) - 1)`.
|
|
36
|
+
|
|
37
|
+
Currently, there is always a single parameter for each rule, and it is always a 64-bit integer.
|
|
38
|
+
|
|
39
|
+
## Function reference
|
|
40
|
+
|
|
41
|
+
The following functions are available in rule parameters. Assume current parameter is `p`,
|
|
42
|
+
`v` is a 64-bit integer literal using decimal or hexadecimal notation,
|
|
43
|
+
`k`, `x`, and `y` are bit indices (0-based).
|
|
44
|
+
Additionally, `_` can be used to refer to `[0:64]`.
|
|
45
|
+
|
|
46
|
+
- `_ => p` (self-reference)
|
|
47
|
+
- `set_bit(k) => p | (1 << k)` sets the k-th bit in the parameter
|
|
48
|
+
- `clear_bit(k) => p & ~(1 << k)` clears the k-th bit in the parameter
|
|
49
|
+
- `bit_and(v) => p & v`
|
|
50
|
+
- `bit_or(v) => p | v`
|
|
51
|
+
- `incr([x:y]) => p[x:y] == 0b11...1 ? p : p + (1 << x)` - saturating increment of bits in the range `[x:y]`
|
|
52
|
+
- `decr([x:y]) => p[x:y] == 0 ? p : p - (1 << x)` - saturating decrement of bits in the range `[x:y]`
|
|
53
|
+
|
|
54
|
+
The following functions are available in rule conditions (`c` is a condition expression).
|
|
55
|
+
All comparisons treat intergers as unsigned.
|
|
56
|
+
|
|
57
|
+
- `true` and `true()` (always true)
|
|
58
|
+
- `bit_clear(k) => p[k:k+1] == 0` (checks if the k-th bit is clear)
|
|
59
|
+
- `bit_set(k) => p[k:k+1] == 1` (checks if the k-th bit is set)
|
|
60
|
+
- `is_ones([x:y]) => p[x:y] == ((1 << (y - x)) - 1)` (checks if all bits in the range `[x:y]` are set)
|
|
61
|
+
- `is_zeros([x:y]) => p[x:y] == 0` (checks if all bits in the range `[x:y]` are clear)
|
|
62
|
+
- `eq([x:y], v) => p[x:y] == v` (checks if bits in the range `[x:y]` are equal to `v`)
|
|
63
|
+
- `ne([x:y], v) => p[x:y] != v`
|
|
64
|
+
- `lt([x:y], v) => p[x:y] < v`
|
|
65
|
+
- `le([x:y], v) => p[x:y] <= v`
|
|
66
|
+
- `gt([x:y], v) => p[x:y] > v`
|
|
67
|
+
- `ge([x:y], v) => p[x:y] >= v`
|
|
68
|
+
- `bit_count_eq([x:y], k) => bin(p[x:y]).count('1') == k` (checks if the number of set bits in the range `[x:y]` is equal to `k`)
|
|
69
|
+
- `bit_count_ne([x:y], k) => bin(p[x:y]).count('1') != k`
|
|
70
|
+
- `bit_count_lt([x:y], k) => bin(p[x:y]).count('1') < k`
|
|
71
|
+
- `bit_count_le([x:y], k) => bin(p[x:y]).count('1') <= k`
|
|
72
|
+
- `bit_count_gt([x:y], k) => bin(p[x:y]).count('1') > k`
|
|
73
|
+
- `bit_count_ge([x:y], k) => bin(p[x:y]).count('1') >= k`
|
|
74
|
+
- `and(c, c)` (logical AND of two conditions)
|
|
75
|
+
- `or(c, c)` (logical OR of two conditions)
|
|
76
|
+
- `not(c)` (logical negation of a condition)
|
|
77
|
+
|
|
78
|
+
## Examples
|
|
79
|
+
|
|
80
|
+
Any sequence of `a`, `b`, and `c` where each element occurs at least once:
|
|
81
|
+
|
|
82
|
+
```lark
|
|
83
|
+
start : perm::0x0
|
|
84
|
+
perm::_ : "" %if is_ones([0:3])
|
|
85
|
+
| "a" perm::set_bit(0)
|
|
86
|
+
| "b" perm::set_bit(1)
|
|
87
|
+
| "c" perm::set_bit(2)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
A sequence `s` matching `/a*b*/` where `len(s) < 20`:
|
|
91
|
+
|
|
92
|
+
```lark
|
|
93
|
+
start : aa::0
|
|
94
|
+
aa::_ : "b" aa::incr(_) %if lt(_, 20)
|
|
95
|
+
| bb::_
|
|
96
|
+
bb::_ : "a" bb::incr(_) %if lt(_, 20)
|
|
97
|
+
| ""
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
A sequence of `a`, `b`, and `c` in any order,
|
|
101
|
+
where `a` and `b` can occur at most 5 times each, and `c` at most 6 times.
|
|
102
|
+
Note that you have to allocate enough bits for each element.
|
|
103
|
+
|
|
104
|
+
```lark
|
|
105
|
+
start : lst::0x0
|
|
106
|
+
lst::_ : "a" lst::incr([0:3]) %if lt([0:3], 5)
|
|
107
|
+
| "b" lst::incr([3:6]) %if lt([3:6], 5)
|
|
108
|
+
| "c" lst::incr([6:9]) %if lt([6:9], 6)
|
|
109
|
+
| ""
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Pick at last 1 and at most 3 elements from `a`, `b`, `c`, `d`, `e`;
|
|
113
|
+
each element can occur at most once.
|
|
114
|
+
|
|
115
|
+
```lark
|
|
116
|
+
start : perm::0x0
|
|
117
|
+
perm::_ : "" %if bit_count_ge(_, 1)
|
|
118
|
+
| "a" perm::set_bit(0) %if and(bit_clear(0), bit_count_lt(_, 3))
|
|
119
|
+
| "b" perm::set_bit(1) %if and(bit_clear(1), bit_count_lt(_, 3))
|
|
120
|
+
| "c" perm::set_bit(2) %if and(bit_clear(2), bit_count_lt(_, 3))
|
|
121
|
+
| "d" perm::set_bit(3) %if and(bit_clear(3), bit_count_lt(_, 3))
|
|
122
|
+
| "e" perm::set_bit(4) %if and(bit_clear(4), bit_count_lt(_, 3))
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Performance considerations
|
|
126
|
+
|
|
127
|
+
All the rules above are right-recursive, which is generally [not ideal](./syntax.md#recursive-rules) for Earley parsing.
|
|
128
|
+
The problem is, for a list of length `N` it will generate `O(N^2)` items during parsing
|
|
129
|
+
(for item number `i`, it will generate about `i` items).
|
|
130
|
+
|
|
131
|
+
However, if you were to make them left-recursive, it may generate `O(2^K)` items
|
|
132
|
+
where `K` is the number of bits used, so do not do that.
|
|
133
|
+
|
|
134
|
+
Practically, this means the rules will not work for lists longer than about 2000 elements.
|
|
@@ -105,20 +105,34 @@ with a definition of a Python string, depending on how the model was trained.
|
|
|
105
105
|
### Reasoning/thinking
|
|
106
106
|
|
|
107
107
|
Yet another example is "thinking" or reasoning models distilled from DeepSeek-R1.
|
|
108
|
-
A grammar for forcing JSON may look like this:
|
|
108
|
+
A grammar for forcing a JSON-formatted address may look like this:
|
|
109
109
|
|
|
110
110
|
```lark
|
|
111
|
-
start: <think> "\n" /(.|\n)*/ </think>
|
|
112
|
-
|
|
111
|
+
start: <think> "\n" /(.|\n)*/ </think> address
|
|
112
|
+
address: %json {
|
|
113
|
+
"type": "object",
|
|
114
|
+
"properties": {
|
|
115
|
+
"street": { "type": "string" },
|
|
116
|
+
"city": { "type": "string" },
|
|
117
|
+
"zip": { "type": "number" }
|
|
118
|
+
},
|
|
119
|
+
"required": ["street", "city", "state", "zip"]
|
|
120
|
+
}
|
|
113
121
|
```
|
|
114
122
|
|
|
115
123
|
Often, the chat format already includes initial `<think>\n` - in these cases
|
|
116
|
-
you can use `start: /(.|\n)*/ </think>
|
|
124
|
+
you can use `start: /(.|\n)*/ </think> address` as the grammar.
|
|
117
125
|
You can also use `/(.|\n){1000,3000}/` to place lower and upper bounds on the thinking amount.
|
|
118
126
|
|
|
119
127
|
This assumes `<think>` is a special token. If it was just a string, you would need
|
|
120
128
|
to use [`suffix="</think>"`](#lazy-lexemes).
|
|
121
129
|
|
|
130
|
+
### Parametric grammars (unique lists, permutations etc.)
|
|
131
|
+
|
|
132
|
+
Rules can be parameterized by a 64-bit value, which allows for expressing
|
|
133
|
+
combinatorial structures like unique lists and permutations.
|
|
134
|
+
See [Parametric grammars](./parametric.md) for details.
|
|
135
|
+
|
|
122
136
|
### Lexeme options
|
|
123
137
|
|
|
124
138
|
Some of these features (especially `stop`) are primarily for compatibility with [Guidance](https://github.com/guidance-ai/guidance).
|
|
@@ -182,9 +182,9 @@ impl GrammarInit {
|
|
|
182
182
|
extra_lexemes: Vec<String>,
|
|
183
183
|
) -> Result<Arc<CGrammar>> {
|
|
184
184
|
let t0 = Instant::now();
|
|
185
|
-
let (grammar, mut lexer_spec) = self.to_internal(tok_env, limits)?;
|
|
185
|
+
let (grammar, mut lexer_spec) = self.to_internal(tok_env, limits.clone())?;
|
|
186
186
|
lexer_spec.add_extra_lexemes(&extra_lexemes);
|
|
187
|
-
compile_grammar(t0, grammar, lexer_spec, logger)
|
|
187
|
+
compile_grammar(t0, grammar, lexer_spec, logger, &limits)
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
|
|
@@ -193,6 +193,7 @@ fn compile_grammar(
|
|
|
193
193
|
mut grammar: Grammar,
|
|
194
194
|
lexer_spec: LexerSpec,
|
|
195
195
|
logger: &mut Logger,
|
|
196
|
+
limits: &ParserLimits,
|
|
196
197
|
) -> Result<Arc<CGrammar>> {
|
|
197
198
|
let log_grammar = logger.level_enabled(3) || (logger.level_enabled(2) && grammar.is_small());
|
|
198
199
|
if log_grammar {
|
|
@@ -226,7 +227,7 @@ fn compile_grammar(
|
|
|
226
227
|
writeln!(logger.info_logger(), " ==> {}", grammar.stats()).unwrap();
|
|
227
228
|
}
|
|
228
229
|
|
|
229
|
-
let grammars = Arc::new(grammar.compile(lexer_spec));
|
|
230
|
+
let grammars = Arc::new(grammar.compile(lexer_spec, limits)?);
|
|
230
231
|
|
|
231
232
|
loginfo!(
|
|
232
233
|
logger,
|