feat: support offsetless BYO tokenizers - #142
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 17822f8. Configure here.
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR adds offsetless BYO-tokenizer support through shared runtime helpers and changes attribution and sampling metadata across many production renderers. Its decoder-based fallbacks and broad cross-renderer behavior make the change larger than a small isolated compatibility tweak. Notes:
No code changes detected at You can add or adjust custom eligibility rules. Learn more. |
Pull Request is not mergeable
Pull Request is not mergeable
The merge-base changed after approval.
aeba360 to
b2e13b1
Compare
b2e13b1 to
ad0326c
Compare

Stacked on #70; review and merge after that PR.
Why
Removing Transformers from the base install should allow a genuinely minimal BYO tokenizer. Character offsets are only needed for precise body/scaffold attribution, not for producing correct token IDs.
What changed
TokenizerandOffsetTokenizercapabilities.is_content=[]instead of rejecting them.sampled_mask=[]for PrimeQwen when its assistant sampled/scaffold split cannot be recovered without offsets.Verification
3813 passed, 179 skipped, 1 xfailed153 passed774 passed, 19 skippedNote
Support offsetless BYO tokenizers and move
transformersto optional extrasTokenizer,OffsetTokenizer, andChatTemplateTokenizerprotocols in base.py; all renderer constructors now accept any conforming tokenizer instead oftransformers.PreTrainedTokenizer.attribute_text_segmentsno longer raises when a tokenizer lacks offset support. It returns token IDs withhas_content_attribution=False; renderers then emit emptyis_contentmasks via_content_mask_or_empty.transformers>=4.50.0andpillow>=12.2.0into optional extras (renderers[transformers],renderers[multimodal]) in pyproject.toml. Calls that need transformers now raise clearImportErrormessages via_require_transformers.RendererPool,create_renderer_pool, and_maybe_offload;generate()in client.py now accepts onlyRenderer.RendererPoolandcreate_renderer_poolare removed from base.py and init.py — any out-of-tree imports of these names will fail. Passing aRendererPooltorenderers.client.generatenow raises a type error. Base installs no longer includetransformers; consumers relying on auto-resolve orload_tokenizermust install thetransformersextra.Macroscope summarized ad0326c.
Note
Medium Risk
Wide renderer surface change: token IDs stay aligned but loss-mask consumers lose
is_content/sampled_maskon offsetless tokenizers, and decode-inferred message attribution on Hy3/Laguna may mis-label edge cases.Overview
Hand-coded renderers no longer require a fast tokenizer with
return_offsets_mapping. The baseTokenizerprotocol coversencode/decode/ special-token IDs;OffsetTokenizeris the optional add-on for character-offset attribution.When offsets are missing, renderers still run a single joined BPE pass (same
token_idsas before) but exposeis_content=[]via_content_mask_or_empty, instead of raising at construction or returning misleading body/scaffold masks.attribute_text_segmentsnow returnsAttributedTextSegmentswithhas_content_attributionso callers know when bools are exact vs placeholders.PrimeQwen3Rendereralso clearssampled_maskwhen assistant sampled/scaffold splits cannot be recovered without offsets.Hy3 and Laguna 2.1 add
_infer_offsets_from_decode(and conservative fallbacks) so joined system/tool headers still get sensiblemessage_indiceswithout splitting the BPE pass; that path does not re-enableis_content.Docs (README, pyproject) and exports (
OffsetTokenizer) reflect the softer BYO contract. Newtests/test_offsetless_tokenizers.pymatrix-tests render + bridge parity across the renderer set.Reviewed by Cursor Bugbot for commit ad0326c. Bugbot is set up for automated code reviews on this repo. Configure here.