llguidance 1.3.0__tar.gz → 1.4.0__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 (195) hide show
  1. {llguidance-1.3.0 → llguidance-1.4.0}/.github/workflows/rust.yml +14 -1
  2. {llguidance-1.3.0 → llguidance-1.4.0}/CHANGELOG.md +10 -0
  3. {llguidance-1.3.0 → llguidance-1.4.0}/Cargo.lock +39 -18
  4. {llguidance-1.3.0 → llguidance-1.4.0}/PKG-INFO +4 -4
  5. {llguidance-1.3.0 → llguidance-1.4.0}/README.md +2 -2
  6. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/jstats.sh +0 -0
  7. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/scripts/split-stats.sh +0 -0
  8. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/scripts/split_plot.py +0 -0
  9. {llguidance-1.3.0 → llguidance-1.4.0}/parser/Cargo.toml +1 -1
  10. {llguidance-1.3.0 → llguidance-1.4.0}/pyproject.toml +2 -2
  11. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/gbnf_to_lark.py +0 -0
  12. {llguidance-1.3.0 → llguidance-1.4.0}/python/mypy.ini +1 -1
  13. {llguidance-1.3.0 → llguidance-1.4.0}/python/torch_tests/test_matcher.py +2 -2
  14. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/Cargo.toml +2 -2
  15. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/src/llinterpreter.rs +1 -1
  16. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/src/llmatcher.rs +11 -11
  17. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/src/py.rs +1 -1
  18. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/src/pyjson.rs +4 -4
  19. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/Cargo.toml +1 -0
  20. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/cli.sh +0 -0
  21. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/gtest.sh +0 -0
  22. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/lark.sh +0 -0
  23. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/run.sh +0 -0
  24. llguidance-1.4.0/sample_parser/tests/test_json_x_guidance.rs +367 -0
  25. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/bump.py +0 -0
  26. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/cbindgen.sh +0 -0
  27. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/checklinks.py +0 -0
  28. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/checklinks.sh +0 -0
  29. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/ci-publish.py +0 -0
  30. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/disasm.sh +0 -0
  31. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/gbnf_to_lark.py +0 -0
  32. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/gen-testcase.py +0 -0
  33. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/git-version.sh +0 -0
  34. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/install-deps.sh +0 -0
  35. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/remote-guidance-test.sh +0 -0
  36. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/rust_size.py +0 -0
  37. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/test-guidance.sh +1 -0
  38. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/update-git.py +0 -0
  39. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/Cargo.toml +1 -1
  40. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_hf_downloader/Cargo.toml +1 -1
  41. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_hf_tokenizers/Cargo.toml +1 -1
  42. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_hf_tokenizers/src/lib.rs +79 -0
  43. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_tiktoken/Cargo.toml +1 -1
  44. llguidance-1.3.0/sample_parser/tests/test_json_x_guidance.rs +0 -81
  45. {llguidance-1.3.0 → llguidance-1.4.0}/.github/workflows/code-coverage.yml +0 -0
  46. {llguidance-1.3.0 → llguidance-1.4.0}/.github/workflows/wheels.yml +0 -0
  47. {llguidance-1.3.0 → llguidance-1.4.0}/.gitignore +0 -0
  48. {llguidance-1.3.0 → llguidance-1.4.0}/CODE_OF_CONDUCT.md +0 -0
  49. {llguidance-1.3.0 → llguidance-1.4.0}/Cargo.toml +0 -0
  50. {llguidance-1.3.0 → llguidance-1.4.0}/LICENSE +0 -0
  51. {llguidance-1.3.0 → llguidance-1.4.0}/SECURITY.md +0 -0
  52. {llguidance-1.3.0 → llguidance-1.4.0}/SUPPORT.md +0 -0
  53. {llguidance-1.3.0 → llguidance-1.4.0}/c_sample/Makefile +0 -0
  54. {llguidance-1.3.0 → llguidance-1.4.0}/c_sample/README.md +0 -0
  55. {llguidance-1.3.0 → llguidance-1.4.0}/c_sample/c_sample.cpp +0 -0
  56. {llguidance-1.3.0 → llguidance-1.4.0}/docs/de_recursing.md +0 -0
  57. {llguidance-1.3.0 → llguidance-1.4.0}/docs/fast_forward.md +0 -0
  58. {llguidance-1.3.0 → llguidance-1.4.0}/docs/json_schema.md +0 -0
  59. {llguidance-1.3.0 → llguidance-1.4.0}/docs/mask_plot.png +0 -0
  60. {llguidance-1.3.0 → llguidance-1.4.0}/docs/optimizations.md +0 -0
  61. {llguidance-1.3.0 → llguidance-1.4.0}/docs/parametric.md +0 -0
  62. {llguidance-1.3.0 → llguidance-1.4.0}/docs/special_tokens.md +0 -0
  63. {llguidance-1.3.0 → llguidance-1.4.0}/docs/syntax.md +0 -0
  64. {llguidance-1.3.0 → llguidance-1.4.0}/docs/toktrie.md +0 -0
  65. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/Cargo.toml +0 -0
  66. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/expected_maskbench.json +0 -0
  67. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/src/json_stats.rs +0 -0
  68. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/src/lib.rs +0 -0
  69. {llguidance-1.3.0 → llguidance-1.4.0}/json_stats/src/stats.rs +0 -0
  70. {llguidance-1.3.0 → llguidance-1.4.0}/parser/LICENSE +0 -0
  71. {llguidance-1.3.0 → llguidance-1.4.0}/parser/README.md +0 -0
  72. {llguidance-1.3.0 → llguidance-1.4.0}/parser/build.rs +0 -0
  73. {llguidance-1.3.0 → llguidance-1.4.0}/parser/cbindgen.toml +0 -0
  74. {llguidance-1.3.0 → llguidance-1.4.0}/parser/grammars/character.json +0 -0
  75. {llguidance-1.3.0 → llguidance-1.4.0}/parser/grammars/json.json +0 -0
  76. {llguidance-1.3.0 → llguidance-1.4.0}/parser/llguidance.h +0 -0
  77. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/api.rs +0 -0
  78. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/constraint.rs +0 -0
  79. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/from_guidance.rs +0 -0
  80. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/grammar.rs +0 -0
  81. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/lexer.rs +0 -0
  82. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/lexerspec.rs +0 -0
  83. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/mod.rs +0 -0
  84. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/parser.rs +0 -0
  85. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/perf.rs +0 -0
  86. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/regexvec.rs +0 -0
  87. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/earley/slicer.rs +0 -0
  88. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/factory.rs +0 -0
  89. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/ffi.rs +0 -0
  90. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/ffi_par.rs +0 -0
  91. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/grammar_builder.rs +0 -0
  92. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/hashcons.rs +0 -0
  93. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/README.md +0 -0
  94. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/compiler.rs +0 -0
  95. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/context_ref.rs +0 -0
  96. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/context_simple/context.rs +0 -0
  97. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/context_simple/draft.rs +0 -0
  98. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/context_simple/mod.rs +0 -0
  99. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/formats.rs +0 -0
  100. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/mod.rs +0 -0
  101. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/numeric.rs +0 -0
  102. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/schema.rs +0 -0
  103. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json/shared_context.rs +0 -0
  104. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/json_validation.rs +0 -0
  105. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lark/README.md +0 -0
  106. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lark/ast.rs +0 -0
  107. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lark/common.rs +0 -0
  108. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lark/compiler.rs +0 -0
  109. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lark/lexer.rs +0 -0
  110. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lark/mod.rs +0 -0
  111. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lark/parser.rs +0 -0
  112. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/lib.rs +0 -0
  113. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/logging.rs +0 -0
  114. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/matcher.rs +0 -0
  115. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/output.rs +0 -0
  116. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/panic_utils.rs +0 -0
  117. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/regex_rewrite.rs +0 -0
  118. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/stop_controller.rs +0 -0
  119. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/substring.rs +0 -0
  120. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/tokenizer_json.rs +0 -0
  121. {llguidance-1.3.0 → llguidance-1.4.0}/parser/src/tokenparser.rs +0 -0
  122. {llguidance-1.3.0 → llguidance-1.4.0}/plan.md +0 -0
  123. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/__init__.py +0 -0
  124. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/_grammar_from.py +0 -0
  125. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/_lib.pyi +0 -0
  126. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/_struct_tag.py +0 -0
  127. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/_tokenizer.py +0 -0
  128. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/_util.py +0 -0
  129. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/cli.py +0 -0
  130. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/hf.py +0 -0
  131. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/llamacpp.py +0 -0
  132. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/mlx.py +0 -0
  133. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/numpy.py +0 -0
  134. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/py.typed +0 -0
  135. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/tiktoken.py +0 -0
  136. {llguidance-1.3.0 → llguidance-1.4.0}/python/llguidance/torch.py +0 -0
  137. {llguidance-1.3.0 → llguidance-1.4.0}/python/torch_tests/__init__.py +0 -0
  138. {llguidance-1.3.0 → llguidance-1.4.0}/python/torch_tests/test_bitmask.py +0 -0
  139. {llguidance-1.3.0 → llguidance-1.4.0}/python/torch_tests/test_hf.py +0 -0
  140. {llguidance-1.3.0 → llguidance-1.4.0}/python/torch_tests/test_llamacpp.py +0 -0
  141. {llguidance-1.3.0 → llguidance-1.4.0}/python/torch_tests/test_tiktoken.py +0 -0
  142. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/src/lib.rs +0 -0
  143. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/src/llamatokenizer.rs +0 -0
  144. {llguidance-1.3.0 → llguidance-1.4.0}/python_ext/src/parserlimits.rs +0 -0
  145. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/README.md +0 -0
  146. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/blog.sample.json +0 -0
  147. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/blog.schema.json +0 -0
  148. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/blog.schema.ll.json +0 -0
  149. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/README.md +0 -0
  150. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/arithmetic.gbnf +0 -0
  151. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/c.gbnf +0 -0
  152. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/chess.gbnf +0 -0
  153. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/english.gbnf +0 -0
  154. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/japanese.gbnf +0 -0
  155. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/json.gbnf +0 -0
  156. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/json_arr.gbnf +0 -0
  157. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/list.gbnf +0 -0
  158. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/vllm-sql.gbnf +0 -0
  159. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/lark.lark +0 -0
  160. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/rfc.lark +0 -0
  161. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/rfc.xml +0 -0
  162. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/data/ulysses.md +0 -0
  163. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/src/lib.rs +0 -0
  164. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/src/minimal.rs +0 -0
  165. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/src/sample_parser.rs +0 -0
  166. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/common_lark_utils/mod.rs +0 -0
  167. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_json_arrays.rs +0 -0
  168. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_json_enum_const.rs +0 -0
  169. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_json_objects.rs +0 -0
  170. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_json_primitives.rs +0 -0
  171. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_json_schema_combinations.rs +0 -0
  172. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_json_string_format.rs +0 -0
  173. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_lark.rs +0 -0
  174. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_ll.rs +0 -0
  175. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_raw_parser.rs +0 -0
  176. {llguidance-1.3.0 → llguidance-1.4.0}/sample_parser/tests/test_stop.rs +0 -0
  177. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/annotate_asm.js +0 -0
  178. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/jsonschema-stats.js +0 -0
  179. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/rust-size.js +0 -0
  180. {llguidance-1.3.0 → llguidance-1.4.0}/scripts/tokenizer_test.py +0 -0
  181. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/LICENSE +0 -0
  182. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/README.md +0 -0
  183. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/src/bytes.rs +0 -0
  184. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/src/lib.rs +0 -0
  185. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/src/recognizer.rs +0 -0
  186. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/src/rng.rs +0 -0
  187. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/src/svob.rs +0 -0
  188. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/src/tokenv.rs +0 -0
  189. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/src/toktree.rs +0 -0
  190. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie/tests/test_svob.rs +0 -0
  191. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_hf_downloader/LICENSE +0 -0
  192. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_hf_downloader/src/lib.rs +0 -0
  193. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_hf_tokenizers/LICENSE +0 -0
  194. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_tiktoken/LICENSE +0 -0
  195. {llguidance-1.3.0 → llguidance-1.4.0}/toktrie_tiktoken/src/lib.rs +0 -0
