Repository navigation
[sgl-router] Allow load-only routing without a tokenizer - #41611
Conversation
0144054 to
9f96e38
Compare
|
|
||
| /// Cache matching and length-based buckets require a real tokenizer. | ||
| /// Load-only routing can use the request-size estimate for accounting. | ||
| pub fn requires_tokenizer(&self) -> bool { |
There was a problem hiding this comment.
nit: requires_tokenizer() mirrors Policy::needs_request_tokens() by hand. It matches today, but if a future token-dependent term or filter is added and this list isn't updated, PrefixCachePolicy-style terms silently return flat scores instead of failing at startup. Consider validating against the built policy (needs_request_tokens()) instead, or add a test that asserts the two agree for every PolicyKind/term/filter.
There was a problem hiding this comment.
Good point. I removed requires_tokenizer().
| pub model_id: String, | ||
|
|
||
| /// Local tokenizer.json or HuggingFace repo id. Defaults to --model-id; honors HF_TOKEN / HF_HOME. | ||
| /// "none" skips it for load-only policies; cache-aware and length-bucket routing require one. |
There was a problem hiding this comment.
nit: Consider a dedicated --no-tokenizer flag instead of the magic "none" value, which could collide with a real path and doesn't match None/NONE.
There was a problem hiding this comment.
Agreed. I replaced the "none" value with a dedicated --no-tokenizer flag (conflicts_with = "tokenizer_path"). Internally ModelConfig.tokenizer_path is now Option<String>, so there's no sentinel value left.
3a8dc45 to
f979c83
Compare
`--tokenizer-path none` skips tokenizer loading for load-only policies on both routing paths. Cache-aware routing, prefix-cache terms or filters, and --bucket-config still require a tokenizer and fail validation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A dedicated flag cannot collide with a real path; ModelConfig now carries `tokenizer_path: Option<String>`. Startup now rejects --no-tokenizer by asking the built routing whether it reads request tokens, instead of mirroring each policy in the config. Reorg policies gain `needs_request_tokens`, so the check covers both routing paths and length-bounded reorg buckets. --bucket-config is still rejected during config validation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
f979c83 to
46e169a
Compare
The reorg handler passed a literal `true`, so `Bucket::needs_request_tokens` only ever ran at startup to vet `--no-tokenizer`; at request time every reorg request tokenized regardless of what its buckets select on. Startup and dispatch could therefore disagree: the guard admits a load-only bucket set without a tokenizer, and the handler then asks for tokens anyway. Pass the resolver's own answer, which is what the old comment described. Behaviour is unchanged wherever tokens are read -- a bounded bucket, a prefix-matching group policy, or any worker-bound forwarding, which already forces tokenization through `can_forward_input_ids`. What it removes is a `serde_json::from_slice` of every body on the load-only path, whose result `build_outgoing_body` discards outside PD mode (`needs_parse` is false, so it returns `body.clone()`). Cover the predicate's length arms directly, since they now gate request-time tokenization: the existing tests only vary the group policy, leaving `limits.min`, `limits.max` and `max_context_tokens` untested. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Resolves ten conflicts left by #41610, #41611 and #41612 landing on main while this branch still carried their pre-squash commits. Two needed judgement rather than a side: - `readyz`: main gained the peer-bootstrap seed gate (#40699) while this branch rewrote the pool check for version groups. The hunks overlap, and taking either side whole drops the other, so the resolution keeps this branch's group-aware `pool_ready` *and* main's `&& ctx.kv_bootstrap_admit_ready()`. - `chat/forward.rs`: this branch carries #41612's pre-fix copy; main has the post-fix one. The version-group feature does not touch this file at all, so it takes main's version, keeping the `cancelled` outcome #41612 records for a decode dispatch that prefill's failure abandoned. - `pd_bootstrap_injection/reliability.rs` (add/add): keeps this branch's `..Default::default()` spec and main's two #41612 assertions. The rest are the mechanical `..Default::default()` churn this branch introduced meeting fields main spells out, plus a `readiness_rejects_portless_prefill` body git aligned against its own merged copy; resolved so each test and helper is defined once. Verified on the merge result: 1017 lib + 129 component + 157 proxy tests pass, clippy -D warnings and rustfmt clean. The two fixes a careless resolution would have reverted are covered by tests that still pass -- the five `pd_bootstrap_injection::reliability` cases and the four seed-gate `readyz` cases. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Load-only routing does not need a tokenizer, but the router always downloads and loads one at startup.
Changes
--no-tokenizerskips tokenizer loading. It cannot be combined with--tokenizer-path.--no-tokenizerwhen the built routing reads request tokens (cache-aware routing, prefix-cache fuse terms or filters, length-bounded reorg buckets)./v1/tokenizeand/v1/detokenizereturn 400tokenizer disabledfor the served model instead of 404.CI States
Latest PR Test (Base): ✅ Run #36826694042
Latest PR Test (Extra): ❌ Run #36826693833
Latest PR Test (AMD ROCm 10): ➖ No AMD PR run found for this commit.