Repository navigation
Conversation
The model card tokenizes "<Instruct>: {i}\n<Query>: {q}\n<Document>: {d}" as one
string, so the space after "<Document>:" joins the document's first word (" License").
The adapter tokenized the text up to "<Document>: " and the document apart, so almost
every row carried a lone space token and the document's first word without its space:
token ids the model never saw in the reference prompt.
End the prefix at "<Document>:" and tokenize the document with the space in front of it.
The pre-tokenizer always splits after that colon, so prefix + tail are the card's ids and
prefix reuse still shares one prefix per query. The separator is not billed as document
text where it stays a token of its own.
A Qwen3 row's tail now starts with the space after "<Document>:", so the test's documents are one character shorter to keep their tails on the graph bucket edges.
This branch has not been deployed
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.
Problem
Qwen3-Reranker's model card builds each pair as one string,
<Instruct>: {instruction}\n<Query>: {query}\n<Document>: {doc}, tokenizes it once, and wraps it in the chat template's prefix and suffix tokens. The adapter tokenized the text up to<Document>:(with its trailing space) and the document separately. Qwen2's pre-tokenizer then emits a lone space token and the document's first word without its space (Ġ,License), where the card has oneĠLicensetoken. The model scores token ids it never sees in the reference prompt.On a 3,840-row workload (48 contract questions, 8 instructions, 10 candidates each), 3,800 rows on main differ from the card's ids. The 40 that match are documents that start with a digit, where the space stays a token of its own either way.
Fix
End the prefix at
<Document>:and tokenize the document as" " + document. The pre-tokenizer always splits after that colon, so prefix + tail equal the card's single tokenization, and prefix reuse still shares one prefix per (instruction, query). The separator is not billed as document text where it stays a token of its own. Where it merges into the first word (ĠLicense), the merged token is one document token, the same count as before; a document whose first character joins the space differently ((gbecomes(,g) can bill one token more or less than before.The mxbai input format is unchanged.
Evidence
One H100 on Modal, the server and its client in one container (the reranker serving study's recipe: released
sie-serverv0.10.1defaultimage, pinned by digest, with main and this branch overlaid), plain HTTP, one request in flight. Reference: the Transformers code from the Qwen3-Reranker-4B model card at revision22e683669bc0f0bd69640a1354a6d0aebcfeede5, float32. Noise floor: the largest change of any candidate-pair gap between float32 and bfloat16 in the card's own code on the same rows, 0.47 log-odds.fastprofile againstdefaultFeeding main's token rows to the card's own code gives zero flips above noise against main's scores, so the numerics are fine and the whole difference is the tokenization.
Root-cause record, harness and per-request scores: superlinked/sie-web#859,
apps/site/public/reference/legal-supersession/root-cause/(ls_app.py,ref_card.py,check_rows.py,analyze.py,summary.json).Compatibility
Scores for
input_format: qwen3models (Qwen3-Reranker 0.6B and 4B, and decision or routing jobs served through this adapter) move toward the reference, by a median 0.13 log-odds on the workload above. Recordings made before this change will not reproduce bit-for-bit. Billed content tokens are unchanged for documents that start with a letter or digit. No API or wire change.Validation
pytest tests/adapters/test_qwen2_flash_cross_encoder.py tests/adapters/test_qwen2_flash_cross_encoder_prefix.py tests/adapters/test_qwen2_flash_cross_encoder_fused.pyon CPU: 49 passed, 6 skipped (CUDA).test_factory_integration.py,test_runtime_options.py,tests/config/test_native_zerank_catalog.py,test_all_models.pyand the three above): 171 passed, 7 skipped.ruff checkandruff format --checkon the changed files: clean.ty checkon them reports the same 6 diagnostics as main (flash_attnimports and two existing ones), none new.test_qwen3_rows_are_the_model_cards_token_idsbuilds an offline word-level tokenizer over Qwen2's own pre-tokenizer and checks that_build_input_idsand the batchedscore_pairspath both produce the card's single tokenization, for documents starting with a letter, a digit, a bracket, a quote, a newline and a space. On main it fails for 4 of the 6.Summary by CodeRabbit