BertTokenizer merges words separated only by `\n`, `\t` or `\r`
Maintainer thường phản hồi trong vòng 2 ngày
@rosebyte đang làm issue này rồi.
Từ ngày 23/9/2026.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 85/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- csharp
- Lĩnh vực
- machine-learning
Hướng nghiên cứu
Bắt đầu trong src/Microsoft.ML.Tokenizers/Normalizer/BertNormalizer.cs và kiểm tra cách các ký tự UnicodeCategory.Control được xử lý trước bước tiền token hóa theo khoảng trắng. Tái hiện vấn đề bằng các ví dụ được cung cấp one\nline, one\tline và note\nbook; hoàn thành khi các ký tự này được xử lý như khoảng trắng và đầu ra khớp với cách token hóa mong đợi.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description
BertTokenizer deletes \n, \t and \r rather than treating them as whitespace, so the words on either side are joined into one word before tokenization. What that yields depends on the vocabulary: one\nline becomes one ##line, while note\nbook becomes the single token notebook. Either way it changes the tokens, and therefore the embeddings, for any text with a line break or tab that has no adjacent space, which is common in real documents.
Hugging Face's BERT basic tokenizer treats these three characters as whitespace: _is_control explicitly excludes them, and _is_whitespace includes them. That is not specific to HF — it comes from the original BERT release, whose tokenization.py returns False from _is_control for \t, \n and \r, commented "These are technically control characters but we count them as whitespace characters". BertTokenizer's own remarks state that its implementation "is based on the original Bert implementation in the Hugging Face Transformers library".
If this is deliberate — a decision to treat Control uniformly rather than follow the _is_whitespace exception — please share the reasoning, and I'll close this.
Versions
- Microsoft.ML.Tokenizers 2.0.0 and 3.0.0-preview.26457.2, with identical results
- .NET 10.0.12, macOS arm64
- Vocabulary:
sentence-transformers/all-MiniLM-L6-v2vocab.txt(uncased BERT, 30,522 tokens) - Reference: Hugging Face
tokenizers0.21.1,BertWordPieceTokenizer(vocab, lowercase=True) - Cosine under "Impact":
onnxruntime1.22.0, mean pooling over the token ids
Reproduce
using Microsoft.ML.Tokenizers;
var vocab = File.ReadAllLines("vocab.txt");
var tokenizer = BertTokenizer.Create("vocab.txt", new BertOptions());
foreach (var input in new[] { "one\nline", "one\tline", "one \nline", "note\nbook" })
{
var tokens = tokenizer.EncodeToIds(input).Select(id => vocab[id]);
Console.WriteLine($"{input.Replace("\n", "\\n").Replace("\t", "\\t")} -> {string.Join(' ', tokens)}");
}
Expected vs actual
| input | actual | expected (HF tokenizers) |
|---|---|---|
one\nline |
[CLS] one ##line [SEP] |
[CLS] one line [SEP] |
one\tline |
[CLS] one ##line [SEP] |
[CLS] one line [SEP] |
one \nline |
[CLS] one line [SEP] |
[CLS] one line [SEP] |
note\nbook |
[CLS] notebook [SEP] |
[CLS] note book [SEP] |
No BertOptions setting preserves BERT basic-tokenization semantics while correcting this behavior. Setting ApplyBasicTokenization = false bypasses the faulty normalizer, but also disables the rest of BERT basic tokenization.
Cause
BertNormalizer.Normalize (src/Microsoft.ML.Tokenizers/Normalizer/BertNormalizer.cs) skips every character whose category is UnicodeCategory.Control:
if (category == UnicodeCategory.Control)
{
i += inc;
continue;
}
\t, \n and \r are all Control, so they are removed before the pre-tokenizer splits on whitespace. A fix is to emit a space for those three characters before that check, as HF does:
if (c is '\t' or '\n' or '\r')
{
AddChar(ref buffer, ref index, ' ');
continue;
}
Impact
Embedding all-MiniLM-L6-v2 through ONNX Runtime with mean pooling, the input " line one\n\tline two " scores cosine 0.936 against the same text tokenized by HF tokenizers. Callers can work around it by replacing \t, \n and \r with spaces before encoding.
- Ngôn ngữ chính
- C#
- Star
- 9.4k
- Fork
- 2k
- Merge trung bình
- 4 ngày 14 giờ
- Pull request đã merge (30 ngày)
- 33
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của dotnet/machinelearning
-
LlamaTokenizer encodes some runs of repeated characters differently from SentencePieceCó thể đã có người làm @Laurianti đã nhận 13 ngày trước. Đang mởuntriaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
dotnet/machinelearning#7751 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Comment in example code not matching docstring for TimeSeriesCatalog.DetectSeasonality MethodĐang mởarea-TimeSeries documentation untriaged
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
dotnet/machinelearning#7205 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
area-ONNX documentation Priority:3
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
dotnet/machinelearning#5894 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Add a .vsconfig fileĐang mởarea-Infrastructure Priority:2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
dotnet/machinelearning#3260 · 2 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 2 ngày
-
area-Core enhancement Priority:3
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
dotnet/machinelearning#2669 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
Tất cả issue của dotnet/machinelearning
Issue tương tự
-
area-signalr
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
dotnet/aspnetcore#69842 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 64/100
Maintainer thường phản hồi trong vòng 2 ngày
-
bug needs-triage
Độ khó 2/5 Dưới một giờ Mức phù hợp với người mới 78/100
microsoft/microsoft-ui-reactor#1373 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Client customer-reported KeyVault needs-team-attention question Service Attention
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
Azure/azure-sdk-for-net#63861 · 3 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày