llguidance 0.7.20__tar.gz → 0.7.21__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 (174) hide show
  1. {llguidance-0.7.20 → llguidance-0.7.21}/CHANGELOG.md +5 -0
  2. {llguidance-0.7.20 → llguidance-0.7.21}/Cargo.lock +5 -5
  3. {llguidance-0.7.20 → llguidance-0.7.21}/PKG-INFO +3 -1
  4. {llguidance-0.7.20 → llguidance-0.7.21}/README.md +2 -0
  5. {llguidance-0.7.20 → llguidance-0.7.21}/parser/Cargo.toml +1 -1
  6. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/constraint.rs +10 -4
  7. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/formats.rs +9 -3
  8. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/matcher.rs +4 -3
  9. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/tokenparser.rs +37 -1
  10. {llguidance-0.7.20 → llguidance-0.7.21}/pyproject.toml +1 -1
  11. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/cli.py +1 -1
  12. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/hf.py +3 -3
  13. {llguidance-0.7.20 → llguidance-0.7.21}/python/torch_tests/test_hf.py +1 -1
  14. {llguidance-0.7.20 → llguidance-0.7.21}/python_ext/Cargo.toml +1 -1
  15. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/tests/test_lark.rs +34 -0
  16. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/tests/test_raw_parser.rs +29 -1
  17. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/install-deps.sh +1 -1
  18. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/Cargo.toml +1 -1
  19. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/src/toktree.rs +12 -10
  20. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie_hf_downloader/Cargo.toml +1 -1
  21. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie_hf_tokenizers/Cargo.toml +1 -1
  22. {llguidance-0.7.20 → llguidance-0.7.21}/.github/workflows/rust.yml +0 -0
  23. {llguidance-0.7.20 → llguidance-0.7.21}/.github/workflows/wheels.yml +0 -0
  24. {llguidance-0.7.20 → llguidance-0.7.21}/.gitignore +0 -0
  25. {llguidance-0.7.20 → llguidance-0.7.21}/CODE_OF_CONDUCT.md +0 -0
  26. {llguidance-0.7.20 → llguidance-0.7.21}/Cargo.toml +0 -0
  27. {llguidance-0.7.20 → llguidance-0.7.21}/LICENSE +0 -0
  28. {llguidance-0.7.20 → llguidance-0.7.21}/SECURITY.md +0 -0
  29. {llguidance-0.7.20 → llguidance-0.7.21}/SUPPORT.md +0 -0
  30. {llguidance-0.7.20 → llguidance-0.7.21}/c_sample/Makefile +0 -0
  31. {llguidance-0.7.20 → llguidance-0.7.21}/c_sample/README.md +0 -0
  32. {llguidance-0.7.20 → llguidance-0.7.21}/c_sample/c_sample.cpp +0 -0
  33. {llguidance-0.7.20 → llguidance-0.7.21}/docs/fast_forward.md +0 -0
  34. {llguidance-0.7.20 → llguidance-0.7.21}/docs/json_schema.md +0 -0
  35. {llguidance-0.7.20 → llguidance-0.7.21}/docs/mask_plot.png +0 -0
  36. {llguidance-0.7.20 → llguidance-0.7.21}/docs/optimizations.md +0 -0
  37. {llguidance-0.7.20 → llguidance-0.7.21}/docs/special_tokens.md +0 -0
  38. {llguidance-0.7.20 → llguidance-0.7.21}/docs/syntax.md +0 -0
  39. {llguidance-0.7.20 → llguidance-0.7.21}/docs/toktrie.md +0 -0
  40. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/Cargo.toml +0 -0
  41. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/expected_maskbench.json +0 -0
  42. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/jstats.sh +0 -0
  43. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/scripts/split-stats.sh +0 -0
  44. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/scripts/split_plot.py +0 -0
  45. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/src/json_stats.rs +0 -0
  46. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/src/lib.rs +0 -0
  47. {llguidance-0.7.20 → llguidance-0.7.21}/json_stats/src/stats.rs +0 -0
  48. {llguidance-0.7.20 → llguidance-0.7.21}/parser/LICENSE +0 -0
  49. {llguidance-0.7.20 → llguidance-0.7.21}/parser/README.md +0 -0
  50. {llguidance-0.7.20 → llguidance-0.7.21}/parser/build.rs +0 -0
  51. {llguidance-0.7.20 → llguidance-0.7.21}/parser/cbindgen.toml +0 -0
  52. {llguidance-0.7.20 → llguidance-0.7.21}/parser/grammars/character.json +0 -0
  53. {llguidance-0.7.20 → llguidance-0.7.21}/parser/grammars/json.json +0 -0
  54. {llguidance-0.7.20 → llguidance-0.7.21}/parser/llguidance.h +0 -0
  55. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/api.rs +0 -0
  56. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/from_guidance.rs +0 -0
  57. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/grammar.rs +0 -0
  58. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/lexer.rs +0 -0
  59. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/lexerspec.rs +0 -0
  60. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/mod.rs +0 -0
  61. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/parser.rs +0 -0
  62. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/perf.rs +0 -0
  63. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/regexvec.rs +0 -0
  64. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/earley/slicer.rs +0 -0
  65. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/factory.rs +0 -0
  66. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/ffi.rs +0 -0
  67. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/ffi_par.rs +0 -0
  68. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/grammar_builder.rs +0 -0
  69. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/README.md +0 -0
  70. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/compiler.rs +0 -0
  71. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/context_ref.rs +0 -0
  72. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/context_simple/context.rs +0 -0
  73. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/context_simple/draft.rs +0 -0
  74. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/context_simple/mod.rs +0 -0
  75. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/mod.rs +0 -0
  76. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/numeric.rs +0 -0
  77. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/schema.rs +0 -0
  78. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json/shared_context.rs +0 -0
  79. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/json_validation.rs +0 -0
  80. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lark/README.md +0 -0
  81. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lark/ast.rs +0 -0
  82. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lark/common.rs +0 -0
  83. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lark/compiler.rs +0 -0
  84. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lark/lexer.rs +0 -0
  85. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lark/mod.rs +0 -0
  86. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lark/parser.rs +0 -0
  87. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/lib.rs +0 -0
  88. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/logging.rs +0 -0
  89. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/output.rs +0 -0
  90. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/panic_utils.rs +0 -0
  91. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/regex_rewrite.rs +0 -0
  92. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/stop_controller.rs +0 -0
  93. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/substring.rs +0 -0
  94. {llguidance-0.7.20 → llguidance-0.7.21}/parser/src/tokenizer_json.rs +0 -0
  95. {llguidance-0.7.20 → llguidance-0.7.21}/plan.md +0 -0
  96. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/__init__.py +0 -0
  97. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/_grammar_from.py +0 -0
  98. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/_lib.pyi +0 -0
  99. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/_struct_tag.py +0 -0
  100. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/_tokenizer.py +0 -0
  101. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/_util.py +0 -0
  102. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/gbnf_to_lark.py +0 -0
  103. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/mlx.py +0 -0
  104. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/numpy.py +0 -0
  105. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/py.typed +0 -0
  106. {llguidance-0.7.20 → llguidance-0.7.21}/python/llguidance/torch.py +0 -0
  107. {llguidance-0.7.20 → llguidance-0.7.21}/python/mypy.ini +0 -0
  108. {llguidance-0.7.20 → llguidance-0.7.21}/python/torch_tests/__init__.py +0 -0
  109. {llguidance-0.7.20 → llguidance-0.7.21}/python/torch_tests/test_bitmask.py +0 -0
  110. {llguidance-0.7.20 → llguidance-0.7.21}/python/torch_tests/test_matcher.py +0 -0
  111. {llguidance-0.7.20 → llguidance-0.7.21}/python_ext/src/lib.rs +0 -0
  112. {llguidance-0.7.20 → llguidance-0.7.21}/python_ext/src/llinterpreter.rs +0 -0
  113. {llguidance-0.7.20 → llguidance-0.7.21}/python_ext/src/llmatcher.rs +0 -0
  114. {llguidance-0.7.20 → llguidance-0.7.21}/python_ext/src/parserlimits.rs +0 -0
  115. {llguidance-0.7.20 → llguidance-0.7.21}/python_ext/src/py.rs +0 -0
  116. {llguidance-0.7.20 → llguidance-0.7.21}/python_ext/src/pyjson.rs +0 -0
  117. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/Cargo.toml +0 -0
  118. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/README.md +0 -0
  119. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/cli.sh +0 -0
  120. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/blog.sample.json +0 -0
  121. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/blog.schema.json +0 -0
  122. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/blog.schema.ll.json +0 -0
  123. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/README.md +0 -0
  124. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/arithmetic.gbnf +0 -0
  125. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/c.gbnf +0 -0
  126. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/chess.gbnf +0 -0
  127. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/english.gbnf +0 -0
  128. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/japanese.gbnf +0 -0
  129. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/json.gbnf +0 -0
  130. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/json_arr.gbnf +0 -0
  131. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/list.gbnf +0 -0
  132. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/from-llama.cpp/vllm-sql.gbnf +0 -0
  133. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/lark.lark +0 -0
  134. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/rfc.lark +0 -0
  135. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/rfc.xml +0 -0
  136. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/data/ulysses.md +0 -0
  137. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/gtest.sh +0 -0
  138. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/lark.sh +0 -0
  139. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/run.sh +0 -0
  140. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/src/lib.rs +0 -0
  141. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/src/minimal.rs +0 -0
  142. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/src/sample_parser.rs +0 -0
  143. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/tests/test_ll.rs +0 -0
  144. {llguidance-0.7.20 → llguidance-0.7.21}/sample_parser/tests/test_stop.rs +0 -0
  145. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/annotate_asm.js +0 -0
  146. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/bump.py +0 -0
  147. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/cbindgen.sh +0 -0
  148. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/checklinks.py +0 -0
  149. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/checklinks.sh +0 -0
  150. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/ci-publish.py +0 -0
  151. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/disasm.sh +0 -0
  152. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/gbnf_to_lark.py +0 -0
  153. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/gen-testcase.py +0 -0
  154. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/git-version.sh +0 -0
  155. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/jsonschema-stats.js +0 -0
  156. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/remote-guidance-test.sh +0 -0
  157. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/rust-size.js +0 -0
  158. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/rust_size.py +0 -0
  159. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/test-guidance.sh +0 -0
  160. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/tokenizer_test.py +0 -0
  161. {llguidance-0.7.20 → llguidance-0.7.21}/scripts/update-git.py +0 -0
  162. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/LICENSE +0 -0
  163. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/README.md +0 -0
  164. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/src/bytes.rs +0 -0
  165. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/src/lib.rs +0 -0
  166. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/src/recognizer.rs +0 -0
  167. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/src/rng.rs +0 -0
  168. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/src/svob.rs +0 -0
  169. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/src/tokenv.rs +0 -0
  170. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie/tests/test_svob.rs +0 -0
  171. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie_hf_downloader/LICENSE +0 -0
  172. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie_hf_downloader/src/lib.rs +0 -0
  173. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie_hf_tokenizers/LICENSE +0 -0
  174. {llguidance-0.7.20 → llguidance-0.7.21}/toktrie_hf_tokenizers/src/lib.rs +0 -0
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. Dates are d
5
5
  If a release doesn't introduce any interesting changes (build fixes etc.), it's skipped.
