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.
Files changed (184) hide show
  1. {llguidance-0.7.27 → llguidance-0.7.30}/CHANGELOG.md +13 -0
  2. {llguidance-0.7.27 → llguidance-0.7.30}/Cargo.lock +6 -6
  3. {llguidance-0.7.27 → llguidance-0.7.30}/PKG-INFO +5 -1
  4. {llguidance-0.7.27 → llguidance-0.7.30}/README.md +4 -0
  5. llguidance-0.7.30/docs/parametric.md +134 -0
  6. {llguidance-0.7.27 → llguidance-0.7.30}/docs/syntax.md +18 -4
  7. {llguidance-0.7.27 → llguidance-0.7.30}/parser/Cargo.toml +1 -1
  8. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/from_guidance.rs +4 -3
  9. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/grammar.rs +730 -56
  10. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/mod.rs +4 -1
  11. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/parser.rs +162 -55
  12. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/slicer.rs +1 -1
  13. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/grammar_builder.rs +146 -32
  14. llguidance-0.7.30/parser/src/hashcons.rs +84 -0
  15. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/ast.rs +8 -1
  16. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/compiler.rs +81 -18
  17. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/lexer.rs +83 -10
  18. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/parser.rs +279 -27
  19. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lib.rs +1 -0
  20. {llguidance-0.7.27 → llguidance-0.7.30}/pyproject.toml +1 -1
  21. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/Cargo.toml +1 -1
  22. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_lark.rs +369 -2
  23. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_raw_parser.rs +16 -0
  24. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/install-deps.sh +2 -1
  25. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/Cargo.toml +1 -1
  26. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/toktree.rs +27 -9
  27. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_downloader/Cargo.toml +1 -1
  28. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_tokenizers/Cargo.toml +1 -1
  29. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_tiktoken/Cargo.toml +1 -1
  30. {llguidance-0.7.27 → llguidance-0.7.30}/.github/workflows/rust.yml +0 -0
  31. {llguidance-0.7.27 → llguidance-0.7.30}/.github/workflows/wheels.yml +0 -0
  32. {llguidance-0.7.27 → llguidance-0.7.30}/.gitignore +0 -0
  33. {llguidance-0.7.27 → llguidance-0.7.30}/CODE_OF_CONDUCT.md +0 -0
  34. {llguidance-0.7.27 → llguidance-0.7.30}/Cargo.toml +0 -0
  35. {llguidance-0.7.27 → llguidance-0.7.30}/LICENSE +0 -0
  36. {llguidance-0.7.27 → llguidance-0.7.30}/SECURITY.md +0 -0
  37. {llguidance-0.7.27 → llguidance-0.7.30}/SUPPORT.md +0 -0
  38. {llguidance-0.7.27 → llguidance-0.7.30}/c_sample/Makefile +0 -0
  39. {llguidance-0.7.27 → llguidance-0.7.30}/c_sample/README.md +0 -0
  40. {llguidance-0.7.27 → llguidance-0.7.30}/c_sample/c_sample.cpp +0 -0
  41. {llguidance-0.7.27 → llguidance-0.7.30}/docs/fast_forward.md +0 -0
  42. {llguidance-0.7.27 → llguidance-0.7.30}/docs/json_schema.md +0 -0
  43. {llguidance-0.7.27 → llguidance-0.7.30}/docs/mask_plot.png +0 -0
  44. {llguidance-0.7.27 → llguidance-0.7.30}/docs/optimizations.md +0 -0
  45. {llguidance-0.7.27 → llguidance-0.7.30}/docs/special_tokens.md +0 -0
  46. {llguidance-0.7.27 → llguidance-0.7.30}/docs/toktrie.md +0 -0
  47. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/Cargo.toml +0 -0
  48. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/expected_maskbench.json +0 -0
  49. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/jstats.sh +0 -0
  50. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/scripts/split-stats.sh +0 -0
  51. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/scripts/split_plot.py +0 -0
  52. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/src/json_stats.rs +0 -0
  53. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/src/lib.rs +0 -0
  54. {llguidance-0.7.27 → llguidance-0.7.30}/json_stats/src/stats.rs +0 -0
  55. {llguidance-0.7.27 → llguidance-0.7.30}/parser/LICENSE +0 -0
  56. {llguidance-0.7.27 → llguidance-0.7.30}/parser/README.md +0 -0
  57. {llguidance-0.7.27 → llguidance-0.7.30}/parser/build.rs +0 -0
  58. {llguidance-0.7.27 → llguidance-0.7.30}/parser/cbindgen.toml +0 -0
  59. {llguidance-0.7.27 → llguidance-0.7.30}/parser/grammars/character.json +0 -0
  60. {llguidance-0.7.27 → llguidance-0.7.30}/parser/grammars/json.json +0 -0
  61. {llguidance-0.7.27 → llguidance-0.7.30}/parser/llguidance.h +0 -0
  62. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/api.rs +0 -0
  63. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/constraint.rs +0 -0
  64. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/lexer.rs +0 -0
  65. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/lexerspec.rs +0 -0
  66. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/perf.rs +0 -0
  67. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/earley/regexvec.rs +0 -0
  68. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/factory.rs +0 -0
  69. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/ffi.rs +0 -0
  70. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/ffi_par.rs +0 -0
  71. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/README.md +0 -0
  72. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/compiler.rs +0 -0
  73. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_ref.rs +0 -0
  74. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_simple/context.rs +0 -0
  75. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_simple/draft.rs +0 -0
  76. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/context_simple/mod.rs +0 -0
  77. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/formats.rs +0 -0
  78. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/mod.rs +0 -0
  79. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/numeric.rs +0 -0
  80. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/schema.rs +0 -0
  81. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json/shared_context.rs +0 -0
  82. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/json_validation.rs +0 -0
  83. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/README.md +0 -0
  84. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/common.rs +0 -0
  85. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/lark/mod.rs +0 -0
  86. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/logging.rs +0 -0
  87. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/matcher.rs +0 -0
  88. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/output.rs +0 -0
  89. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/panic_utils.rs +0 -0
  90. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/regex_rewrite.rs +0 -0
  91. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/stop_controller.rs +0 -0
  92. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/substring.rs +0 -0
  93. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/tokenizer_json.rs +0 -0
  94. {llguidance-0.7.27 → llguidance-0.7.30}/parser/src/tokenparser.rs +0 -0
  95. {llguidance-0.7.27 → llguidance-0.7.30}/plan.md +0 -0
  96. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/__init__.py +0 -0
  97. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_grammar_from.py +0 -0
  98. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_lib.pyi +0 -0
  99. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_struct_tag.py +0 -0
  100. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_tokenizer.py +0 -0
  101. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/_util.py +0 -0
  102. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/cli.py +0 -0
  103. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/gbnf_to_lark.py +0 -0
  104. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/hf.py +0 -0
  105. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/llamacpp.py +0 -0
  106. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/mlx.py +0 -0
  107. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/numpy.py +0 -0
  108. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/py.typed +0 -0
  109. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/tiktoken.py +0 -0
  110. {llguidance-0.7.27 → llguidance-0.7.30}/python/llguidance/torch.py +0 -0
  111. {llguidance-0.7.27 → llguidance-0.7.30}/python/mypy.ini +0 -0
  112. {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/__init__.py +0 -0
  113. {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_bitmask.py +0 -0
  114. {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_hf.py +0 -0
  115. {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_llamacpp.py +0 -0
  116. {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_matcher.py +0 -0
  117. {llguidance-0.7.27 → llguidance-0.7.30}/python/torch_tests/test_tiktoken.py +0 -0
  118. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/lib.rs +0 -0
  119. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/llamatokenizer.rs +0 -0
  120. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/llinterpreter.rs +0 -0
  121. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/llmatcher.rs +0 -0
  122. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/parserlimits.rs +0 -0
  123. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/py.rs +0 -0
  124. {llguidance-0.7.27 → llguidance-0.7.30}/python_ext/src/pyjson.rs +0 -0
  125. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/Cargo.toml +0 -0
  126. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/README.md +0 -0
  127. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/cli.sh +0 -0
  128. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/blog.sample.json +0 -0
  129. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/blog.schema.json +0 -0
  130. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/blog.schema.ll.json +0 -0
  131. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/README.md +0 -0
  132. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/arithmetic.gbnf +0 -0
  133. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/c.gbnf +0 -0
  134. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/chess.gbnf +0 -0
  135. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/english.gbnf +0 -0
  136. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/japanese.gbnf +0 -0
  137. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/json.gbnf +0 -0
  138. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/json_arr.gbnf +0 -0
  139. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/list.gbnf +0 -0
  140. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/from-llama.cpp/vllm-sql.gbnf +0 -0
  141. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/lark.lark +0 -0
  142. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/rfc.lark +0 -0
  143. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/rfc.xml +0 -0
  144. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/data/ulysses.md +0 -0
  145. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/gtest.sh +0 -0
  146. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/lark.sh +0 -0
  147. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/run.sh +0 -0
  148. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/src/lib.rs +0 -0
  149. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/src/minimal.rs +0 -0
  150. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/src/sample_parser.rs +0 -0
  151. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_ll.rs +0 -0
  152. {llguidance-0.7.27 → llguidance-0.7.30}/sample_parser/tests/test_stop.rs +0 -0
  153. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/annotate_asm.js +0 -0
  154. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/bump.py +0 -0
  155. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/cbindgen.sh +0 -0
  156. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/checklinks.py +0 -0
  157. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/checklinks.sh +0 -0
  158. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/ci-publish.py +0 -0
  159. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/disasm.sh +0 -0
  160. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/gbnf_to_lark.py +0 -0
  161. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/gen-testcase.py +0 -0
  162. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/git-version.sh +0 -0
  163. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/jsonschema-stats.js +0 -0
  164. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/remote-guidance-test.sh +0 -0
  165. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/rust-size.js +0 -0
  166. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/rust_size.py +0 -0
  167. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/test-guidance.sh +0 -0
  168. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/tokenizer_test.py +0 -0
  169. {llguidance-0.7.27 → llguidance-0.7.30}/scripts/update-git.py +0 -0
  170. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/LICENSE +0 -0
  171. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/README.md +0 -0
  172. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/bytes.rs +0 -0
  173. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/lib.rs +0 -0
  174. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/recognizer.rs +0 -0
  175. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/rng.rs +0 -0
  176. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/svob.rs +0 -0
  177. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/src/tokenv.rs +0 -0
  178. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie/tests/test_svob.rs +0 -0
  179. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_downloader/LICENSE +0 -0
  180. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_downloader/src/lib.rs +0 -0
  181. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_tokenizers/LICENSE +0 -0
  182. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_hf_tokenizers/src/lib.rs +0 -0
  183. {llguidance-0.7.27 → llguidance-0.7.30}/toktrie_tiktoken/LICENSE +0 -0
  184. {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.27"
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.27"
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.27"
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.27"
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.27"
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.27"
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.27
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> json
112
- json: %json { ... }
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> json` as the grammar.
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).
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "llguidance"
3
- version = "0.7.27"
3
+ version = "0.7.30"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "Super-fast Structured Outputs"
@@ -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,