Repository navigation
feat: add opt-in vLLM sampling validation - #683
Conversation
|
Hi @irar2 Would you also mind having a review on this? |
mayabar
left a comment
There was a problem hiding this comment.
The simulator has so far parsed only the fields that affect response generation.
In strict mode, we should validate the entire request against the OpenAI API specification, along with the vLLM-specific extension fields. This means verifying that all required fields are present and that every supplied field has a valid value and is consistent with related parameters.
The implementation in this PR validates only part of the request. For example:
nhas an upper limit configured byVLLM_MAX_N_SEQUENCES, but this limit is not currently validated.- When
max_tokensis omitted, vLLM applies a default value. However,min_tokensis not validated against that effective maximum.
Rather than incrementally adding validation for individual fields, I suggest using an existing library that validates OpenAI-compatible requests, if one is available. Alternatively, we could generate or obtain a JSON Schema from vLLM’s OpenAPI specification:
curl http://localhost:8000/openapi.json > openapi.jsonThen we can apply standard JSON Schema validation for the common request structure and add explicit validation for constraints that depend on runtime configuration or relationships between fields, such as VLLM_MAX_N_SEQUENCES and the effective max_tokens value.
|
Thanks, I agree that strict mode should use the full request schema. I reworked this to compile the two completion request schemas from a target vLLM OpenAPI 3.1 snapshot, using the JSON Schema library already in the repository. I also added the The communication, endpoint, common, and API tests, targeted |
mayabar
left a comment
There was a problem hiding this comment.
Thanks for the rework, and for moving to the full request schema. There are several issues in the proposed implementation that need to be resolved before this can land.
1. Strict mode should not depend on a user-supplied schema file
Requiring --strict-openapi puts the burden on the user to export and carry a snapshot, and it makes strict mode depend on an artifact the simulator cannot control. The important problem: a schema exported from a newer vLLM can be inconsistent with the validations implemented in the code here, and then strict mode silently mixes two different vLLM versions - a new field passes the schema and then hits a check written for an older release, or vice versa.
Please check a snapshot into the repository and load it from there (go:embed), so the schema version and the hand-written checks are versioned together and --strict works with no extra user setup.
2. The schema covers only a small part of the validation
Schema validation gives structure and types; most of what vLLM rejects is not expressible there. n is one example (both n < 1 and n > VLLM_MAX_N_SEQUENCES, whose default is 16384 in vllm/envs.py), but there are many more, for example:
stream_optionsset whilestreamis false or absenttop_logprobsset whilelogprobsis false
...
This needs a systematic pass over vLLM's request models and SamplingParams to cover all request fields, rather than a partial list. Please also keep the exact vLLM message text where you claim parity - for instance the n upper-bound message here drops vLLM's second sentence about setting VLLM_MAX_N_SEQUENCES.
3. Validation logic is spread across too many places
Right now a single request is validated in four different locations, with rules duplicated between them:
pkg/communication/strict_schema.go: schema validation,n > VLLM_MAX_N_SEQUENCES, andmin_tokensagainst the schema'smax_tokensdefaultpkg/communication/strict_validation.go: all sampling ranges, plusmin_tokensagainst the explicitmax_tokenspkg/endpoint/request.go(validateTokenizedRequest):min_tokensagain, against the remaining context windowpkg/api/request.go:strictMinTokens/strictDefaultMaxTokensfields andSetStrictTokenLimits/StrictTokenLimits, only to carry values from the first location to the third (please remove new fields from the request)
So min_tokens versus max_tokens is implemented three times with three different notions of the maximum. On top of that, pkg/endpoint/helpers.go (validateRequest) already validates n < 1 and max_tokens < 1, so those conditions now exist twice with two different messages depending on the flag. Please consolidate: one place per rule, one message per rule.
4. Align with the new engine structure
The project has been restructured recently and now has an explicit engine concept (pkg/engine, with pkg/engine/vllm supplying the vLLM-specific flags, config validation, and transport). Strict request validation should fit into that seam rather than sit beside it.
Suggested split, worth agreeing before you rework:
- Run strict validation when the request is received, in one place, so it is not interleaved with tokenization and generation.
- Keep generic OpenAI-level checks in the common path.
- Put vLLM-specific fields in a vLLM validator owned by the engine, next to the existing
ValidateConfig-min_tokensis a good example, it is a vLLMSamplingParamsextension, not an OpenAI field.
|
@mayabar Thanks for the detailed review. I have addressed the requested changes in the latest commit ( |
| if err := validateStrictContentType(string(ctx.Request.Header.ContentType())); err != nil { | ||
| c.sendError(ctx, err, false) | ||
| return | ||
| } |
There was a problem hiding this comment.
Consider a function for all headers validation, currently it will contain only one header only
| if value, exists := os.LookupEnv("VLLM_MAX_N_SEQUENCES"); exists { | ||
| maxN, err = strconv.ParseInt(value, 10, 64) | ||
| if err != nil || maxN < 1 { | ||
| return nil, errors.New("VLLM_MAX_N_SEQUENCES must be a positive integer") | ||
| } | ||
| } |
There was a problem hiding this comment.
Seems that there are additional environment variables that are used by vLLM for request validation, e.g. VLLM_MAX_COMPLETION_PROMPTS.
mayabar
left a comment
There was a problem hiding this comment.
Great, thanks!
PR is ready for merge, just waiting for conflict resolution
Signed-off-by: 0z5a <[email protected]>
|
Unsigned commits detected! Please sign your commits. For instructions on how to set up GPG/SSH signing and verify your commits, please see GitHub Documentation. |
|
@0z5a you commit was not signed ;) |
Signed-off-by: 0z5a <[email protected]>
243f218 to
9a3451c
Compare
|
Thanks for catching this. I re-signed the merge commit; GitHub now verifies the updated head, and the code tree is unchanged. |
Add a strict request-validation foundation for the OpenAI chat and text completion endpoints while preserving existing lenient behavior by default. Signed-off-by: 0z5a <[email protected]> Signed-off-by: 0z5a <[email protected]>
Match vLLM validation for prompt logprobs, allowed token IDs, greedy sampling, and multi-error precedence. Validated against vllm/vllm-openai:v0.21.0 on an NVIDIA L20. Signed-off-by: 0z5a <[email protected]> Signed-off-by: 0z5a <[email protected]>
Signed-off-by: 0z5a <[email protected]> Signed-off-by: 0z5a <[email protected]>
Signed-off-by: 0z5a <[email protected]>
Signed-off-by: 0z5a <[email protected]>
…-validation Signed-off-by: 0z5a <[email protected]>
Signed-off-by: 0z5a <[email protected]>
Strict validation mirrored the engine's schema and sampling rules, but the engine also bounds the number of prompts in a text completion request through VLLM_MAX_COMPLETION_PROMPTS, and the header checks had no single home for further additions. Signed-off-by: 0z5a <[email protected]>
Signed-off-by: 0z5a <[email protected]>
9a3451c to
10b519e
Compare
|
@0z5a sorry for delay with review (was on vacation ;) ) please resolve conflicts and I'll be able to approve |
Will resolve conflicts soon, and would you mind me taking some review tasks on inference-sim when you are not available? |
Keep engine-owned request validation compatible with upstream error framing and boolean flag parsing. Signed-off-by: 0z5a <[email protected]>
|
Resolved the merge conflicts with main in 344b4f3, incorporating main at f33dd09. Kept engine-owned strict validation compatible with upstream transport error framing and KV-event encoding. Registered strict validation through the shared toggle parser, added coverage for Validation passed:
The full container-dependent GPU/tokenizer integration suite was not run locally. |
Signed-off-by: Maya Barnea <[email protected]>
|
@0z5a This PR had code conflicts, I merged the upstream/main to your branch. |
Implement the optional validator hook and apply strict header and schema checks only when the engine supplies a validator. Preserve ordinary request checks and cover both completion endpoints. Signed-off-by: 0z5a <[email protected]>
Keep the current SGLang response fields and documentation while preserving the optional strict validator hook. Signed-off-by: 0z5a <[email protected]>
Incremental review: Files changed against
main.What does this PR do?
Adds opt-in validation for
/v1/chat/completionsand/v1/completionswith--strict. The vLLM engine embeds complete request schemas pinned to vLLM 0.21.0 and runs schema and semantic validation when requests arrive, before tokenization or generation. No user-supplied schema file is required.The engine owns sampling ranges, sequence limits, streaming/logprob combinations, tool usage, structured-output constraints and repetition-detection checks. Generic request checks remain shared with lenient mode. The request types carry no validation-only state, and
min_tokenshas one validation site.Why is this change needed?
The simulator otherwise leaves unused request fields unchecked. Versioning the schema and semantic rules together prevents strict mode from mixing constraints from different vLLM releases. The checked-in audit documents every request-field category and the model-dependent limits that require a real serving configuration; strict mode does not assume a vocabulary size or fixed logprob capacity.
Schema errors use the OpenAI error envelope without promising Pydantic coercion or formatting. Schema defaults affect validation only. Context-limited effective token maxima and structured-output backend compilation are outside the receipt-time validator.
How was this tested?
Passed targeted tests for communication, vLLM engine, endpoint, common and API; targeted
go vet; compilation of all packages; andmake lintwith Go 1.26.6. Regenerating the snapshot from the pinned clean vLLM checkout produced identical bytes. The installedgovulncheckreported no reachable vulnerabilities.make presubmitpassed signature/DCO, module tidiness, formatting and lint checks, then failed downloading the latest vulnerability-checker tool due to a network timeout. The installed checker was run separately.Checklist
git commit -s) per DCOmake test)make lint)Related Issues
Related to #676