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
File size: 5,753 Bytes
44810a8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | from typing import Iterable, List, Optional, Set, Union
import torch
class ReachabilityFSM:
"""
Finite State Machine with backward BFS reachability bitmap for O(1) logit masking.
Attributes:
num_states (int): Total number of states in the FSM.
vocab_size (int): Size of the token vocabulary.
transitions (torch.Tensor): Tensor of shape [num_states, vocab_size] storing next state ID (-1 if invalid).
goal_states (Set[int]): Set of target/accepting state IDs.
reachability_table (torch.Tensor): Boolean tensor of shape [max_steps + 1, num_states].
device (torch.device): Device on which tensors reside.
"""
def __init__(
self,
num_states: int,
vocab_size: int,
goal_states: Optional[Iterable[int]] = None,
initial_state: int = 0,
device: Union[str, torch.device] = "cpu",
):
self.num_states = num_states
self.vocab_size = vocab_size
self.initial_state = initial_state
self.device = torch.device(device)
# Transitions: [num_states, vocab_size] initialized with -1 (no transition)
self.transitions = torch.full(
(num_states, vocab_size),
-1,
dtype=torch.long,
device=self.device,
)
self.goal_states: Set[int] = set(goal_states) if goal_states is not None else set()
self.is_goal_state = torch.zeros(num_states, dtype=torch.bool, device=self.device)
for g in self.goal_states:
self.is_goal_state[g] = True
self.reachability_table: Optional[torch.Tensor] = None
self.max_steps: Optional[int] = None
def add_transition(self, from_state: int, token_id: int, to_state: int) -> None:
"""Add a transition for a single token ID."""
if not (0 <= from_state < self.num_states):
raise ValueError(f"from_state {from_state} out of bounds [0, {self.num_states})")
if not (0 <= to_state < self.num_states):
raise ValueError(f"to_state {to_state} out of bounds [0, {self.num_states})")
if not (0 <= token_id < self.vocab_size):
raise ValueError(f"token_id {token_id} out of bounds [0, {self.vocab_size})")
self.transitions[from_state, token_id] = to_state
def add_transitions(self, from_state: int, token_ids: Iterable[int], to_state: int) -> None:
"""Add transitions for multiple token IDs simultaneously."""
for tid in token_ids:
self.add_transition(from_state, tid, to_state)
def set_goal_states(self, goal_states: Iterable[int]) -> None:
"""Set target/accepting states."""
self.goal_states = set()
self.is_goal_state.zero_()
for g in goal_states:
if not (0 <= g < self.num_states):
raise ValueError(f"goal_state {g} out of bounds [0, {self.num_states})")
self.goal_states.add(g)
self.is_goal_state[g] = True
def build_reachability(self, max_steps: int, allow_early_finish: bool = True) -> torch.Tensor:
"""
Compute backward BFS reachability table R[t, s] using vectorized PyTorch operations.
R[t, s] == True iff state s can reach at least one goal state in:
- <= t steps (if allow_early_finish=True)
- exactly t steps (if allow_early_finish=False)
Args:
max_steps (int): Maximum token budget T_max.
allow_early_finish (bool): If True, reaching goal in <= t steps is considered reachable.
Returns:
torch.Tensor: Boolean tensor of shape [max_steps + 1, num_states].
"""
if not self.goal_states:
raise ValueError("No goal states specified. Call set_goal_states() first.")
self.max_steps = max_steps
table = torch.zeros((max_steps + 1, self.num_states), dtype=torch.bool, device=self.device)
# Base case t = 0: only goal states are reachable in 0 steps
for g in self.goal_states:
table[0, g] = True
valid_trans = self.transitions >= 0
clamped_trans = torch.clamp(self.transitions, min=0)
for t in range(1, max_steps + 1):
prev_reachable = table[t - 1] # [num_states]
# For each transition (s, v) -> next_s, check if next_s is reachable in t-1 steps
# trans_reachable: [num_states, vocab_size]
trans_reachable = prev_reachable[clamped_trans] & valid_trans
# A state s can transition to a reachable state if any token v leads to a reachable next_s
can_reach = trans_reachable.any(dim=1) # [num_states]
if allow_early_finish:
table[t] = table[t - 1] | can_reach
else:
table[t] = can_reach
self.reachability_table = table
return self.reachability_table
def to(self, device: Union[str, torch.device]) -> "ReachabilityFSM":
"""Move FSM tensors to specified device."""
self.device = torch.device(device)
self.transitions = self.transitions.to(self.device)
self.is_goal_state = self.is_goal_state.to(self.device)
if self.reachability_table is not None:
self.reachability_table = self.reachability_table.to(self.device)
return self
def memory_footprint_bytes(self) -> int:
"""Calculate total memory usage of FSM tensors in bytes."""
trans_bytes = self.transitions.numel() * self.transitions.element_size()
reach_bytes = 0
if self.reachability_table is not None:
reach_bytes = self.reachability_table.numel() * self.reachability_table.element_size()
return trans_bytes + reach_bytes
|