llguidance 1.2.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.4.0/.github/workflows/code-coverage.yml +126 -0
  2. {llguidance-1.2.0 → llguidance-1.4.0}/.github/workflows/rust.yml +15 -2
  3. {llguidance-1.2.0 → llguidance-1.4.0}/CHANGELOG.md +18 -1
  4. {llguidance-1.2.0 → llguidance-1.4.0}/Cargo.lock +41 -20
  5. {llguidance-1.2.0 → llguidance-1.4.0}/Cargo.toml +3 -0
  6. {llguidance-1.2.0 → llguidance-1.4.0}/PKG-INFO +4 -4
  7. {llguidance-1.2.0 → llguidance-1.4.0}/README.md +2 -2
  8. {llguidance-1.2.0 → llguidance-1.4.0}/docs/json_schema.md +22 -2
  9. {llguidance-1.2.0 → llguidance-1.4.0}/docs/syntax.md +1 -1
  10. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/jstats.sh +0 -0
  11. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/scripts/split-stats.sh +0 -0
  12. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/scripts/split_plot.py +0 -0
  13. {llguidance-1.2.0 → llguidance-1.4.0}/parser/Cargo.toml +2 -1
  14. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/api.rs +10 -0
  15. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/grammar.rs +1 -1
  16. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/parser.rs +5 -6
  17. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/perf.rs +1 -1
  18. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/regexvec.rs +1 -1
  19. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/grammar_builder.rs +3 -0
  20. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/compiler.rs +49 -25
  21. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/numeric.rs +1 -1
  22. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/logging.rs +2 -2
  23. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/matcher.rs +1 -2
  24. {llguidance-1.2.0 → llguidance-1.4.0}/pyproject.toml +2 -2
  25. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/gbnf_to_lark.py +0 -0
  26. {llguidance-1.2.0 → llguidance-1.4.0}/python/mypy.ini +1 -1
  27. {llguidance-1.2.0 → llguidance-1.4.0}/python/torch_tests/test_matcher.py +2 -2
  28. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/Cargo.toml +3 -2
  29. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/src/llinterpreter.rs +3 -3
  30. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/src/llmatcher.rs +15 -15
  31. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/src/py.rs +4 -12
  32. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/src/pyjson.rs +4 -4
  33. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/Cargo.toml +1 -0
  34. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/cli.sh +0 -0
  35. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/gtest.sh +0 -0
  36. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/lark.sh +0 -0
  37. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/run.sh +0 -0
  38. llguidance-1.4.0/sample_parser/tests/test_json_x_guidance.rs +367 -0
  39. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_ll.rs +9 -0
  40. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_raw_parser.rs +26 -0
  41. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/bump.py +0 -0
  42. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/cbindgen.sh +0 -0
  43. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/checklinks.py +0 -0
  44. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/checklinks.sh +0 -0
  45. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/ci-publish.py +0 -0
  46. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/disasm.sh +0 -0
  47. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/gbnf_to_lark.py +0 -0
  48. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/gen-testcase.py +0 -0
  49. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/git-version.sh +0 -0
  50. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/install-deps.sh +0 -0
  51. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/remote-guidance-test.sh +0 -0
  52. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/rust_size.py +0 -0
  53. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/test-guidance.sh +1 -0
  54. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/update-git.py +0 -0
  55. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/Cargo.toml +2 -1
  56. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/src/bytes.rs +1 -1
  57. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/src/svob.rs +1 -1
  58. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/src/toktree.rs +1 -1
  59. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_hf_downloader/Cargo.toml +2 -1
  60. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_hf_tokenizers/Cargo.toml +2 -1
  61. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_hf_tokenizers/src/lib.rs +79 -0
  62. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_tiktoken/Cargo.toml +2 -1
  63. llguidance-1.2.0/.github/workflows/code-coverage.yml +0 -62
  64. {llguidance-1.2.0 → llguidance-1.4.0}/.github/workflows/wheels.yml +0 -0
  65. {llguidance-1.2.0 → llguidance-1.4.0}/.gitignore +0 -0
  66. {llguidance-1.2.0 → llguidance-1.4.0}/CODE_OF_CONDUCT.md +0 -0
  67. {llguidance-1.2.0 → llguidance-1.4.0}/LICENSE +0 -0
  68. {llguidance-1.2.0 → llguidance-1.4.0}/SECURITY.md +0 -0
  69. {llguidance-1.2.0 → llguidance-1.4.0}/SUPPORT.md +0 -0
  70. {llguidance-1.2.0 → llguidance-1.4.0}/c_sample/Makefile +0 -0
  71. {llguidance-1.2.0 → llguidance-1.4.0}/c_sample/README.md +0 -0
  72. {llguidance-1.2.0 → llguidance-1.4.0}/c_sample/c_sample.cpp +0 -0
  73. {llguidance-1.2.0 → llguidance-1.4.0}/docs/de_recursing.md +0 -0
  74. {llguidance-1.2.0 → llguidance-1.4.0}/docs/fast_forward.md +0 -0
  75. {llguidance-1.2.0 → llguidance-1.4.0}/docs/mask_plot.png +0 -0
  76. {llguidance-1.2.0 → llguidance-1.4.0}/docs/optimizations.md +0 -0
  77. {llguidance-1.2.0 → llguidance-1.4.0}/docs/parametric.md +0 -0
  78. {llguidance-1.2.0 → llguidance-1.4.0}/docs/special_tokens.md +0 -0
  79. {llguidance-1.2.0 → llguidance-1.4.0}/docs/toktrie.md +0 -0
  80. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/Cargo.toml +0 -0
  81. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/expected_maskbench.json +0 -0
  82. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/src/json_stats.rs +0 -0
  83. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/src/lib.rs +0 -0
  84. {llguidance-1.2.0 → llguidance-1.4.0}/json_stats/src/stats.rs +0 -0
  85. {llguidance-1.2.0 → llguidance-1.4.0}/parser/LICENSE +0 -0
  86. {llguidance-1.2.0 → llguidance-1.4.0}/parser/README.md +0 -0
  87. {llguidance-1.2.0 → llguidance-1.4.0}/parser/build.rs +0 -0
  88. {llguidance-1.2.0 → llguidance-1.4.0}/parser/cbindgen.toml +0 -0
  89. {llguidance-1.2.0 → llguidance-1.4.0}/parser/grammars/character.json +0 -0
  90. {llguidance-1.2.0 → llguidance-1.4.0}/parser/grammars/json.json +0 -0
  91. {llguidance-1.2.0 → llguidance-1.4.0}/parser/llguidance.h +0 -0
  92. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/constraint.rs +0 -0
  93. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/from_guidance.rs +0 -0
  94. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/lexer.rs +0 -0
  95. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/lexerspec.rs +0 -0
  96. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/mod.rs +0 -0
  97. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/earley/slicer.rs +0 -0
  98. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/factory.rs +0 -0
  99. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/ffi.rs +0 -0
  100. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/ffi_par.rs +0 -0
  101. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/hashcons.rs +0 -0
  102. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/README.md +0 -0
  103. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/context_ref.rs +0 -0
  104. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/context_simple/context.rs +0 -0
  105. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/context_simple/draft.rs +0 -0
  106. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/context_simple/mod.rs +0 -0
  107. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/formats.rs +0 -0
  108. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/mod.rs +0 -0
  109. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/schema.rs +0 -0
  110. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json/shared_context.rs +0 -0
  111. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/json_validation.rs +0 -0
  112. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lark/README.md +0 -0
  113. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lark/ast.rs +0 -0
  114. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lark/common.rs +0 -0
  115. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lark/compiler.rs +0 -0
  116. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lark/lexer.rs +0 -0
  117. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lark/mod.rs +0 -0
  118. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lark/parser.rs +0 -0
  119. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/lib.rs +0 -0
  120. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/output.rs +0 -0
  121. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/panic_utils.rs +0 -0
  122. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/regex_rewrite.rs +0 -0
  123. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/stop_controller.rs +0 -0
  124. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/substring.rs +0 -0
  125. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/tokenizer_json.rs +0 -0
  126. {llguidance-1.2.0 → llguidance-1.4.0}/parser/src/tokenparser.rs +0 -0
  127. {llguidance-1.2.0 → llguidance-1.4.0}/plan.md +0 -0
  128. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/__init__.py +0 -0
  129. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/_grammar_from.py +0 -0
  130. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/_lib.pyi +0 -0
  131. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/_struct_tag.py +0 -0
  132. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/_tokenizer.py +0 -0
  133. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/_util.py +0 -0
  134. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/cli.py +0 -0
  135. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/hf.py +0 -0
  136. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/llamacpp.py +0 -0
  137. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/mlx.py +0 -0
  138. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/numpy.py +0 -0
  139. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/py.typed +0 -0
  140. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/tiktoken.py +0 -0
  141. {llguidance-1.2.0 → llguidance-1.4.0}/python/llguidance/torch.py +0 -0
  142. {llguidance-1.2.0 → llguidance-1.4.0}/python/torch_tests/__init__.py +0 -0
  143. {llguidance-1.2.0 → llguidance-1.4.0}/python/torch_tests/test_bitmask.py +0 -0
  144. {llguidance-1.2.0 → llguidance-1.4.0}/python/torch_tests/test_hf.py +0 -0
  145. {llguidance-1.2.0 → llguidance-1.4.0}/python/torch_tests/test_llamacpp.py +0 -0
  146. {llguidance-1.2.0 → llguidance-1.4.0}/python/torch_tests/test_tiktoken.py +0 -0
  147. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/src/lib.rs +0 -0
  148. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/src/llamatokenizer.rs +0 -0
  149. {llguidance-1.2.0 → llguidance-1.4.0}/python_ext/src/parserlimits.rs +0 -0
  150. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/README.md +0 -0
  151. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/blog.sample.json +0 -0
  152. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/blog.schema.json +0 -0
  153. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/blog.schema.ll.json +0 -0
  154. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/README.md +0 -0
  155. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/arithmetic.gbnf +0 -0
  156. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/c.gbnf +0 -0
  157. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/chess.gbnf +0 -0
  158. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/english.gbnf +0 -0
  159. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/japanese.gbnf +0 -0
  160. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/json.gbnf +0 -0
  161. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/json_arr.gbnf +0 -0
  162. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/list.gbnf +0 -0
  163. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/from-llama.cpp/vllm-sql.gbnf +0 -0
  164. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/lark.lark +0 -0
  165. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/rfc.lark +0 -0
  166. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/rfc.xml +0 -0
  167. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/data/ulysses.md +0 -0
  168. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/src/lib.rs +0 -0
  169. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/src/minimal.rs +0 -0
  170. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/src/sample_parser.rs +0 -0
  171. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/common_lark_utils/mod.rs +0 -0
  172. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_json_arrays.rs +0 -0
  173. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_json_enum_const.rs +0 -0
  174. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_json_objects.rs +0 -0
  175. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_json_primitives.rs +0 -0
  176. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_json_schema_combinations.rs +0 -0
  177. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_json_string_format.rs +0 -0
  178. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_lark.rs +0 -0
  179. {llguidance-1.2.0 → llguidance-1.4.0}/sample_parser/tests/test_stop.rs +0 -0
  180. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/annotate_asm.js +0 -0
  181. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/jsonschema-stats.js +0 -0
  182. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/rust-size.js +0 -0
  183. {llguidance-1.2.0 → llguidance-1.4.0}/scripts/tokenizer_test.py +0 -0
  184. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/LICENSE +0 -0
  185. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/README.md +0 -0
  186. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/src/lib.rs +0 -0
  187. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/src/recognizer.rs +0 -0
  188. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/src/rng.rs +0 -0
  189. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/src/tokenv.rs +0 -0
  190. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie/tests/test_svob.rs +0 -0
  191. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_hf_downloader/LICENSE +0 -0
  192. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_hf_downloader/src/lib.rs +0 -0
  193. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_hf_tokenizers/LICENSE +0 -0
  194. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_tiktoken/LICENSE +0 -0
  195. {llguidance-1.2.0 → llguidance-1.4.0}/toktrie_tiktoken/src/lib.rs +0 -0
