Repository navigation
feat(models): add the vllm_native dialect (RFC #25's seventh) - #261
Merged
Merged
Conversation
vLLM serves no text /generate; its native surface is the extension fields /v1/completions accepts beyond OpenAI's. vllm_native sends them as first-class wire over async_http_json: - input scoring through prompt_logprobs, its own channel, checked against prompt_token_ids and usage.prompt_tokens (no echo split); - token ids on input and sampled tokens (return_token_ids); - structured_output lowered to structured_outputs (json / json_object); - a per-request seed (measured: equal seeds give equal samples). Every active leaf is consumed with wire evidence, a documented no-op, or refused before I/O: max_tokens 0, suffix, strict=False and every option outside min_p / repetition_penalty / stop_token_ids, since vLLM drops an unknown field silently. The diff meets #256's extension-cost contract: one new dialect module, one DIALECT_BINDERS entry and the DIALECT_SPECS row moved from reserved to active. Tests that used vllm_native as the reserved example now hide its binder instead. Closes #256 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eads Sampled top-k maps are keyed by decoded text, so two tokens that decode alike (byte-fallback pieces) collapse into one key. The `len == k + 1` test then missed a sampled token listed beside the top-k and reported it as an alternative. A map that is short of k, or that holds another value for the sampled token, is now refused. Input positions must list k or k + 1 entries. At k + 1 the scored token is the extra one even when a rank tie gives it a top-k rank. Drop the unreachable vllm_native branch in _not_implemented_message, and trim the dialect's comments and guide text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ethan-scitix
marked this pull request as ready for review
October 28, 2026 03:22
Merged
7 tasks done
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.
Type
Summary
Implements
vllm_native, the seventh dialect in RFC #25's symbol space and the last one still reserved.vLLM serves no text
/generate. Its native surface is the extension fields its/v1/completionsaccepts beyond OpenAI's, sovllm_nativeposts there over rawasync_http_json. The OpenAI SDK would move these fields intoextra_bodyand type the reply without them. They are sent as first-class wire:prompt_logprobsis its own channel: noecho, and no split at a usage boundary. Completeness is checked against bothprompt_token_idsandusage.prompt_tokens, as RFC [RFC]: A capability-based Model IR — decouple model access from the OpenAI protocol #25 §8.2 asks. A short or missing channel is refused.return_token_idsfillsTokenLogprob.token_idon input and sampled tokens, andTopKEntry.token_idon the input top-k. It also identifies the scored token among its top-k: a position listskentries, ork + 1with the scored token beside them, and any other count is refused.structured_outputis lowered tostructured_outputs(jsonschema orjson_object) and lifted toResponse.structured_output.k, or one holding another value for the sampled token, is refused instead of misread. A collision that still leaveskentries is undetectable (the map carries no rank).SUPPORTED. Measured: equal seeds gave equal samples at temperature 1, and a different seed gave a different one.Unsupported. vLLM's reasoning and tool parsers act on chat requests only, and this endpoint takes a raw prompt.Every active request leaf is decided before I/O:
seed,n), scoring,structured_output.format/.schemascheduling.streamprompt_logprobsstructured_output.namestructured_outputstakes no namestructured_output.stricttrue;falserefused (the grammar is always strict)max_tokens: 0,suffixmin_p,repetition_penalty,stop_token_idsExtension-cost contract (#256). The diff stays inside it. Shared code changes only in
dialect_registry.py: one import, oneDIALECT_BINDERSentry, and thevllm_nativeDIALECT_SPECSrow moved fromRESERVEDto active with its decisions. There is no IR, registry-schema,reconcile(), connection-family or existing-dialect change.session.pyandresolution.pybind the new id with no edits.Not changed: no default dialect moves. A vLLM
genmodel keepsopenai_completionsunless it setsdialect: vllm_native. This is additive: not in any identity, and noRESULT_SCHEMA_VERSIONbump.Related Issues
Closes #256. Refs #25 (§3.1, §3.2, §3.3, §8.2) and #250, whose
sglang_nativeparity run this follows.Test Plan
Automated
ruff check,ruff format --check, barety check(tests included): cleanpytest tests/unit tests/integration --cov --cov-fail-under=95 -n 8: 10174 passed, 1 skipped, total coverage 97.17%.vllm_native.py98%,dialect_registry.py97% (at df5c641)pytest tests/unit tests/integration -n 8: 10179 passed, 1 skipped. The 5 new top-k tests fail on df5c641scripts/check_preflight.py: all pass.sync_package_stubs.py --check: cleantests/unit/core/models/dialects/test_vllm_native.py(86 tests). Its reply fixtures are vLLM 0.26.0 shapes recorded live, e.g. a scored token ranked 522 listed beside the top 2test_dialect_registry,test_validation) now hidevllm_native's binder, so "reserved ⇒DialectNotImplemented" stays covered with no reserved id left.test_reconcile's unavailable-dialect case usessglang_legacyManual
Live endpoint (§3.3). 1× H100, image
vllm:0.26.0(/version→0.26.0,system_fingerprintvllm-0.26.0-0c752b4e),Qwen/Qwen2.5-0.5B,--max-logprobs 100 --seed 0 --no-enable-prefix-caching, behind a logging proxy. Requested model idQwen/Qwen2.5-0.5B; reportedQwen/Qwen2.5-0.5B(Response.response_model).Parity against the OpenAI-compatible route on the input-scoring tasks,
concurrency_limit: 1, on one server:openai_completions, thenvllm_native, thenopenai_completionsagain as a control.openai_completionsvllm_nativearc_easy_kshot_pplhellaswag_kshot_ppl(acc_norm / acc)mmlu_kshot_clpgsm8k_kshot_base_genZero fails anywhere. Per call, over 395 calls: 160,545 input-token logprobs compared, max |diff| = 0, with input token text equal at every position. That includes the unscored first token, whose text
vllm_nativerecovers as the prompt prefix the decoded tokens leave. Underopenai_completionsthe input's last token and the generated token both come from the echo. The only record difference istextson the PPL calls: echo returns prompt + generation, whilevllm_nativereturns the generation only. No PPL/CLP task reads it.Wire, redacted. 395 vs 395 requests, all
/v1/completions, all 200. Native body shapes:{model, prompt, stream: false, temperature, max_tokens: 1, return_token_ids: true, prompt_logprobs: 0}→ choice hasprompt_logprobs(809 positions =usage.prompt_tokens809) andprompt_token_ids.{…, return_token_ids: true, logprobs: 100}.{…, max_tokens: 256, stop: [...]}.The OpenAI route sent
echo: true, logprobs: 0, stream: truefor the same calls.Supported cases, live: input top-3 with token ids; CJK input (first token
中国的recovered);n=2with per-choice token ids; seed repeat (identical text);json_schema→{"name": "jazznix"}; optionsmin_p+repetition_penalty.Refused, live:
max_tokens: 0,suffix(plan:fimunavailable), unknown optionguided_json,strict: false.--max-logprobs; context overflow (read bycontext_overflow_message).structured output is not valid JSONon a reply cut atmax_tokens.Prefix caching on (vLLM's default), same probes. Input scoring stays complete; a repeated 363-token prompt kept 363/363 positions. That needs no
--no-enable-prefix-cachingremedy on 0.26.0, unlike the V1 behaviour RFC [RFC]: A capability-based Model IR — decouple model access from the OpenAI protocol #25 §8.2 guarded against. The length check stays as a safeguard.Raw wire probe (no sieval) before the implementation:
prompt_logprobswithreturn_token_idsreturnsprompt_token_ids.prompt_logprobsandmax_tokens: 0→ 400max_tokens must be at least 1.suffix→ 400suffix is not currently supported.stream: true→ noprompt_logprobsin the stream.Checklist
Required (all PRs)
type(scope): description)AI-Generated Code - <model> (<provider>)in module docstringcore/🤖 Generated with Claude Code