enhance(BA-6053): preserve str start_command form in model definitions#11625
Open
achimnol wants to merge 3 commits into
Open
enhance(BA-6053): preserve str start_command form in model definitions#11625achimnol wants to merge 3 commits into
achimnol wants to merge 3 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR resolves #11624 (BA-6053) by preserving start_command as a str when provided as a string in model definitions, instead of coercing it into an argv list via shlex.split. This aligns validation/DTO/GQL layers with the kernel runner’s existing behavior of wrapping string commands as [shell, "-c", str], enabling full shell semantics (including multi-line \ continuations) for users who opt into the string form.
Changes:
- Stop normalizing string
start_commandvalues into argv tokens in config/API validation; widen types tostr | list[str] | None. - Update
{model_path}substitution to handle both list and string forms appropriately. - Update arg-appending to preserve semantics: argv concatenation for list form;
shlex.join+ string concatenation for string form, with new unit tests.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/ai/backend/common/config.py |
Removes shlex.split coercion, widens start_command type, updates placeholder substitution and arg-appending behavior. |
src/ai/backend/common/dto/manager/v2/deployment/request.py |
Widens request DTO start_command to `str |
src/ai/backend/common/dto/manager/v2/deployment/types.py |
Widens response DTO start_command and updates field description to document list-vs-string semantics. |
src/ai/backend/manager/api/gql/deployment/types/revision.py |
Exposes start_command as `JSON |
tests/unit/common/test_config.py |
Adds unit tests ensuring string preservation, placeholder substitution for strings, and shell-quoted arg appending for string form. |
changes/11624.enhance.md |
Adds changelog entry describing the behavioral change and motivation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
71e8974 to
e7c0d9b
Compare
Stop coercing string ``start_command`` values into argv lists via
``shlex.split`` in the API and config validators. The kernel runner
already wraps ``str`` commands as ``[shell, "-c", str]`` at exec time
(``kernel/service.py``), so passing the original string through gives
users full shell semantics — line continuations, ``$VAR`` expansion,
pipes — and removes the need to manually strip backslashes from
copy-pasted multi-line vendor recipes (e.g. vLLM).
- ``ModelServiceConfig.start_command`` and the draft mirror now accept
``str | list[str] | None``; the previous ``shlex.split`` validator
is removed.
- ``{model_path}`` substitution and ``with_args_appended`` handle both
forms; preset ARGS appended to a string command are shell-quoted via
``shlex.join``.
- DTOs in ``common/dto/manager/v2/deployment`` are widened to match.
The GraphQL types expose the field as ``JSON | None`` (the same
pattern already used for ``ModelMetadata.version``) since GraphQL
cannot natively represent a scalar/list union.
Existing list-form definitions are unaffected.
resolves #11624
11624.enhance.md -> 11625.enhance.md Co-authored-by: octodog <mu001@lablup.com>
Co-authored-by: octodog <mu001@lablup.com>
e7c0d9b to
8a339f5
Compare
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.
resolves #11624 (BA-6053)
Summary
Stop coercing string
start_commandvalues into argv lists viashlex.splitin the API and config validators. The kernel runner already wrapsstrcommands as[shell, "-c", str]at exec time (src/ai/backend/kernel/service.py:118-122), so passing the original string through gives users full shell semantics — line continuations,$VARexpansion, pipes — and removes the need to manually strip backslashes from copy-pasted multi-line vendor recipes (e.g. the vLLM recipes the issue cites).What changed
common/config.py: dropped_normalize_start_commandand the_coerce_start_commandfield validators onModelServiceConfig/ModelServiceConfigDraft; widenedstart_commandtostr | list[str] | None. The trafaret schemamodel_definition_ivno longer routes strings throughshlex.spliteither.{model_path}substitution inModelConfigDraft.to_resolvednow dispatches on type — per-token.replacefor the list form, in-place.replacefor the string form.ModelDefinition.with_args_appendedappends preset ARGS as separate argv tokens for the list form, and shell-quotes them viashlex.joinand concatenates with a single space for the string form so the same shell that runs the user's script parses them.common/dto/manager/v2/deployment/{request,types}.pyare widened tostr | list[str] | None.ModelServiceConfigGQL,ModelServiceConfigInputGQL) expose the field asJSON | None— same pattern already used forModelMetadata.versionsince GraphQL cannot natively represent a scalar/list union.Why pass-through (and not, e.g., shell-aware line-continuation stripping)?
Two reasonable options were on the table:
\<newline>beforeshlex.splitso multi-line strings still become argv lists.Option 1 fixes the immediate copy-paste paper cut but does not help users who actually want
$VAR, pipes,&&, or globs in their command — which is the bigger ask in the vendor recipes the issue links. Option 2 (this PR) hands those semantics over to the user explicitly and relies on the kernel runner's already-existing[shell, "-c", str]wrap, so the change is concentrated in validators rather than runtime.Trade-off: a string
start_commandis now eval'd bybashinside the container, so anything that flows into it from external input is shell-evaluated. The list form remains argv-only (no shell) and is the default for the variant baselines; users only opt into shell-eval by writing a string.Scope
Per the issue: existing model definitions with list-style
start_commandare unaffected. The previously released backfill migration8c1f7d3a9e2b(which wrapped legacy string values as one-item lists for the older narrowed schema) is intentionally left untouched.Checklist
test_to_resolved_preserves_str_start_command— string survives validation and{model_path}substitution unchangedtest_model_service_config_accepts_str_start_command— strict type accepts the string form tootest_appends_args_to_str_start_command_with_shell_quoting—with_args_appendedshell-quotes appended argsdescription=updated onModelServiceConfig, the DTO, and both GraphQL typesai.backend.test(N/A — covered by existing model-definition flow tests)Test plan
pants checkon the 5 changed Python files (mypy clean)pants fmt/pants fix/pants lintcleanpants test tests/unit/common/test_config.pypassespants test tests/unit/agent/test_model_service_start_command.pypasses (no regression on the agent-side parser)\) into the WebUI'sstart_commandfield, deploy, and verify the service starts and serves requests📚 Documentation preview 📚: https://sorna--11625.org.readthedocs.build/en/11625/
📚 Documentation preview 📚: https://sorna-ko--11625.org.readthedocs.build/ko/11625/