@@ -0,0 +1,126 @@
1
+ name: Code Coverage
2
+ permissions:
3
+ contents: read
4
+
5
+
6
+ on:
7
+ pull_request:
8
+ push:
9
+ branches: [ "main" ]
10
+ workflow_dispatch:
11
+ inputs:
12
+ commit_id:
13
+ description: 'Branch or Commit ID (optional)'
14
+ required: false
15
+ type: string
16
+
17
+
18
+ env:
19
+ CARGO_TERM_COLOR: always
20
+ RUSTFLAGS: "-Cinstrument-coverage"
21
+ LLVM_PROFILE_FILE: "llg-%p-%m.profraw"
22
+
23
+
24
+ jobs:
25
+ code-cov-rust:
26
+ runs-on: ubuntu-latest
27
+
28
+ steps:
29
+ - name: Checkout repo at ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
30
+ uses: actions/checkout@v4
31
+ with:
32
+ ref: ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
33
+
34
+ - name: Update toolchain
35
+ run: rustup component add llvm-tools
36
+
37
+ - name: Install grcov
38
+ run: cargo install grcov
39
+
40
+ - name: Build everything
41
+ run: cargo build
42
+
43
+ - name: Run tests
44
+ run: cargo test
45
+
46
+ - name: Check environment
47
+ run: |
48
+ echo "CARGO_TERM_COLOR: $CARGO_TERM_COLOR"
49
+ echo "RUSTFLAGS: $RUSTFLAGS"
50
+ echo "LLVM_PROFILE_FILE: $LLVM_PROFILE_FILE"
51
+
52
+ - name: Generate coverage report
53
+ run: |
54
+ grcov . -s . --binary-path target/debug/ -t html --branch --ignore-not-existing -o target/debug/coverage/
55
+
56
+ - name: Check output
57
+ run: ls target/debug/coverage/
58
+
59
+ - uses: actions/upload-artifact@v4
60
+ with:
61
+ name: coverage-report-rust
62
+ path: target/debug/coverage/
63
+
64
+ code-cov-python:
65
+ runs-on: ubuntu-latest
66
+
67
+ steps:
68
+ - name: Checkout repo at ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
69
+ uses: actions/checkout@v4
70
+ with:
71
+ ref: ${{ github.event_name == 'workflow_dispatch' && inputs.commit_id || github.sha }}
72
+
73
+ - name: Setup Python
74
+ uses: actions/setup-python@v5
75
+ with:
76
+ python-version: "3.11"
77
+
78
+ - name: Check environment
79
+ run: |
80
+ echo "CARGO_TERM_COLOR: $CARGO_TERM_COLOR"
81
+ echo "RUSTFLAGS: $RUSTFLAGS"
82
+ echo "LLVM_PROFILE_FILE: $LLVM_PROFILE_FILE"
83
+
84
+ - name: Update toolchain
85
+ run: rustup component add llvm-tools
86
+
87
+ - name: Install grcov
88
+ run: cargo install grcov
89
+
90
+ - name: Clone guidance
91
+ run: |
92
+ git clone -b main https://github.com/guidance-ai/guidance
93
+
94
+ - name: Install guidance
95
+ run: |
96
+ cd guidance
97
+ pip install .[all,test]
98
+
99
+ - name: Install local llguidance
100
+ run: |
101
+ pip uninstall -y llguidance || :
102
+ pip install -v -e .
103
+
104
+ - name: Verify llguidance being used
105
+ run: pip show llguidance
106
+
107
+ - name: Run tests
108
+ run: |
109
+ cd guidance
110
+ python -m pytest tests/unit
111
+
112
+ - name: See all outputs
113
+ run: ls -R
114
+
115
+ - name: Generate coverage report
116
+ run: |
117
+ grcov . -s . --binary-path . -t html --branch --ignore-not-existing -o target/debug/coverage/
118
+
119
+ - name: Check output
120
+ run: ls target/debug/coverage/
121
+
122
+ - uses: actions/upload-artifact@v4
123
+ with:
124
+ name: coverage-report-python
125
+ path: target/debug/coverage/
126
+
@@ -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
@@ -62,7 +75,7 @@ jobs:
62
75
  - uses: actions/checkout@v4
