Repository navigation
Conversation
6eab0fc to
80de760
Compare
|
Tested this branch against various leading-whitespace cases — plain encode/decode round-trips correctly now for 0/1/2/3+ leading spaces, tabs, and newlines. Nice fix, and the re-encode check is a clean way to disambiguate the synthetic prefix. One gap: FIM/infilling mode (tokenize(prefix, suffix=...)) still has a leading-space bug, separate from the one this PR fixes. Repro: Looks like CodeLlamaTokenizer.tokenize() prepends its own " " to the prefix for FIM formatting (separate from the Metaspace synthetic prefix), and _decode's re-encode check doesn't account for that since it only checks against plain self.encode(). Given real code almost always has leading indentation, this seems worth covering too — happy to help dig into it if useful. |
|
@ArthurZucker @itazap, can you take a look at this? There's a separate leading-space bug in FIM infilling (raised here), which I confirmed is independent of this PR since raw I'd prefer to keep this PR to the plain-decode fix and open a separate issue for FIM since that prepend looks load-bearing and riskier to touch, but I can look into handling both here if that's the direction you want. How would you like this handled? |
|
Sounds good — happy to open a separate issue for the FIM bug with the repro, so it's tracked. I can also take a shot at fixing it if that's welcome, since I've already been digging through the tokenize()/_decode interaction. |
|
Opened #47602 to track the FIM/infilling leading-space bug separately, as discussed. |
itazap
left a comment
There was a problem hiding this comment.
we sorry we should not have to overwrite _decode here, the normalizer should be properly constructed in the _tokenzier above
| def eot_token(self): | ||
| return self._eot_token | ||
|
|
||
| def _decode( |
There was a problem hiding this comment.
sorry we should not have to overwrite _decode here, the normalizer should be properly constructed in the _tokenzier above
There was a problem hiding this comment.
Thanks for the direction! Looking into the architecture more deeply, I think I have found the core fix: swapping the plain path's Metaspace pre-tokenizer for the Prepend("▁") + Replace(" ","▁") normalizer (with pre_tokenizer = None), and delete the _decode override.
Initial results support this hypothesis (leading whitespace round-trips on real CodeLlama-7b-hf, matching the shipped tokenizer.json). I will verify it completely and update the body to reflect the new approach when done!
There was a problem hiding this comment.
Done, I removed _decode override and the pipeline is now built from the Prepend("▁") + Replace(" ", "▁") normalizer with pre_tokenizer = None, matching the shipped tokenizer.json. I also updated the PR body to reflect this change of approach.
Two things I would flag for you to take a look at since they may not be perfectly clear/obvious:
- The pipeline has to be assigned after
super().__init__(), otherwise the added-token trie is built against thePrependnormalizer andnormalized=Truespecial tokens get split mid-text (<s>). - One narrow behavior change:
"<s>hello"decoded withskip_special_tokens=Falsenow shows a space after the special token ("<s> hello"). The shippedtokenizer.jsondecodes identically so it is reference-faithful, and it does not affect the normal BOS path, but flagging in case you would rather special-case it.
There was a problem hiding this comment.
Hey, I did some digging and code llama was based on llama2 so pre meatspace era. Additionally, CodeLlama-7b-hf is now in tests as opposed to the internal checkpoint which didnt have matching params. the init now initialized the same tokenizer as in tokenizer.json on this original checkpoint!
I made a push to support this, let me know what you think and if it covers all the edge cases you had. Thanks!
There was a problem hiding this comment.
This makes sense and everything looks great! I verified the push against the edge cases I had (especially leading whitespace down to a single space, the <s> handling, and also the FIM prefix path) and they all round-trip exactly. Nothing left on my end. Thanks for taking this the rest of the way!
c14ab06 to
d91aef8
Compare
d91aef8 to
d01567f
Compare
|
[For maintainers] Suggested jobs to run (before merge) run-slow: code_llama |
CI recapDashboard: View test results in Grafana |
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
…gface#47488) * Build CodeLlama pipeline from the reference SentencePiece normalizer * match tokenizer init to real checkpoint's tokenizer.json, code llama is llama2 --------- Co-authored-by: itazap <[email protected]>
…#47488)" (#47861) This reverts commit 1b20eb1. #47488 replaced the `Metaspace` pre-tokenizer with a `Prepend("▁") + Replace(" ", "▁")` normalizer. That changes tokenization in two ways that break existing checkpoints. 1. Added-token contents are themselves normalized when the added-vocabulary matcher (daachorse) is rebuilt, so `<s>` is stored as `▁<s>` and stops matching `<s>` in the text. Any checkpoint shipping its specials with `normalized=True` loses them: tok.tokenize("Hey how are<s>you?<unk> <unk>") ['▁Hey', '▁how', '▁are', '<', 's', '>', 'you', '?', '<', 'unk', '>', '▁<unk>'] 2. The prepend runs on every chunk produced by the added-token split, so a metaspace is inserted after every special token. `[INST] How are you doing?<s>[/INST]` moves `[` from 29961 to 518, i.e. every multi-turn Llama-2 chat prompt tokenizes differently. #47488 wrote this into its own expected outputs rather than treating it as a bug. The leading-whitespace round-trip reported in #47487 is real, but it is decode-only and does not need a pipeline change.
…#47488)" (#47861) This reverts commit 1b20eb1. #47488 replaced the `Metaspace` pre-tokenizer with a `Prepend("▁") + Replace(" ", "▁")` normalizer. That changes tokenization in two ways that break existing checkpoints. 1. Added-token contents are themselves normalized when the added-vocabulary matcher (daachorse) is rebuilt, so `<s>` is stored as `▁<s>` and stops matching `<s>` in the text. Any checkpoint shipping its specials with `normalized=True` loses them: tok.tokenize("Hey how are<s>you?<unk> <unk>") ['▁Hey', '▁how', '▁are', '<', 's', '>', 'you', '?', '<', 'unk', '>', '▁<unk>'] 2. The prepend runs on every chunk produced by the added-token split, so a metaspace is inserted after every special token. `[INST] How are you doing?<s>[/INST]` moves `[` from 29961 to 518, i.e. every multi-turn Llama-2 chat prompt tokenizes differently. #47488 wrote this into its own expected outputs rather than treating it as a bug. The leading-whitespace round-trip reported in #47487 is real, but it is decode-only and does not need a pipeline change.
What does this PR do?
Fixes #47487
From the tagged issue,
CodeLlamaTokenizerbuilds its plain-path pipeline with aMetaspace(prepend_scheme="first")pre-tokenizer. Metaspace runsreplace(" ", "▁")before its guarded prepend, so a real leading space becomes▁and the prepend is then skipped, which fuses a user-provided leading space into the synthetic prefix at encode time." hello"and"hello"encode to the same ids, so the leading space is already gone before decode runs, and the ids also diverge from the pipeline the checkpoint ships intokenizer.json.The earlier version of this PR recovered the space in
_decode, but the loss happens at encode, so this PR fixes it directly in the pipeline instead. It builds the pipeline from thePrepend("▁") + Replace(" ", "▁")normalizer with no pre-tokenizer, which is what the checkpoint ships intokenizer.json. Leading whitespace now round-trips exactly, including a single leading space, tabs, newlines, and real code with nested indentation.The same fusion also affected the most common round-trip,
encode(text)followed bydecode(ids, skip_special_tokens=True). The BOS carried the synthetic prefix, so decoding dropped it and left a spurious leading space on ordinary text ("def foo():"decoded to" def foo():"). This is fixed too.This PR also updates
test_spm_edge_casesto the reference tokenization (<s>is followed by▁[), un-skipstest_simple_encode_decodeandtest_no_differences_showcasewhich the fix restores, points the two<s>assertions atcodellama/CodeLlama-7b-hfsince thehf-internal-testing/llama-code-tokenizerfixture marks<s>asnormalized=True, and corrects the whitespace note incode_llama.md. The existingLlamaIntegrationTesttokenizer tests still pass.Code Agent Policy
Before submitting
Pull Request checks?
to it if that's the case.
Who can review?
@ArthurZucker and @itazap