"""Exact token accounting with the frozen local Qwen tokenizer.""" from __future__ import annotations from hashlib import sha256 from pathlib import Path from typing import Sequence from tokenizers import Tokenizer from .components import Candidate DEFAULT_TOKENIZER = ( Path.home() / ".lmstudio/models/lmstudio-community/" "Qwen3.6-35B-A3B-MLX-4bit/tokenizer.json" ) class QwenTokenCounter: def __init__(self, path: Path = DEFAULT_TOKENIZER): self.path = path.resolve() raw = self.path.read_bytes() self.sha256 = sha256(raw).hexdigest() self.tokenizer = Tokenizer.from_file(str(self.path)) def count(self, text: str) -> int: return len(self.tokenizer.encode(text, add_special_tokens=False).ids) def pack_ranked( self, candidates: Sequence[Candidate], budget: int, ) -> tuple[str, tuple[Candidate, ...], int]: blocks: list[str] = [] included: list[Candidate] = [] used = 0 for rank, candidate in enumerate(candidates, start=1): block = ( f"\n--- Rank {rank}: {candidate.path} " f"(lines {candidate.line_start}-{candidate.line_end}; {candidate.source}) ---\n" f"{candidate.text}\n" ) tokens = self.count(block) if used + tokens > budget: continue blocks.append(block) included.append(candidate) used += tokens return "".join(blocks), tuple(included), used