Repository navigation
Bytes encoder: read BOS and bytes, not EOS - #96
Merged
Merged
Conversation
EOS is the bytes decoder's target (where a word ends); the bidirectional encoder already knows each word's length, so it reads one position fewer per word. Training (WeLTModel.encode_words), vLLM inference (WeLTGenerator), and the FLOPs benchmark alike. Saves 6-9% of step FLOPs with byte models split evenly (e.g. 25.6 -> 23.4 TFLOPs per step for the 25M latent transformer matched in parameters), under 1% with decoder-heavy ones. Checkpoints trained before this change read EOS: retrain (or evaluate with the earlier code). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Xm62qoeaTunFSU5GYCQ1f
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Each word is stored as BOS, bytes, EOS. EOS is the bytes decoder's target (where the word ends), but the bytes encoder is bidirectional and already knows each word's length from the mask, so reading EOS tells it nothing. It now reads BOS and the bytes only:
WeLTModel.encode_words(training) masks each word's last position (EOS) out of the encoder's inputWeLTGenerator._encode_words(vLLM inference) drops it likewisebenchmarks/flops.pycounts one position fewer per encoded wordStep FLOPs saved (measured on the ClimbMix / FineWeb-2 mixes): 8.8% for the 25M latent transformer with byte models matched in parameters (25.6 → 23.4 TFLOPs), 5.9–6.7% matched in FLOPs, under 1% with decoder-heavy byte models (where the encoder is 1–2 layers).
Compatibility: checkpoints trained before this change read EOS; retrain them, or evaluate them with the earlier code.
Tests:
test_bytes_encoder_ignores_eos(a word's embedding does not depend on its EOS; fails before this change), andtest_vllm_matches_megatronkeeps training and inference in agreement. Full suite: 137 passed, 1 skipped.🤖 Generated with Claude Code
https://claude.ai/code/session_015Xm62qoeaTunFSU5GYCQ1f
Note
Medium Risk
Changes word-embedding computation and breaks weight compatibility with checkpoints trained before this change; training and inference paths were updated together.
Overview
The bytes encoder no longer consumes each word’s EOS token—only BOS and the byte sequence—because the bidirectional encoder already knows word length from the attention mask, so EOS added no information.
Training (
WeLTModel.encode_words) masks out the final EOS position before the bytes encoder runs. vLLM inference (WeLTGenerator._encode_words) drops EOS from prompt token ids the same way. FLOP benchmarks count one fewer token per encoded word (n - 1).Docs in the README describe this behavior. A new test asserts that changing EOS does not change word embeddings. Older checkpoints that were trained with EOS in the encoder input are incompatible unless you retrain or run the previous code.
Reviewed by Cursor Bugbot for commit 5b2e7be. Bugbot is set up for automated code reviews on this repo. Configure here.