Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build_and_release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- {os: ubuntu-24.04-arm, arch: aarch64, build: 'cp*-manylinux*'}
- {os: windows-latest, arch: AMD64, build: 'cp*'}
- {os: macos-14, arch: arm64, build: 'cp*'}
- {os: macos-13, arch: x86_64, build: 'cp*',}
- {os: macos-15-intel, arch: x86_64, build: 'cp*',}

steps:
- uses: astral-sh/setup-uv@v4
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/tmate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-14, macos-13]
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-14, macos-15-intel]
python: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
exclude:
- os: macos-13
- os: macos-15-intel
python: '3.13'
# The reason for the exclusion is that pytorch distribution
# can't be found by pip on macos-13 with python 3.13.

# can't be found by pip on macos-15-intel with python 3.13.
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
7 changes: 3 additions & 4 deletions .github/workflows/unit_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-14, macos-13]
os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, macos-14, macos-15-intel]
python: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
exclude:
- os: macos-13
- os: macos-15-intel
python: '3.13'
# The reason for the exclusion is that pytorch distribution
# can't be found by pip on macos-13 with python 3.13.

# can't be found by pip on macos-15-intel with python 3.13.
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
46 changes: 33 additions & 13 deletions tests/python/test_structural_tag_converter.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import sys
import time
from typing import Any, Dict, List, Tuple
from typing import Any, Dict, List, Optional, Tuple, Union

import pytest
from transformers import AutoTokenizer

import xgrammar as xgr
from xgrammar.structural_tag import StructuralTag
from xgrammar.testing import _is_grammar_accept_string

PROFILER_ON = True
tokenizer_id = "meta-llama/Llama-3.1-8B-Instruct"


class Profiler:
def __init__(self, tokenizer_id: str):
Expand All @@ -22,8 +20,13 @@ def __init__(self, tokenizer_id: str):
self.tokenizer_info, max_threads=16, cache_enabled=False
)

def profile_stag(self, structural_tag_format: Dict[str, Any], instance: str):
structural_tag = {"type": "structural_tag", "format": structural_tag_format}
def profile_stag(
self, structural_tag_format: Union[Dict[str, Any], StructuralTag], instance: str
):
if isinstance(structural_tag_format, StructuralTag):
structural_tag = structural_tag_format
else:
structural_tag = {"type": "structural_tag", "format": structural_tag_format}
time_begin = time.monotonic_ns()
compiled_grammar = self.compiler.compile_structural_tag(structural_tag)
time_end = time.monotonic_ns()
Expand All @@ -45,8 +48,23 @@ def profile_stag(self, structural_tag_format: Dict[str, Any], instance: str):
print(f"Time to generate mask: {duration / 1000} us, Character: '{char}'")


if PROFILER_ON:
profiler = Profiler(tokenizer_id)
profiler: Optional[Profiler] = None
PROFILER_ON = True
tokenizer_id = "meta-llama/Llama-3.1-8B-Instruct"


@pytest.fixture(autouse=True)
def disable_profiler(request):
global PROFILER_ON
global profiler
markexpr = getattr(request.config.option, "markexpr", "") or request.config.getoption(
"markexpr", ""
)
hf_token_not_provided = "not hf_token_required" in (markexpr or "")
if hf_token_not_provided:
PROFILER_ON = False
else:
profiler = Profiler(tokenizer_id)


def check_stag_with_grammar(structural_tag_format: Dict[str, Any], expected_grammar_ebnf: str):
Expand All @@ -56,13 +74,16 @@ def check_stag_with_grammar(structural_tag_format: Dict[str, Any], expected_gram


def check_stag_with_instance(
structural_tag_format: Dict[str, Any],
structural_tag_format: Union[Dict[str, Any], StructuralTag],
instance: str,
is_accepted: bool = True,
debug_print: bool = False,
):
structural_tag = {"type": "structural_tag", "format": structural_tag_format}
stag_grammar = xgr.Grammar.from_structural_tag(structural_tag)
if isinstance(structural_tag_format, StructuralTag):
stag_grammar = xgr.Grammar.from_structural_tag(structural_tag_format)
else:
structural_tag = {"type": "structural_tag", "format": structural_tag_format}
stag_grammar = xgr.Grammar.from_structural_tag(structural_tag)
accepted = _is_grammar_accept_string(stag_grammar, instance, debug_print=debug_print)
assert accepted == is_accepted
if PROFILER_ON:
Expand Down Expand Up @@ -1955,8 +1976,7 @@ def test_from_structural_tag_with_structural_tag_instance(
stag_format: xgr.structural_tag.Format, instance: str, is_accepted: bool
):
stag = xgr.StructuralTag(format=stag_format)
grammar = xgr.Grammar.from_structural_tag(stag)
assert _is_grammar_accept_string(grammar, instance) == is_accepted
check_stag_with_instance(stag, instance, is_accepted)


if __name__ == "__main__":
Expand Down
Loading