63
76
 
64
77
  - name: Set up Rust
65
- uses: dtolnay/rust-toolchain@1.80.0
78
+ uses: dtolnay/rust-toolchain@1.87.0
66
79
  with:
67
80
  components: clippy
68
81
 
@@ -4,7 +4,24 @@ 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.1.3](https://github.com/guidance-ai/llguidance/compare/v1.1.2...v1.1.3) 2025-08-12
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
+
17
+ #### [v1.3.0](https://github.com/guidance-ai/llguidance/compare/v1.2.0...v1.3.0) 2025-10-20
18
+
19
+ - change semantics of JSON separators (now regex patterns instead of text literals) [`#246`](https://github.com/guidance-ai/llguidance/pull/246)
20
+ - fix Inconsistent handling of the EOS token in `try_consume_tokens` [`#244`](https://github.com/guidance-ai/llguidance/pull/244)
21
+ - add option for initial skip of `%ignore` lexeme [`#235`](https://github.com/guidance-ai/llguidance/pull/235)
22
+ - bump MSRV to 1.87.0 [`#243`](https://github.com/guidance-ai/llguidance/pull/243)
23
+
24
+ #### [v1.2.0](https://github.com/guidance-ai/llguidance/compare/v1.1.2...v1.2.0) 2025-08-12
8
25
 
9
26
  - support multithreaded compute bitmask for speculative decoding [`#225`](https://github.com/guidance-ai/llguidance/pull/225)
10
27
  - thank you [@ZonePG](https://github.com/ZonePG)!
@@ -1241,7 +1241,7 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
1241
1241
 
1242
1242
  [[package]]
1243
1243
  name = "llguidance"
1244
- version = "1.2.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.2.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"
@@ -2176,9 +2186,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
2176
2186
 
2177
2187
  [[package]]
2178
2188
  name = "slab"
2179
- version = "0.4.10"
2189
+ version = "0.4.11"
2180
2190
  source = "registry+https://github.com/rust-lang/crates.io-index"
2181
- checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
2191
+ checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
2182
2192
 
2183
2193
  [[package]]
2184
2194
  name = "smallvec"
@@ -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.2.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.2.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.2.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.2.0"
2536
+ version = "1.4.0"
2516
2537
  dependencies = [
2517
2538
  "anyhow",
2518
2539
  "log",
@@ -21,6 +21,9 @@ default-members = [
21
21
  ]
22
22
  resolver = "2"
23
23
 
24
+ [workspace.package]
25
+ rust-version="1.87"
26
+
24
27
  [profile.release]
25
28
  debug = 1
26
29
  strip = "debuginfo"
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: llguidance
3
- Version: 1.2.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
 
@@ -76,8 +76,8 @@ You can modify your grammar easily to allow initial or trailing whitespace.
76
76
  You can set top-level `"x-guidance"` key to control this.
77
77
  Following keys are available inside of it:
78
78
 
79
- - `item_separator`, defaults to `":"`
80
- - `key_separator`, defaults to `","`
79
+ - `item_separator`, defaults to `","` - a regex pattern for the separator between array items or object properties
80
+ - `key_separator`, defaults to `":"` - a regex pattern for the separator between object keys and values
81
81
  - `whitespace_flexible`, defaults to `true`; set to `false` to enforce compact JSON representation
82
82
  - `whitespace_pattern`, optional string, overrides `whitespace_flexible`;
83
83
  `whitespace_flexible: true` is equivalent to `whitespace_pattern: r"[\x20\x0A\x0D\x09]+"`
@@ -100,6 +100,26 @@ For example:
100
100
  }
101
101
  ```
102
102
 
103
+ The separators are treated as regex patterns, allowing for flexible formatting:
104
+
105
+ ```json
106
+ {
107
+ "x-guidance": {
108
+ "item_separator": "\\s{0,2},\\s{0,2}",
109
+ "key_separator": "\\s{0,2}:\\s{0,2}",
110
+ "whitespace_flexible": false
111
+ },
112
+ "type": "object",
113
+ "properties": {
114
+ "a": { "type": "number" },
115
+ "b": { "type": "number" }
116
+ }
117
+ }
118
+ ```
119
+
120
+ This will match JSON like `{"a":1,"b":2}`, `{"a": 1, "b": 2}`, or `{"a" : 1 , "b":2}`,
121
+ but not `{"a":1, "b":2}` (too much whitespace after comma).
122
+
103
123
  The `"x-guidance"` key is only recognized at the top level of the schema.
104
124
 
105
125
 
@@ -318,7 +318,7 @@ MULT_NUM: %regex {
318
318
 
319
319
  Certain grammar options can be set by using `%llguidnace { ... }`,
320
320
  by passing it a JSON object with the options;
321
- see `LLGuidanceOptions` in [api.rs](../parser/src/api.rs#L24).
321
+ see `LLGuidanceOptions` in [api.rs](../parser/src/api.rs#L36).
322
322
  Example: `%llguidance { "no_forcing": true }`.
323
323
  It can be specified multiple times, with the options being merged.
324
324
 
@@ -1,10 +1,11 @@
1
1
  [package]
2
2
  name = "llguidance"
3
- version = "1.2.0"
3
+ version = "1.4.0"
4
4
  edition = "2021"
5
5
  license = "MIT"
6
6
  description = "Super-fast Structured Outputs"
7
7
  repository = "https://github.com/guidance-ai/llguidance"
8
+ rust-version.workspace = true
8
9
 
9
10
  [dependencies]
10
11
  toktrie = { workspace = true }
@@ -47,6 +47,13 @@ pub struct LLGuidanceOptions {
47
47
  /// This is very unlikely what you need.
48
48
  #[serde(default)]
49
49
  pub allow_invalid_utf8: bool,
50
+
51
+ /// If set, the grammar will allow the %ignore lexeme at the start of the grammar.
52
+ /// Otherwise, it will only be allowed after the first non-ignored lexeme.
53
+ /// This option (like the other options here) will apply to the entire grammar,
54
+ /// including nested sub-grammars.
55
+ #[serde(default)]
56
+ pub allow_initial_skip: bool,
50
57
  }
51
58
 
52
59
  impl LLGuidanceOptions {
@@ -57,6 +64,9 @@ impl LLGuidanceOptions {
57
64
  if other.allow_invalid_utf8 {
58
65
  self.allow_invalid_utf8 = true;
59
66
  }
67
+ if other.allow_initial_skip {
68
+ self.allow_initial_skip = true;
69
+ }
60
70
  }
61
71
  }
62
72
 
@@ -1322,7 +1322,7 @@ impl CGrammar {
1322
1322
  outp.rhs_elements.push(CSymIdx::NULL);
1323
1323
  outp.rhs_params.push(ParamExpr::Null);
1324
1324
  }
1325
- while outp.rhs_elements.len() % (1 << RULE_SHIFT) != 0 {
1325
+ while !outp.rhs_elements.len().is_multiple_of(1 << RULE_SHIFT) {
1326
1326
  outp.rhs_elements.push(CSymIdx::NULL);
1327
1327
  outp.rhs_params.push(ParamExpr::Null);
1328
1328
  }
@@ -132,7 +132,7 @@ impl XorShift {
132
132
  }
133
133
 
134
134
  pub fn one_in(&mut self, n: u32) -> bool {
135
- self.next() % n == 0
135
+ self.next().is_multiple_of(n)
136
136
  }
137
137
 
138
138
  pub fn next_alt(&mut self) -> u32 {
@@ -1611,7 +1611,10 @@ impl ParserState {
1611
1611
 
1612
1612
  let curr = self.lexer_state();
1613
1613
 
1614
- let res = if byte.is_none() {
1614
+ let res = if let Some(b) = byte {
1615
+ self.stats.definitive_bytes += 1;
1616
+ self.lexer_mut().advance(curr.lexer_state, b, true)
1617
+ } else {
1615
1618
  let lexeme = self.lexer_mut().force_lexeme_end(curr.lexer_state);
1616
1619
  if lexeme.is_error() {
1617
1620
  debug!(
@@ -1620,10 +1623,6 @@ impl ParserState {
1620
1623
  );
1621
1624
  }
1622
1625
  lexeme
1623
- } else {
1624
- self.stats.definitive_bytes += 1;
1625
- self.lexer_mut()
1626
- .advance(curr.lexer_state, byte.unwrap(), true)
1627
1626
  };
1628
1627
 
1629
1628
  if res.is_error() {
@@ -140,7 +140,7 @@ pub fn num_with_commas(x: usize) -> String {
140
140
 
141
141
  for (i, c) in s.chars().enumerate() {
142
142
  // Insert a comma once we've passed 'offset' and every 3 digits after that.
143
- if i != 0 && i >= offset && (i - offset) % 3 == 0 {
143
+ if i != 0 && i >= offset && (i - offset).is_multiple_of(3) {
144
144
  result.push(',');
145
145
  }
146
146
  result.push(c);
@@ -674,7 +674,7 @@ impl RegexVec {
674
674
  // if lst.len() == 0 {
675
675
  // return StateID::DEAD;
676
676
  // }
677
- assert!(lst.len() % 2 == 0);
677
+ assert!(lst.len().is_multiple_of(2));
678
678
  let id = StateID::new(self.rx_sets.insert(&lst));
679
679
  if id.as_usize() >= self.state_descs.len() {
680
680
  let state_desc = self.compute_state_desc(id);
@@ -233,6 +233,9 @@ impl GrammarBuilder {
233
233
  if options.no_forcing {
234
234
  self.regex.spec.no_forcing = true;
235
235
  }
236
+ if options.allow_initial_skip {
237
+ self.regex.spec.allow_initial_skip = true;
238
+ }
236
239
 
237
240
  // add root node
238
241
  self.curr_start_idx = self.new_node("start");