Skip to content

Document that BpeOptions.ByteLevel requires a PreTokenizer - #7716

Merged
rosebyte merged 4 commits into
dotnet:mainfrom
lunosia:patch-1
Oct 13, 2026
Merged

rosebyte merged 4 commits into
dotnet:mainfrom
lunosia:patch-1

Conversation

@lunosia

@lunosia lunosia commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Documents the requirement reported in #7715.

BpeOptions.ByteLevel only documented the byte <-> unicode mapping (for example Space -> 'Ġ').
It did not state that a pre-tokenizer is required. Without one, byte-level encoding maps the space
character to 'Ġ' but does not keep the whitespace attached to the following token, so spaces and
newlines are dropped during encoding and cannot be recovered by decoding - with no exception and
no warning.

This adds a <remarks> block to the ByteLevel property that:

  • states that PreTokenizer must be set when ByteLevel is true;
  • describes the failure mode (silent whitespace loss, not recoverable on decode);
  • points at RegexPreTokenizer built from the GPT-2 pattern as a configuration that round-trips losslessly.

Measured against HuggingFace tokenizers as the reference, a properly configured pre-tokenizer makes
encoding match token-for-token and decoding exact, while without one the lossless round-trip rate drops
to 1/5 on a small mixed-language sample.

This is a documentation-only change: no code and no public API surface change.

The documentation for `BpeOptions.ByteLevel` only described the byte <-> unicode mapping
(for example `Space -> 'Ġ'`) and did not mention that a pre-tokenizer is required.

Without a pre-tokenizer, byte-level encoding maps the space character to `'Ġ'` but does not
keep the whitespace attached to the following token, so spaces and newlines are dropped
during encoding and cannot be recovered by decoding.

This adds a `<remarks>` block stating the requirement and points at `RegexPreTokenizer`
with the GPT-2 pattern as the configuration that keeps the round trip lossless.

Relates to dotnet#7715.
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Pull requests submitted by community contributors label Sep 14, 2026
@codecov

codecov Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.95%. Comparing base (f1c6972) to head (bc05887).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7716      +/-   ##
==========================================
- Coverage   69.95%   69.95%   -0.01%     
==========================================
  Files        1419     1419              
  Lines      272603   272603              
  Branches    27562    27562              
==========================================
- Hits       190707   190706       -1     
  Misses      73701    73701              
- Partials     8195     8196       +1     
Flag Coverage Δ
Debug 69.95% <ø> (-0.01%) ⬇️
production 64.14% <ø> (-0.01%) ⬇️
test 89.69% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/Microsoft.ML.Tokenizers/Model/BpeOptions.cs 68.42% <ø> (ø)

... and 11 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

/// <see langword="true"/>, <see cref="PreTokenizer"/> must be set as well.
/// On its own, byte-level encoding maps the space character to 'Ġ' but does not keep the whitespace attached
/// to the following token, so spaces and newlines are dropped during encoding and cannot be recovered by decoding.
/// Configuring a byte-level pre-tokenizer, for example <see cref="RegexPreTokenizer"/> built from the GPT-2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we limit this claim to preserving whitespace during pre-tokenisation? Normalisation and missing vocabulary entries can still change or discard input, so the GPT-2 regex alone cannot guarantee a lossless round trip.

/// Additionally, some ASCII characters will be transformed to different characters (e.g Space character will be transformed to 'Ġ' character).
/// </summary>
/// <remarks>
/// Byte-level encoding is normally paired with a byte-level pre-tokenizer. When this property is set to

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we describe the default pre-tokeniser’s behaviour rather than make this a requirement of ByteLevel?

Updated documentation for ByteLevel property to clarify behavior with pre-tokenizers.
@lunosia

lunosia commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review — I've reworded the remarks accordingly:

  • Dropped the "lossless round trip" claim; the statement is now limited to whitespace during pre-tokenization.
  • Replaced the "PreTokenizer must be set" requirement with a description of the default pre-tokenizer (CreateWordOrNonWord), whose pattern doesn't cover whitespace characters.

Please take another look when you have a moment.

@rosebyte
rosebyte merged commit eb62d29 into dotnet:main Oct 13, 2026
27 checks passed
svick added a commit that referenced this pull request Oct 15, 2026
Adjusts the documentation added in #7716 by moving the whitespace
guidance from `BpeOptions.ByteLevel` to `BpeOptions.PreTokenizer`.

Whitespace removal is not related to the `ByteLevel` setting. When no
pre-tokenizer is specified, BPE uses
`PreTokenizer.CreateWordOrNonWord()`, which discards whitespace with
either value of `ByteLevel`. Byte-level mapping operates on the retained
segments; it does not configure pre-tokenization or preserve characters
excluded by the pre-tokenizer.

The remark also clarifies that each segment is encoded independently, so
BPE merges cannot cross segment boundaries. To preserve whitespace
during pre-tokenization, callers should select rules matching the model,
such as the GPT-2 pattern where appropriate. No exception or runtime
behavior change is needed.

Documentation-only change.

Closes #7715

/cc @lunosia

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: c5e01d75-322d-4ff0-96a2-51fe6fca4882
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution Pull requests submitted by community contributors

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants