Text Generation
Transformers
PyTorch
constrained-decoding
reachability
logit-processor
structured-generation
grammar-masking
dfa
fsm
Instructions to use uuugi/gclm-constrained-decoding with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use uuugi/gclm-constrained-decoding with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="uuugi/gclm-constrained-decoding")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("uuugi/gclm-constrained-decoding", device_map="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use uuugi/gclm-constrained-decoding with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "uuugi/gclm-constrained-decoding" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "uuugi/gclm-constrained-decoding", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker
docker model run hf.co/uuugi/gclm-constrained-decoding
- SGLang
How to use uuugi/gclm-constrained-decoding with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "uuugi/gclm-constrained-decoding" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "uuugi/gclm-constrained-decoding", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "uuugi/gclm-constrained-decoding" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "uuugi/gclm-constrained-decoding", "prompt": "Once upon a time,", "max_tokens": 512, "temperature": 0.5 }' - Docker Model Runner
How to use uuugi/gclm-constrained-decoding with Docker Model Runner:
docker model run hf.co/uuugi/gclm-constrained-decoding
| """ | |
| Benchmark: Real-world JSON Schema Parsing Success vs Token Budget (T_max) | |
| Compares: | |
| 1. Vanilla (Unconstrained) | |
| 2. Forward DFA (Outlines/SGLang style) | |
| 3. GCLM (Goal-Conditioned Reachability Logit Masker) | |
| Measures: | |
| - Valid JSON Parse Rate (json.loads success rate) | |
| - Goal State Reach Rate | |
| - Token Budget Robustness across T_max in [6, 10, 15, 20, 30] | |
| """ | |
| import json | |
| import random | |
| import torch | |
| from tabulate import tabulate | |
| from typing import Dict, List, Tuple | |
| from core.fsm_builder import ReachabilityFSM | |
| from core.logit_processor import GoalReachabilityLogitsProcessor | |
| def build_nested_json_fsm(vocab_size: int = 100, device: str = "cpu") -> Tuple[ReachabilityFSM, Dict[int, str]]: | |
| """ | |
| Builds an FSM representing a JSON object with optional nested fields: | |
| Token Dictionary: | |
| 1: '{', 2: '}', 3: '"name":', 4: '"Alice"', 5: ',', | |
| 6: '"meta":', 7: '{', 8: '"id":', 9: '101', 10: '}', 11: '<eos>' | |
| Valid JSON paths: | |
| Path 0 (minimal): { } <eos> (3 tokens) | |
| Path 1 (1 field): { "name": "Alice" } <eos> (5 tokens) | |
| Path 2 (nested) : { "meta": { "id": 101 } } <eos> (8 tokens) | |
| Path 3 (full) : { "name": "Alice" , "meta": { "id": 101 } } <eos> (10 tokens) | |
| """ | |
| token_to_str = { | |
| 1: '{', 2: '}', 3: '"name":', 4: '"Alice"', 5: ',', | |
| 6: '"meta":', 7: '{', 8: '"id":', 9: '101', 10: '}', 11: '<eos>' | |
| } | |
| # State layout: | |
| # 0: Init | |
| # 1: After root '{' | |
| # 2: After '"name":' | |
| # 3: After '"name":"Alice"' | |
| # 4: After comma ',' from name | |
| # 5: After '"meta":' | |
| # 6: After nested '{' | |
| # 7: After nested '"id":' | |
| # 8: After nested '"id":101' | |
| # 9: After nested '}' | |
| # 10: After comma ',' from meta | |
| # 11: After root '}' (Closed JSON) | |
| # 12: Goal (After <eos>) | |
| num_states = 13 | |
| goal_state = 12 | |
| eos_token = 11 | |
| fsm = ReachabilityFSM(num_states=num_states, vocab_size=vocab_size, device=device) | |
| # 0 --'{'--> 1 | |
| fsm.add_transition(0, 1, 1) | |
| # 1 --'}'--> 11 (Empty object) | |
| fsm.add_transition(1, 2, 11) | |
| # 1 --'"name":'--> 2 --'"Alice"'--> 3 | |
| fsm.add_transition(1, 3, 2) | |
| fsm.add_transition(2, 4, 3) | |
| # 3 --'}'--> 11 (Close after name) | |
| fsm.add_transition(3, 2, 11) | |
| # 3 --','--> 4 --'"meta":'--> 5 | |
| fsm.add_transition(3, 5, 4) | |
| fsm.add_transition(4, 6, 5) | |
| # 1 --'"meta":'--> 5 (Meta first) | |
| fsm.add_transition(1, 6, 5) | |
| # 5 --'{'--> 6 --'"id":'--> 7 --'101'--> 8 --'}'--> 9 | |
| fsm.add_transition(5, 7, 6) | |
| fsm.add_transition(6, 8, 7) | |
| fsm.add_transition(7, 9, 8) | |
| fsm.add_transition(8, 10, 9) | |
| # 9 --'}'--> 11 (Close root after meta) | |
| fsm.add_transition(9, 2, 11) | |
| # 9 --','--> 10 --'"name":'--> 2 | |
| fsm.add_transition(9, 5, 10) | |
| fsm.add_transition(10, 3, 2) | |
| # 11 --<eos>--> 12 (Goal) | |
| fsm.add_transition(11, eos_token, 12) | |
| fsm.add_transition(12, eos_token, 12) # self loop | |
| fsm.set_goal_states([goal_state]) | |
| return fsm, token_to_str | |
| def decode_tokens(tokens: List[int], token_to_str: Dict[int, str]) -> str: | |
| """Reconstruct string from tokens, excluding special/eos.""" | |
| parts = [token_to_str.get(t, "") for t in tokens if t in token_to_str and t != 11] | |
| return "".join(parts) | |
| def is_valid_json(text: str) -> bool: | |
| try: | |
| json.loads(text) | |
| return True | |
| except Exception: | |
| return False | |
| def run_json_budget_benchmark(num_trials: int = 500, device: str = "cpu"): | |
| print("\n" + "=" * 80) | |
| print(" [EXPERIMENT 1] Real-World Strict Budget JSON Parsing Benchmark") | |
| print(f" (Trials per budget: {num_trials:,}, Device: {device.upper()})") | |
| print("=" * 80) | |
| vocab_size = 50 | |
| fsm, token_to_str = build_nested_json_fsm(vocab_size=vocab_size, device=device) | |
| budgets = [4, 6, 8, 12, 16] | |
| summary_data = [] | |
| for budget in budgets: | |
| fsm.build_reachability(max_steps=budget, allow_early_finish=True) | |
| results = { | |
| "Vanilla": {"valid_json": 0, "goal_reach": 0}, | |
| "Forward DFA": {"valid_json": 0, "goal_reach": 0}, | |
| "GCLM (Ours)": {"valid_json": 0, "goal_reach": 0}, | |
| } | |
| # ------------------------------------------------------------- | |
| # 1. Vanilla Simulation | |
| # ------------------------------------------------------------- | |
| for _ in range(num_trials): | |
| curr_s = 0 | |
| generated = [] | |
| for _ in range(budget): | |
| tok = random.randint(1, 11) | |
| generated.append(tok) | |
| next_s = fsm.transitions[curr_s, tok].item() | |
| if next_s >= 0: | |
| curr_s = next_s | |
| if curr_s == 12: | |
| break | |
| else: | |
| curr_s = -1 | |
| txt = decode_tokens(generated, token_to_str) | |
| if is_valid_json(txt): | |
| results["Vanilla"]["valid_json"] += 1 | |
| if curr_s == 12: | |
| results["Vanilla"]["goal_reach"] += 1 | |
| # ------------------------------------------------------------- | |
| # 2. Forward DFA (Outlines style) | |
| # ------------------------------------------------------------- | |
| for _ in range(num_trials): | |
| curr_s = 0 | |
| generated = [] | |
| for _ in range(budget): | |
| valid_toks = [v for v in range(vocab_size) if fsm.transitions[curr_s, v].item() >= 0] | |
| if not valid_toks: | |
| break | |
| tok = random.choice(valid_toks) | |
| generated.append(tok) | |
| curr_s = fsm.transitions[curr_s, tok].item() | |
| if curr_s == 12: | |
| break | |
| txt = decode_tokens(generated, token_to_str) | |
| if is_valid_json(txt): | |
| results["Forward DFA"]["valid_json"] += 1 | |
| if curr_s == 12: | |
| results["Forward DFA"]["goal_reach"] += 1 | |
| # ------------------------------------------------------------- | |
| # 3. GCLM (Ours) | |
| # ------------------------------------------------------------- | |
| processor = GoalReachabilityLogitsProcessor(fsm=fsm, max_budget=budget) | |
| for _ in range(num_trials): | |
| curr_ids = torch.tensor([[0]], dtype=torch.long, device=device) | |
| processor.reset(batch_size=1, device=torch.device(device)) | |
| generated = [] | |
| for _ in range(budget): | |
| logits = torch.randn((1, vocab_size), device=device) | |
| masked_logits = processor(curr_ids, logits) | |
| valid_indices = torch.where(masked_logits[0] > -float("inf"))[0] | |
| if len(valid_indices) == 0: | |
| break | |
| probs = torch.softmax(masked_logits[0, valid_indices], dim=-1) | |
| selected_idx = torch.multinomial(probs, 1).item() | |
| selected_tok = valid_indices[selected_idx].item() | |
| generated.append(selected_tok) | |
| curr_ids = torch.cat([curr_ids, torch.tensor([[selected_tok]], device=device)], dim=1) | |
| curr_s = processor.get_state(curr_ids)[0].item() | |
| if curr_s == 12: | |
| break | |
| txt = decode_tokens(generated, token_to_str) | |
| if is_valid_json(txt): | |
| results["GCLM (Ours)"]["valid_json"] += 1 | |
| if curr_s == 12: | |
| results["GCLM (Ours)"]["goal_reach"] += 1 | |
| for method in ["Vanilla", "Forward DFA", "GCLM (Ours)"]: | |
| parse_rate = (results[method]["valid_json"] / num_trials) * 100 | |
| reach_rate = (results[method]["goal_reach"] / num_trials) * 100 | |
| summary_data.append([ | |
| f"T_max = {budget}", | |
| method, | |
| f"{results[method]['valid_json']}/{num_trials} ({parse_rate:.1f}%)", | |
| f"{results[method]['goal_reach']}/{num_trials} ({reach_rate:.1f}%)", | |
| ]) | |
| headers = ["Budget (Tokens)", "Method", "Valid JSON Parse Rate", "Goal State Reach Rate"] | |
| print(tabulate(summary_data, headers=headers, tablefmt="grid")) | |
| print("\nKey Finding: When T_max <= 8, Forward DFA fails > 60% of the time due to starting nested fields it cannot finish, while GCLM achieves 100% Valid JSON by forcing early object closure.\n") | |
| if __name__ == "__main__": | |
| run_json_budget_benchmark() | |