6
6
 
7
7
 
8
+ #### [0.7.21](https://github.com/guidance-ai/llguidance/compare/v0.7.20...0.7.21) 2025-05-20
9
+
10
+ - include parser state in errors [`82e34da`](https://github.com/guidance-ai/llguidance/commit/82e34da704d22f04979d8cbc54a0ac00885a277d)
11
+ - tighten email format in JSON schema [`7454ea9`](https://github.com/guidance-ai/llguidance/commit/7454ea9df958f8bcc42e6bb986d6de397de65b3e)
12
+
8
13
  #### [0.7.20](https://github.com/guidance-ai/llguidance/compare/v0.7.19...0.7.20) 2025-05-15
9
14
 
10
15
  - use fancy-regex instead of onig as tokenizers regex library [`#172`](https://github.com/guidance-ai/llguidance/pull/172)
@@ -1174,7 +1174,7 @@ checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
1174
1174
 
1175
1175
  [[package]]
1176
1176
  name = "llguidance"
1177
- version = "0.7.20"
1177
+ version = "0.7.21"
1178
1178
  dependencies = [
1179
1179
  "anyhow",
1180
1180
  "derivre",
@@ -1193,7 +1193,7 @@ dependencies = [
1193
1193
 
1194
1194
  [[package]]
1195
1195
  name = "llguidance_py"
1196
- version = "0.7.20"
1196
+ version = "0.7.21"
1197
1197
  dependencies = [
1198
1198
  "anyhow",
1199
1199
  "bytemuck",
@@ -2336,7 +2336,7 @@ dependencies = [
2336
2336
 
2337
2337
  [[package]]
2338
2338
  name = "toktrie"
2339
- version = "0.7.20"
2339
+ version = "0.7.21"
2340
2340
  dependencies = [
2341
2341
  "anyhow",
2342
2342
  "bytemuck",
@@ -2347,7 +2347,7 @@ dependencies = [
2347
2347
 
2348
2348
  [[package]]
2349
2349
  name = "toktrie_hf_downloader"
2350
- version = "0.7.20"
2350
+ version = "0.7.21"
2351
2351
  dependencies = [
2352
2352
  "anyhow",
2353
2353
  "hf-hub",
@@ -2358,7 +2358,7 @@ dependencies = [
2358
2358
 
2359
2359
  [[package]]
2360
2360
  name = "toktrie_hf_tokenizers"
2361
- version = "0.7.20"
2361
+ version = "0.7.21"
2362
2362
  dependencies = [
2363
2363
  "anyhow",
2364
2364
  "log",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llguidance
3
- Version: 0.7.20
3
+ Version: 0.7.21
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-05-20 LLGuidance [shipped](https://x.com/OpenAIDevs/status/1924915341052019166) in [OpenAI](https://x.com/OpenAIDevs/status/1924915343677653014) for JSON Schema
23
24
  * 2025-04-11 integration [merged](https://github.com/chromium/chromium/commit/07ca6337c2f714ba0477202414bd2b1692e70594) into Chromium
24
25
  * 2025-03-25 integration [merged](https://github.com/vllm-project/vllm/pull/14779) into vLLM (v0.8.2)
25
26
  * 2025-02-26 integration [merged](https://github.com/sgl-project/sglang/pull/3298) into SGLang (v0.4.4)
@@ -59,6 +60,7 @@ The library can be used from:
59
60
 
60
61
  The library is currently integrated in:
61
62
  - [Guidance](https://github.com/guidance-ai/guidance) - library for interacting with LLMs
63
+ - [OpenAI models](https://x.com/OpenAIDevs/status/1924915343677653014) - LLGuidance powers [Structured Output](https://platform.openai.com/docs/guides/structured-outputs) (JSON Schema only)
62
64
  - [llama.cpp](https://github.com/ggerganov/llama.cpp/pull/10224) -
63
65
  available via `-DLLAMA_LLGUIDANCE=ON` option for `cmake`;
64
66
  llama.cpp can be also used Guidance Python package
@@ -8,6 +8,7 @@
8
8
 
9
9
  ---
10
10
 
11
+ * 2025-05-20 LLGuidance [shipped](https://x.com/OpenAIDevs/status/1924915341052019166) in [OpenAI](https://x.com/OpenAIDevs/status/1924915343677653014) for JSON Schema
11
12
  * 2025-04-11 integration [merged](https://github.com/chromium/chromium/commit/07ca6337c2f714ba0477202414bd2b1692e70594) into Chromium
12
13
  * 2025-03-25 integration [merged](https://github.com/vllm-project/vllm/pull/14779) into vLLM (v0.8.2)
13
14
  * 2025-02-26 integration [merged](https://github.com/sgl-project/sglang/pull/3298) into SGLang (v0.4.4)
@@ -47,6 +48,7 @@ The library can be used from:
47
48
 
48
49
  The library is currently integrated in:
49
50
  - [Guidance](https://github.com/guidance-ai/guidance) - library for interacting with LLMs
51
+ - [OpenAI models](https://x.com/OpenAIDevs/status/1924915343677653014) - LLGuidance powers [Structured Output](https://platform.openai.com/docs/guides/structured-outputs) (JSON Schema only)
50
52
  - [llama.cpp](https://github.com/ggerganov/llama.cpp/pull/10224) -
51
53
  available via `-DLLAMA_LLGUIDANCE=ON` option for `cmake`;
52
54
  llama.cpp can be also used Guidance Python package
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "llguidance"
3
- version = "0.7.20"
3
+ version = "0.7.21"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "Super-fast Structured Outputs"
@@ -137,7 +137,7 @@ impl Constraint {
137
137
  /// The splice is never returned when ff_tokens are disabled in InferenceCapabilities.
138
138
  /// After this returns, commit_token() must be called with the sampled token if any.
139
139
  pub fn compute_mask(&mut self) -> Result<&StepResult> {
140
- panic_utils::catch_unwind(std::panic::AssertUnwindSafe(|| self.compute_mask_inner()))
140
+ self.catch_unwind(|s| s.compute_mask_inner())
141
141
  .map(|_| &self.last_res)
142
142
  }
143
143
 
@@ -185,6 +185,14 @@ impl Constraint {
185
185
  self.parser.validate_tokens_raw(tokens)
186
186
  }
187
187
 
188
+ fn catch_unwind<F, R>(&mut self, f: F) -> Result<R>
189
+ where
190
+ F: FnOnce(&mut Self) -> Result<R>,
191
+ {
192
+ panic_utils::catch_unwind(std::panic::AssertUnwindSafe(|| f(self)))
193
+ .map_err(|e| anyhow::anyhow!(self.parser.augment_err(e)))
194
+ }
195
+
188
196
  /// commit_token() is a top-level method in this file and is called by
189
197
  /// the LLInterpreter::commit_token().
190
198
  ///
@@ -194,9 +202,7 @@ impl Constraint {
194
202
  /// It only returns 'STOP' if previous compute_mask() already returned 'STOP'
195
203
  /// (in which case there's little point calling commit_token()).
196
204
  pub fn commit_token(&mut self, sampled_token: Option<TokenId>) -> Result<CommitResult> {
197
- panic_utils::catch_unwind(std::panic::AssertUnwindSafe(|| {
198
- self.commit_token_inner(sampled_token)
199
- }))
205
+ self.catch_unwind(|s| s.commit_token_inner(sampled_token))
200
206
  }
201
207
 
202
208
  fn commit_token_inner(&mut self, sampled_token: Option<TokenId>) -> Result<CommitResult> {
@@ -27,9 +27,15 @@ pub fn lookup_format(name: &str) -> Option<&str> {
27
27
  "duration" => {
28
28
  r"P(?:(?P<dur_date>(?:(?P<dur_year>[0-9]+Y(?:[0-9]+M(?:[0-9]+D)?)?)|(?P<dur_month>[0-9]+M(?:[0-9]+D)?)|(?P<dur_day>[0-9]+D))(?:T(?:(?P<dur_hour>[0-9]+H(?:[0-9]+M(?:[0-9]+S)?)?)|(?P<dur_minute>[0-9]+M(?:[0-9]+S)?)|(?P<dur_second>[0-9]+S)))?)|(?P<dur_time>T(?:(?P<dur_hour2>[0-9]+H(?:[0-9]+M(?:[0-9]+S)?)?)|(?P<dur_minute2>[0-9]+M(?:[0-9]+S)?)|(?P<dur_second2>[0-9]+S)))|(?P<dur_week>[0-9]+W))"
29
29
  }
30
- "email" => {
31
- r"(?P<local_part>(?P<dot_string>[^\s@\.]+(\.[^\s@\.]+)*))@((?P<domain>(?P<sub_domain>[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)(\.(?P<sub_domain2>[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?))*)|\[(?P<ipv4>((([0-9])|(([1-9])[0-9]|(25[0-5]|(2[0-4]|(1)[0-9])[0-9])))\.){3}(([0-9])|(([1-9])[0-9]|(25[0-5]|(2[0-4]|(1)[0-9])[0-9]))))\])"
32
- }
30
+ // https://www.rfc-editor.org/rfc/inline-errata/rfc5321.html 4.1.2 -> Mailbox
31
+ "email" => concat!(
32
+ r"(?P<local_part>(?P<dot_string>[a-zA-Z0-9!#$%&'*+\-/=?\^_`{|}~]+(\.[a-zA-Z0-9!#$%&'*+\-/=?\^_`{|}~]+)*))",
33
+ r"@(",
34
+ r"(?P<domain>(?P<sub_domain>[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)(\.(?P<sub_domain2>[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?))*)",
35
+ r"|",
36
+ r"\[(?P<ipv4>((([0-9])|(([1-9])[0-9]|(25[0-5]|(2[0-4]|(1)[0-9])[0-9])))\.){3}(([0-9])|(([1-9])[0-9]|(25[0-5]|(2[0-4]|(1)[0-9])[0-9]))))\]",
37
+ r")"
38
+ ),
33
39
  "hostname" => {
34
40
  r"[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*"
35
41
  }
@@ -1,4 +1,4 @@
1
- use anyhow::{anyhow, ensure, Result};
1
+ use anyhow::{anyhow, bail, ensure, Result};
2
2
  use toktrie::{SimpleVob, TokEnv, TokenId};
3
3
 
4
4
  use crate::{api::StopReason, earley::ParserStats, panic_utils, TokenParser};
@@ -48,8 +48,9 @@ impl Matcher {
48
48
  match r {
49
49
  Ok(r) => Ok(r),
50
50
  Err(e) => {
51
- self.0 = MatcherState::Error(e.to_string());
52
- Err(e)
51
+ let msg = inner.parser.augment_err(e);
52
+ self.0 = MatcherState::Error(msg.clone());
53
+ bail!(msg);
53
54
  }
54
55
  }
55
56
  }
@@ -1,4 +1,4 @@
1
- use std::{hint::black_box, panic::AssertUnwindSafe, sync::Arc, time::Duration};
1
+ use std::{fmt::Display, hint::black_box, panic::AssertUnwindSafe, sync::Arc, time::Duration};
2
2
 
3
3
  use crate::{
4
4
  api::{GrammarInit, ParserLimits, StopReason},
@@ -22,6 +22,9 @@ pub struct TokenParser {
22
22
  max_step_stats: ParserStats,
23
23
  eos_token: TokenId,
24
24
 
25
+ had_rollback: bool,
26
+ had_backtrack: bool,
27
+
25
28
  is_accepting_cache: Option<bool>,
26
29
  ff_tokens_cache: Option<(Vec<TokenId>, Vec<u8>)>,
27
30
  stop_reason: StopReason,
@@ -110,6 +113,8 @@ impl TokenParser {
110
113
  max_tokens_total: max_tokens,
111
114
  last_bias_time: Duration::from_secs(0),
112
115
  is_fresh: true,
116
+ had_backtrack: false,
117
+ had_rollback: false,
113
118
  })
114
119
  }
115
120
 
@@ -268,6 +273,34 @@ impl TokenParser {
268
273
  res_prompt
269
274
  }
270
275
 
276
+ pub fn augment_err(&self, e: impl Display) -> String {
277
+ format!("{e}\n<state>\n{}\n</state>", self.dump_state())
278
+ }
279
+
280
+ pub fn dump_state(&self) -> String {
281
+ format!(
282
+ "Tokens: {}\n{} tokens, {} bytes; grm_prefix: {:?}\nFlags:{}{}\nLexer: {}\nParser: {}\nStop: {}\nError: {}",
283
+ self.tok_trie().tokens_dbg(&self.llm_tokens),
284
+ self.llm_tokens.len(),
285
+ self.llm_bytes.len(),
286
+ String::from_utf8_lossy(&self.grm_prefix),
287
+ if self.had_backtrack {
288
+ " had_backtrack"
289
+ } else {
290
+ ""
291
+ },
292
+ if self.had_rollback {
293
+ " had_rollback"
294
+ } else {
295
+ ""
296
+ },
297
+ self.parser.lexer_stats(),
298
+ self.parser.stats(),
299
+ self.stop_reason,
300
+ self.error_message.as_deref().unwrap_or("None"),
301
+ )
302
+ }
303
+
271
304
  fn clear_caches(&mut self) {
272
305
  self.is_accepting_cache = None;
273
306
  self.ff_tokens_cache = None;
@@ -332,6 +365,8 @@ impl TokenParser {
332
365
  // this will fail in case we're in error state or not initialized
333
366
  self.check_initialized("rollback")?;
334
367
 
368
+ self.had_rollback = true;
369
+
335
370
  let new_len = self.llm_tokens.len() - n_tokens;
336
371
  let mut bytes_to_drop = 0;
337
372
  for tok in &self.llm_tokens[new_len..] {
@@ -522,6 +557,7 @@ impl TokenParser {
522
557
  self.llm_bytes.extend_from_slice(tok_bytes);
523
558
 
524
559
  if backtrack_bytes0 != 0 {
560
+ self.had_backtrack = true;
525
561
  let mut backtrack_bytes: isize = backtrack_bytes0.try_into().unwrap();
526
562
  let mut backtrack_tokens = 0;
527
563
  while backtrack_bytes > 0 {
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "llguidance"
3
- version = "0.7.20"
3
+ version = "0.7.21"
4
4
  description = "Bindings for the Low-level Guidance (llguidance) Rust library for use within Guidance"
5
5
  requires-python = ">=3.9"
6
6
  license = "MIT"
@@ -1,7 +1,7 @@
1
1
  import argparse
2
2
  import json
3
3
  import huggingface_hub
4
- from transformers import AutoTokenizer # type: ignore[attr-defined]
4
+ from transformers import AutoTokenizer
5
5
  import llguidance
6
6
 
7
7
 
@@ -13,11 +13,11 @@ def from_tokenizer(
13
13
  """
14
14
  Create a new tokenizer from a fast Hugging Face tokenizer.
15
15
  This is an expensive operation (~1s), so the result should be cached.
16
- It also currently creates a non-canonical tokenizer, which means it cannot
17
- produce fast-forward tokens (though it can produce fast-forward bytes).
16
+ It currently only supports fast tokenizers, which are then handled
17
+ by the Rust tokenizers library.
18
18
 
19
19
  Args:
20
- hf_tokenizer: transformers.PreTrainedTokenizerBase - the tokenizer to wrap
20
+ hf_tokenizer: transformers.PreTrainedTokenizerFast - the tokenizer to wrap
21
21
  n_vocab: int - override the size of the vocabulary
22
22
  eos_token: int - override the EOS token
23
23
  slices: List[str] - configuration for slicer optimization; pass [] to disable,
@@ -17,7 +17,7 @@ from llguidance import LLMatcher, LLTokenizer, LLExecutor
17
17
 
18
18
  import llguidance.hf
19
19
 
20
- from transformers import AutoTokenizer # type: ignore[attr-defined]
20
+ from transformers import AutoTokenizer
21
21
 
22
22
 
23
23
  def _build_tokenizer() -> LLTokenizer:
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "llguidance_py"
3
- version = "0.7.20"
3
+ version = "0.7.21"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "Super-fast Structured Outputs"
@@ -1306,3 +1306,37 @@ fn test_json_min_max_properties() {
1306
1306
  ],
1307
1307
  );
1308
1308
  }
1309
+
1310
+ #[test]
1311
+ fn test_json_format_email() {
1312
+ json_test_many(
1313
+ &json!({
1314
+ "type": "string",
1315
+ "format": "email",
1316
+ }),
1317
+ &[
1318
+ json!("test@example.com"),
1319
+ json!("foo.bar@example.com"),
1320
+ json!("foo.bar@example-123.com"),
1321
+ json!("foo+bar@example-123.com"),
1322
+ json!("f$o#o`b-a!r@example-123.com"),
1323
+ json!("fo%o#bar@example-123.com"),
1324
+ json!("test@[192.168.1.1]"),
1325
+ ],
1326
+ &[
1327
+ json!(""),
1328
+ json!(" @example.com"),
1329
+ json!("test@"),
1330
+ json!("@example.com"),
1331
+ json!("test@.com"),
1332
+ json!("test@com"),
1333
+ json!("test@com."),
1334
+ json!("test@example..com"),
1335
+ json!("test@example.c"),
1336
+ json!("test@example.c."),
1337
+ json!("test@.example.com"),
1338
+ json!("test:2@example.com"),
1339
+ json!("test[2]@example.com"),
1340
+ ],
1341
+ );
1342
+ }
@@ -3,7 +3,7 @@ use llguidance::{
3
3
  api::TopLevelGrammar,
4
4
  earley::SlicedBiasComputer,
5
5
  toktrie::{InferenceCapabilities, TokEnv},
6
- ParserFactory, TokenParser,
6
+ Matcher, ParserFactory, TokenParser,
7
7
  };
8
8
  use serde_json::{json, Value};
9
9
 
@@ -207,3 +207,31 @@ fn test_ff_early() {
207
207
  parser.consume_token(*tok).unwrap();
208
208
  }
209
209
  }
210
+
211
+ #[test]
212
+ fn test_err_state() {
213
+ let lark = r#"
214
+ start: /[a-z]*/
215
+ "#;
216
+
217
+ let tokens = get_tok_env().tokenize("fobarbazqu123");
218
+ let mut t2 = vec![];
219
+ for _ in 0..100 {
220
+ t2.push(tokens[0]);
221
+ t2.push(tokens[1]);
222
+ t2.push(tokens[2]);
223
+ }
224
+ t2.extend_from_slice(&tokens);
225
+ let mut matcher = Matcher::new(Ok(make_parser(lark)));
226
+
227
+ for tok in t2.iter() {
228
+ if let Err(e) = matcher.consume_token(*tok) {
229
+ let e = e.to_string();
230
+ println!("Error: {}", e);
231
+ assert!(e.contains("<state>"));
232
+ assert!(e.contains("Tokens:"));
233
+ return;
234
+ }
235
+ }
236
+ unreachable!();
237
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  # installing guidance for deps
4
4
  pip install pytest guidance huggingface_hub tokenizers jsonschema maturin[zig] \
5
- torch transformers bitsandbytes ipython psutil mypy
5
+ torch transformers==4.52.1 bitsandbytes ipython psutil mypy
6
6
  pip uninstall -y guidance
7
7
 
8
8
  # print out versions
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "toktrie"
3
- version = "0.7.20"
3
+ version = "0.7.21"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "LLM Token Trie library"
@@ -295,26 +295,25 @@ impl TokTrie {
295
295
  }
296
296
 
297
297
  fn tokens_dbg_ext(&self, toks: &[u32], quote: bool) -> String {
298
+ // if the token list is too long, we are typically interested in the most recent ones
298
299
  let (limited, toks) = if toks.len() > Self::MAX_DBG_TOKENS {
299
- (true, &toks[0..Self::MAX_DBG_TOKENS])
300
+ ("…", &toks[toks.len() - Self::MAX_DBG_TOKENS..])
300
301
  } else {
301
- (false, toks)
302
+ ("", toks)
302
303
  };
303
304
 
304
- let mut joined = toks
305
+ let joined = toks
305
306
  .iter()
306
307
  .map(|t| self.token_dbg_ext(*t, false))
307
308
  .collect::<Vec<_>>()
308
309
  .join("‧");
309
310
 
310
- if limited {
311
- joined.push('…');
312
- }
313
-
314
311
  if quote {
315
- format!("⟦{}⟧", joined)
316
- } else {
312
+ format!("⟦{}{}⟧", limited, joined)
313
+ } else if limited.is_empty() {
317
314
  joined
315
+ } else {
316
+ format!("{}{}", limited, joined)
318
317
  }
319
318
  }
320
319
 
@@ -1037,9 +1036,12 @@ impl TrieHash {
1037
1036
  self.children.sort_by_key(|e| e.byte);
1038
1037
  for entry in &mut self.children {
1039
1038
  num_ch -= 1;
1039
+ assert!(num_parents < 0xff);
1040
1040
  entry.serialize(data, if num_ch == 0 { num_parents + 1 } else { 1 });
1041
1041
  }
1042
- data[idx].bits2 |= ((data.len() - idx) as u32) << 8;
1042
+ let subtree_size = data.len() - idx;
1043
+ assert!(subtree_size < 0x100_0000);
1044
+ data[idx].bits2 |= (subtree_size as u32) << 8;
1043
1045
  }
1044
1046
  }
1045
1047
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "toktrie_hf_downloader"
3
- version = "0.7.20"
3
+ version = "0.7.21"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "HuggingFace Hub download library support for toktrie and llguidance"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "toktrie_hf_tokenizers"
3
- version = "0.7.20"
3
+ version = "0.7.21"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "HuggingFace tokenizers library support for toktrie and llguidance"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes