Repository navigation
Count the LiteRT-LM runtime-template prompt as native prefill reads it - #1873
Merged
Merged
Conversation
engine.chatTemplate() on native LiteRT-LM renders the bundle template since #1854, so a Gemma 4 prompt starts with the text `<bos>`. The renderer counted it with tokenize(prompt, addSpecial: false), which the LiteRT-LM tokenizer reads as three plain tokens, while native prefill strips that text and adds one start token: tokenCount was 2 too high. A runtime-template prompt is now counted by the backend through an internal BackendRuntimePromptTokenization probe. LiteRtLmService reuses the start-token stripping raw generate() uses (#1864) and tokenizes the rest with the start token added once. Other prompts, backends and Web keep the plain count. Fixes #1872 Refs #1845
leehack
marked this pull request as ready for review
November 9, 2026 21:47
Contributor
|
Chat app preview removed for |
This was referenced Nov 9, 2026
Merged
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.
Summary
engine.chatTemplate(...).tokenCountnow equals the runtime's prefilled input for Gemma 4. Since Report the chat template native LiteRT-LM renders #1854 the shown prompt is a render of the bundle template and starts with the text<bos>; the renderer counted it withtokenize(prompt, addSpecial: false), which the LiteRT-LM tokenizer reads as three plain tokens, while native prefill strips that text and adds one start token (2 too many).BackendRuntimePromptTokenizationprobe (registered likeBackendGenerationLimitReporting, so the exportedLiteRtLmBackendtype does not expose it).LiteRtLmService.tokenizeRuntimePromptreuses the start-token stripping rawgenerate()uses since Send the raw prompt unchanged from native LiteRT-LM generate (#1853) #1864 (_withoutLeadingStartToken) and tokenizes the rest with the start token added once.create()rendering and parsing are unchanged.Fixes #1872
Refs #1845
Production-readiness scope
chatTemplate().tokenCount(andChatSessiontrimming, which uses it) is exact for native Gemma 4.litertlm, thinking on/off, with or without a system message.llamadart.chat_template.parsingpresent). Qwen3.5 and Qwen3 stay exact; llama.cpp/GGUF, Web,customTemplateand the parsing-template fallback keep the plaintokenize(prompt, addSpecial: false)count.<__media__>as text, as before.Completeness checklist
chatTemplateDartdoc and both changelogs; no doc claimed exactness.)PR type guidance
<bos>as[236820, 46757, 236813]) and a local-only real-model e2e; native LiteRT-LM only.Before / after (
gemma-4-E2B-it.litertlm181938105e0e, CPU)main99b8406 tokenCount / native inputc5f39b41)c5f39b41)Native input is
getPerformanceContext().promptEvalTokensaftercreate()with the same messages.Test Plan
dart run tool/prepare_workspace.dartdart format --output=none --set-exit-if-changed .dart analyzedart run tool/testing/check_platform_boundaries.dartdart test -p vm -j 1 --exclude-tags local-onlyontest/unit/core/engine test/unit/backends/litert_lm test/unit/backends/native test/integration/backends/litert_lm test/unit/tooling: all pass except 6windows_registry_qualification_test.dartcases needingpwsh, absent on this Mac (unrelated). Full suite in CI.dart test -p chromeonchat_template_renderer_test.dartandengine_test.dart: pass.coverage-lib: full VM suite with coverage on b64aa59, LCOV line coverage 93.65% (threshold 70%). Only the 6pwsh-dependentwindows_registry_qualification_test.dartcases failed (nopwshon this Mac).test/e2e/backends/litert_lm_chat_template_token_count_e2e_test.dartwithLITERT_LM_MODELset to each of Gemma 4 E2B, Qwen3.5-0.8B int8 and Qwen3-0.6B: 4/4 each (Gemma 0/4 onmain);litert-lm-chat-features-smokeon Gemma 4 CPU: pass.Mutations (each reverted; every one fails the named tests)
runtimePromptLiteRtLmBackendsends a plain tokenize requestLiteRtLmBackendregisters no tokenizerNativeAutoBackendnever delegates / counts with special tokensMatrix Evidence
create()paths unchanged).181938105e0e/ CPUReview Notes
High-risk regression review
181938105e0e, Qwen3.5-0.8B int8, Qwen3-0.6Bc5f39b41(table above)Independent audit
Exact head
b64aa59a1f7c4b4234e3816cfb527c5b7b00cc68againstmain99b8406e3: PASS, 0 blocking, 0 PR-caused P1, 0 unresolved threads. Gemma 4chatTemplate().tokenCountequals runtime prefill (22/22, tools 58/58; main was +2); Qwen3.5, Qwen3-0.6Bc5f39b41, GGUF Qwen3-0.6B andcustomTemplatecounts unchanged. Probe stays internal (not exported). 12/12 mutants killed. Readiness evidence v2: local run exits 2. Non-blocking P3s tracked on #1861.