@@ -5,6 +5,16 @@ on:
5
5
  branches: [ "main" ]
6
6
  pull_request:
7
7
  branches: [ "main" ]
8
+ workflow_dispatch:
9
+ inputs:
10
+ commit_id:
11
+ description: 'Branch or Commit ID (optional)'
12
+ required: false
13
+ type: string
14
+ schedule:
15
+ # * is a special character in YAML so we quote this string
16
+ # Run at 09:10 UTC every day
17
+ - cron: '10 09 * * *'
8
18
 
9
19
  env:
10
20
  CARGO_TERM_COLOR: always
@@ -15,7 +25,10 @@ jobs:
15
25
  runs-on: ubuntu-latest
16
26
 
17
27
  steps:
18
- - uses: actions/checkout@v4
28
+ - name: Checkout repo at ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
29
+ uses: actions/checkout@v4
30
+ with:
31
+ ref: ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
19
32
 
20
33
  - name: Build parser
21
34
  run: cargo build --verbose
@@ -4,6 +4,16 @@ 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
+ #### [v1.4.0](https://github.com/guidance-ai/llguidance/compare/v1.3.0...v1.4.0) 2025-11-18
8
+
9
+ - Update pyo3 dependency to latest version to support python 3.14t [`#255`](https://github.com/guidance-ai/llguidance/pull/255)
10
+ - Thank you [@ngoldbaum](https://github.com/ngoldbaum)!
11
+ - Fix tokenization of special tokens for ByteTokenizer [`#249`](https://github.com/guidance-ai/llguidance/pull/249)
12
+ - Thank you [@daulet](https://github.com/daulet)!
13
+ - Bump minimum python version to 3.10 [`#252`](https://github.com/guidance-ai/llguidance/pull/252)
14
+ - Update MSRV in README [`30d1515`](https://github.com/guidance-ai/llguidance/commit/30d15150e2c6bae9e52dea58c72574c160f4697a)
15
+ - Thank you for pointing out the error [@nteodosio](https://github.com/nteodosio)!
16
+
7
17
  #### [v1.3.0](https://github.com/guidance-ai/llguidance/compare/v1.2.0...v1.3.0) 2025-10-20
8
18
 
9
19
  - change semantics of JSON separators (now regex patterns instead of text literals) [`#246`](https://github.com/guidance-ai/llguidance/pull/246)
@@ -1241,7 +1241,7 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
1241
1241
 
1242
1242
  [[package]]
1243
1243
  name = "llguidance"
1244
- version = "1.3.0"
1244
+ version = "1.4.0"
1245
1245
  dependencies = [
1246
1246
  "anyhow",
1247
1247
  "derivre",
@@ -1260,7 +1260,7 @@ dependencies = [
1260
1260
 
1261
1261
  [[package]]
1262
1262
  name = "llguidance_py"
1263
- version = "1.3.0"
1263
+ version = "1.4.0"
1264
1264
  dependencies = [
1265
1265
  "anyhow",
1266
1266
  "bytemuck",
@@ -1669,12 +1669,11 @@ dependencies = [
1669
1669
 
1670
1670
  [[package]]
1671
1671
  name = "pyo3"
1672
- version = "0.24.2"
1672
+ version = "0.27.1"
1673
1673
  source = "registry+https://github.com/rust-lang/crates.io-index"
1674
- checksum = "e5203598f366b11a02b13aa20cab591229ff0a89fd121a308a5df751d5fc9219"
1674
+ checksum = "37a6df7eab65fc7bee654a421404947e10a0f7085b6951bf2ea395f4659fb0cf"
1675
1675
  dependencies = [
1676
1676
  "anyhow",
1677
- "cfg-if",
1678
1677
  "indoc",
1679
1678
  "libc",
1680
1679
  "memoffset",
@@ -1688,19 +1687,18 @@ dependencies = [
1688
1687
 
1689
1688
  [[package]]
1690
1689
  name = "pyo3-build-config"
1691
- version = "0.24.2"
1690
+ version = "0.27.1"
1692
1691
  source = "registry+https://github.com/rust-lang/crates.io-index"
1693
- checksum = "99636d423fa2ca130fa5acde3059308006d46f98caac629418e53f7ebb1e9999"
1692
+ checksum = "f77d387774f6f6eec64a004eac0ed525aab7fa1966d94b42f743797b3e395afb"
1694
1693
  dependencies = [
1695
- "once_cell",
1696
1694
  "target-lexicon",
1697
1695
  ]
1698
1696
 
1699
1697
  [[package]]
1700
1698
  name = "pyo3-ffi"
1701
- version = "0.24.2"
1699
+ version = "0.27.1"
1702
1700
  source = "registry+https://github.com/rust-lang/crates.io-index"
1703
- checksum = "78f9cf92ba9c409279bc3305b5409d90db2d2c22392d443a87df3a1adad59e33"
1701
+ checksum = "2dd13844a4242793e02df3e2ec093f540d948299a6a77ea9ce7afd8623f542be"
1704
1702
  dependencies = [
1705
1703
  "libc",
1706
1704
  "pyo3-build-config",
@@ -1708,9 +1706,9 @@ dependencies = [
1708
1706
 
1709
1707
  [[package]]
1710
1708
  name = "pyo3-macros"
1711
- version = "0.24.2"
1709
+ version = "0.27.1"
1712
1710
  source = "registry+https://github.com/rust-lang/crates.io-index"
1713
- checksum = "0b999cb1a6ce21f9a6b147dcf1be9ffedf02e0043aec74dc390f3007047cecd9"
1711
+ checksum = "eaf8f9f1108270b90d3676b8679586385430e5c0bb78bb5f043f95499c821a71"
1714
1712
  dependencies = [
1715
1713
  "proc-macro2",
1716
1714
  "pyo3-macros-backend",
@@ -1720,9 +1718,9 @@ dependencies = [
1720
1718
 
1721
1719
  [[package]]
1722
1720
  name = "pyo3-macros-backend"
1723
- version = "0.24.2"
1721
+ version = "0.27.1"
1724
1722
  source = "registry+https://github.com/rust-lang/crates.io-index"
1725
- checksum = "822ece1c7e1012745607d5cf0bcb2874769f0f7cb34c4cde03b9358eb9ef911a"
1723
+ checksum = "70a3b2274450ba5288bc9b8c1b69ff569d1d61189d4bff38f8d22e03d17f932b"
1726
1724
  dependencies = [
1727
1725
  "heck",
1728
1726
  "proc-macro2",
@@ -2074,6 +2072,7 @@ dependencies = [
2074
2072
  "llguidance",
2075
2073
  "rstest",
2076
2074
  "serde",
2075
+ "serde-json-fmt",
2077
2076
  "serde_json",
2078
2077
  "toktrie_hf_downloader",
2079
2078
  "toktrie_hf_tokenizers",
@@ -2132,6 +2131,17 @@ dependencies = [
2132
2131
  "serde_derive",
2133
2132
  ]
2134
2133
 
2134
+ [[package]]
2135
+ name = "serde-json-fmt"
2136
+ version = "0.1.0"
2137
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2138
+ checksum = "a4a33b7a5f52a26d520099339add40c48baf2e5ada194c8cc1b18cafa2b5e419"
2139
+ dependencies = [
2140
+ "serde",
2141
+ "serde_json",
2142
+ "smartstring",
2143
+ ]
2144
+
2135
2145
  [[package]]
2136
2146
  name = "serde_derive"
2137
2147
  version = "1.0.219"
@@ -2186,6 +2196,17 @@ version = "1.15.1"
2186
2196
  source = "registry+https://github.com/rust-lang/crates.io-index"
2187
2197
  checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
2188
2198
 
2199
+ [[package]]
2200
+ name = "smartstring"
2201
+ version = "1.0.1"
2202
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2203
+ checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
2204
+ dependencies = [
2205
+ "autocfg",
2206
+ "static_assertions",
2207
+ "version_check",
2208
+ ]
2209
+
2189
2210
  [[package]]
2190
2211
  name = "socket2"
2191
2212
  version = "0.5.10"
@@ -2478,7 +2499,7 @@ dependencies = [
2478
2499
 
2479
2500
  [[package]]
2480
2501
  name = "toktrie"
2481
- version = "1.3.0"
2502
+ version = "1.4.0"
2482
2503
  dependencies = [
2483
2504
  "anyhow",
2484
2505
  "bytemuck",
@@ -2489,7 +2510,7 @@ dependencies = [
2489
2510
 
2490
2511
  [[package]]
2491
2512
  name = "toktrie_hf_downloader"
2492
- version = "1.3.0"
2513
+ version = "1.4.0"
2493
2514
  dependencies = [
2494
2515
  "anyhow",
2495
2516
  "hf-hub",
@@ -2500,7 +2521,7 @@ dependencies = [
2500
2521
 
2501
2522
  [[package]]
2502
2523
  name = "toktrie_hf_tokenizers"
2503
- version = "1.3.0"
2524
+ version = "1.4.0"
2504
2525
  dependencies = [
2505
2526
  "anyhow",
2506
2527
  "log",
@@ -2512,7 +2533,7 @@ dependencies = [
2512
2533
 
2513
2534
  [[package]]
2514
2535
  name = "toktrie_tiktoken"
2515
- version = "1.3.0"
2536
+ version = "1.4.0"
2516
2537
  dependencies = [
2517
2538
  "anyhow",
2518
2539
  "log",
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llguidance
3
- Version: 1.3.0
3
+ Version: 1.4.0
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
7
7
  License-Expression: MIT
8
- Requires-Python: >=3.9
8
+ Requires-Python: >=3.10
9
9
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
10
10
  Project-URL: repository, https://github.com/microsoft/llguidance
11
11
  Project-URL: issue_tracker, https://github.com/microsoft/llguidance/issues
@@ -111,14 +111,14 @@ Thus, with 16 cores and a 10ms forward pass, llguidance can handle batch sizes u
111
111
 
112
112
  ## Building
113
113
 
114
- - [install rust](https://www.rust-lang.org/tools/install); 1.75 or later
114
+ - [install rust](https://www.rust-lang.org/tools/install); 1.87 or later
115
115
 
116
116
  If you just need the C or Rust library (`llguidance`),
117
117
  check the [parser](./parser/README.md) directory.
118
118
 
119
119
  For Python bindings:
120
120
 
121
- - install python 3.9 or later; very likely you'll need a virtual env/conda
121
+ - install python 3.10 or later; very likely you'll need a virtual env/conda
122
122
  - run `./scripts/install-deps.sh`
123
123
  - to build and after any changes, run `./scripts/test-guidance.sh`
124
124
 
@@ -99,14 +99,14 @@ Thus, with 16 cores and a 10ms forward pass, llguidance can handle batch sizes u
99
99
 
100
100
  ## Building
101
101
 
102
- - [install rust](https://www.rust-lang.org/tools/install); 1.75 or later
102
+ - [install rust](https://www.rust-lang.org/tools/install); 1.87 or later
103
103
 
104
104
  If you just need the C or Rust library (`llguidance`),
105
105
  check the [parser](./parser/README.md) directory.
106
106
 
107
107
  For Python bindings:
108
108
 
109
- - install python 3.9 or later; very likely you'll need a virtual env/conda
109
+ - install python 3.10 or later; very likely you'll need a virtual env/conda
110
110
  - run `./scripts/install-deps.sh`
111
111
  - to build and after any changes, run `./scripts/test-guidance.sh`
112
112
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "llguidance"
3
- version = "1.3.0"
3
+ version = "1.4.0"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "Super-fast Structured Outputs"
@@ -1,8 +1,8 @@
1
1
  [project]
2
2
  name = "llguidance"
3
- version = "1.3.0"
3
+ version = "1.4.0"
4
4
  description = "Bindings for the Low-level Guidance (llguidance) Rust library for use within Guidance"
5
- requires-python = ">=3.9"
5
+ requires-python = ">=3.10"
6
6
  license = "MIT"
7
7
  authors = [{name = "Michal Moskal"}]
8
8
  dependencies = []
@@ -2,4 +2,4 @@
2
2
  strict = True
3
3
  files = llguidance, torch_tests
4
4
  exclude = tmp
5
- python_version = 3.9
5
+ python_version = 3.10
@@ -178,11 +178,11 @@ def test_par_errors() -> None:
178
178
  with pytest.raises(RuntimeError, match="Already borrowed"):
179
179
  fill_next_token_bitmask_par(exec, [(g0, 0), (g1, 1), (g1, 2)], mask)
180
180
 
181
- with pytest.raises(TypeError, match="cannot be converted"):
181
+ with pytest.raises(TypeError, match="cannot be cast"):
182
182
  l = [1, (g1, 0), (g1, 1)]
183
183
  fill_next_token_bitmask_par(exec, l, mask) # type: ignore
184
184
 
185
- with pytest.raises(TypeError, match="cannot be converted"):
185
+ with pytest.raises(TypeError, match="cannot be cast"):
186
186
  l = [(tokenizer(), 0)]
187
187
  fill_next_token_bitmask_par(exec, l, mask) # type: ignore
188
188
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "llguidance_py"
3
- version = "1.3.0"
3
+ version = "1.4.0"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "Super-fast Structured Outputs"
@@ -12,7 +12,7 @@ llguidance = { workspace = true }
12
12
  toktrie_hf_tokenizers = { workspace = true }
13
13
  toktrie_tiktoken = { workspace = true }
14
14
  bytemuck = "1.21.0"
15
- pyo3 = {version = "0.24.1", features = ["extension-module", "abi3-py39", "anyhow"]}
15
+ pyo3 = {version = "0.27.1", features = ["extension-module", "abi3-py39", "anyhow"]}
16
16
  serde = { version = "1.0.217", features = ["derive"] }
17
17
  serde_json = "1.0.138"
18
18
  rayon = "1.10.0"
@@ -150,7 +150,7 @@ impl LLInterpreter {
150
150
 
151
151
  fn compute_mask(&mut self, py: Python<'_>) -> PyResult<(Option<Cow<'_, [u8]>>, String)> {
152
152
  let r = py
153
- .allow_threads(|| self.inner.compute_mask())
153
+ .detach(|| self.inner.compute_mask())
154
154
  .map_err(val_error)?
155
155
  .clone();
156
156
  let mask = if r.is_stop() || r.unconditional_splice().is_some() {
@@ -58,7 +58,7 @@ impl LLExecutor {
58
58
 
59
59
  let mut mut_refs = vec![];
60
60
  for ent in interpreters.iter() {
61
- let tupl = ent.downcast::<PyTuple>()?;
61
+ let tupl = ent.cast::<PyTuple>()?;
62
62
  if tupl.len() != 2 {
63
63
  return Err(PyValueError::new_err("Expecting (LLMatcher, int) tuple"));
64
64
  }
@@ -87,7 +87,7 @@ impl LLExecutor {
87
87
 
88
88
  use rayon::prelude::*;
89
89
 
90
- py.allow_threads(|| {
90
+ py.detach(|| {
91
91
  self.pool.install(|| {
92
92
  mut_refs2.into_par_iter().for_each(|(interp, idx)| {
93
93
  interp.unsafe_compute_mask_ptr_inner(
@@ -115,7 +115,7 @@ impl LLExecutor {
115
115
 
116
116
  let mut mut_refs = vec![];
117
117
  for ent in interpreters.iter() {
118
- let tupl = ent.downcast::<PyTuple>()?;
118
+ let tupl = ent.cast::<PyTuple>()?;
119
119
  if tupl.len() != 3 {
120
120
  return Err(PyValueError::new_err(
121
121
  "Expecting (LLMatcher, int, List[int]) tuple",
@@ -151,7 +151,7 @@ impl LLExecutor {
151
151
 
152
152
  use rayon::prelude::*;
153
153
 
154
- py.allow_threads(|| {
154
+ py.detach(|| {
155
155
  self.pool.install(|| {
156
156
  mut_refs2
157
157
  .into_par_iter()
@@ -247,7 +247,7 @@ fn new_matcher(
247
247
  let logger = Logger::new(0, std::cmp::max(0, log_level) as u32);
248
248
  // constructing a grammar can take on the order of 100ms
249
249
  // for very large grammars, so we drop the GIL here
250
- let inner = py.allow_threads(|| {
250
+ let inner = py.detach(|| {
251
251
  let mut r = fact.create_parser_from_init_ext(
252
252
  GrammarInit::Serialized(grammar),
253
253
  logger,
@@ -306,7 +306,7 @@ impl LLMatcher {
306
306
  py: Python<'_>,
307
307
  ) -> String {
308
308
  match extract_grammar(grammar) {
309
- Ok((_, grammar)) => py.allow_threads(|| {
309
+ Ok((_, grammar)) => py.detach(|| {
310
310
  GrammarInit::Serialized(grammar)
311
311
  .validate(
312
312
  tokenizer.map(|t| t.factory().tok_env().clone()),
@@ -328,7 +328,7 @@ impl LLMatcher {
328
328
  py: Python<'_>,
329
329
  ) -> (bool, Vec<String>) {
330
330
  match extract_grammar(grammar) {
331
- Ok((_, grammar)) => py.allow_threads(|| {
331
+ Ok((_, grammar)) => py.detach(|| {
332
332
  GrammarInit::Serialized(grammar)
333
333
  .validate(
334
334
  tokenizer.map(|t| t.factory().tok_env().clone()),
@@ -428,7 +428,7 @@ impl LLMatcher {
428
428
  py: Python<'_>,
429
429
  ) -> PyResult<()> {
430
430
  self.validate_mask_ptr(trg_ptr, trg_bytes)?;
431
- py.allow_threads(|| self.unsafe_compute_mask_ptr_inner(trg_ptr, trg_bytes));
431
+ py.detach(|| self.unsafe_compute_mask_ptr_inner(trg_ptr, trg_bytes));
432
432
  Ok(())
433
433
  }
434
434
 
@@ -440,14 +440,14 @@ impl LLMatcher {
440
440
  py: Python<'_>,
441
441
  ) -> PyResult<()> {
442
442
  self.validate_mask_ptr(trg_ptr, trg_bytes)?;
443
- py.allow_threads(|| {
443
+ py.detach(|| {
444
444
  self.unsafe_compute_mask_ptr_inner_with_draft_tokens(trg_ptr, trg_bytes, draft_tokens)
445
445
  });
446
446
  Ok(())
447
447
  }
448
448
 
449
449
  fn compute_logit_bias(&mut self, py: Python<'_>) -> Cow<'_, [u8]> {
450
- py.allow_threads(|| {
450
+ py.detach(|| {
451
451
  let m = self.compute_mask_or_eos();
452
452
  let mut res = vec![0u8; m.len()];
453
453
  m.iter_set_entries(|i| res[i] = 200);
@@ -456,7 +456,7 @@ impl LLMatcher {
456
456
  }
457
457
 
458
458
  fn compute_bitmask(&mut self, py: Python<'_>) -> Cow<'_, [u8]> {
459
- py.allow_threads(|| {
459
+ py.detach(|| {
460
460
  let m = self.compute_mask_or_eos();
461
461
  Cow::Owned(bytemuck::cast_slice(m.as_slice()).to_vec())
462
462
  })
@@ -320,7 +320,7 @@ impl TokenizerEnv for PyTokenizer {
320
320
 
321
321
  fn tokenize_bytes(&self, utf8bytes: &[u8]) -> Vec<TokenId> {
322
322
  self.tok_trie.tokenize_with_greedy_fallback(utf8bytes, |s| {
323
- Python::with_gil(|py| {
323
+ Python::attach(|py| {
324
324
  let r = self.tokenizer_fun.call1(py, (s,)).unwrap();
325
325
  r.extract::<Vec<TokenId>>(py).unwrap()
326
326
  })
@@ -67,7 +67,7 @@ impl Serialize for SerializePyObject<'_> {
67
67
  extract!(String);
68
68
  extract!(bool);
69
69
 
70
- if let Ok(x) = self.v.downcast::<PyFloat>() {
70
+ if let Ok(x) = self.v.cast::<PyFloat>() {
71
71
  return x.value().serialize(serializer);
72
72
  }
73
73
 
@@ -78,7 +78,7 @@ impl Serialize for SerializePyObject<'_> {
78
78
  return serializer.serialize_unit();
79
79
  }
80
80
 
81
- if let Ok(x) = self.v.downcast::<PyDict>() {
81
+ if let Ok(x) = self.v.cast::<PyDict>() {
82
82
  let mut map = serializer.serialize_map(Some(x.len()))?;
83
83
  for (key, value) in x {
84
84
  if let Ok(key) = key.str() {
@@ -94,7 +94,7 @@ impl Serialize for SerializePyObject<'_> {
94
94
  return map.end();
95
95
  }
96
96
 
97
- if let Ok(x) = self.v.downcast::<PyList>() {
97
+ if let Ok(x) = self.v.cast::<PyList>() {
98
98
  let mut seq = serializer.serialize_seq(Some(x.len()))?;
99
99
  for element in x {
100
100
  seq.serialize_element(&SerializePyObject { v: element })?
@@ -102,7 +102,7 @@ impl Serialize for SerializePyObject<'_> {
102
102
  return seq.end();
103
103
  }
104
104
 
105
- if let Ok(x) = self.v.downcast::<PyTuple>() {
105
+ if let Ok(x) = self.v.cast::<PyTuple>() {
106
106
  let mut seq = serializer.serialize_seq(Some(x.len()))?;
107
107
  for element in x {
108
108
  seq.serialize_element(&SerializePyObject { v: element })?
@@ -16,6 +16,7 @@ clap = { version = "4.5.31", features = ["derive"] }
16
16
 
17
17
  [dev-dependencies]
18
18
  rstest = "0.25.0"
19
+ serde-json-fmt = "0.1.0"
19
20
 
20
21
  [[bin]]
21
22
  name = "sample_parser"