From bef7f54073e73ba303fa1f5e2efdedc6044470f2 Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Sun, 24 May 2026 13:52:39 +0000 Subject: [PATCH] Studio: align YAML export gate with API mapper + extend Image Size dropdown - training-section.tsx: handleSaveConfig now passes isVisionModel && isDatasetImage === true to serializeConfigToYaml, matching buildTrainingStartPayload. Stops vision_image_size from leaking into exported YAML for text-only datasets where the API would have sent null. - params-section.tsx: add 256 to visionImageSizePresets so the dropdown spans the validator's full [256, 2048] range. Also render a synthetic SelectItem for the current value when it was loaded from YAML or model defaults and is not in the preset list, so the controlled Select always shows the active size. --- .../src/features/studio/sections/params-section.tsx | 13 ++++++++++++- .../features/studio/sections/training-section.tsx | 6 +++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/studio/frontend/src/features/studio/sections/params-section.tsx b/studio/frontend/src/features/studio/sections/params-section.tsx index 56eedfa651..d6489d677c 100644 --- a/studio/frontend/src/features/studio/sections/params-section.tsx +++ b/studio/frontend/src/features/studio/sections/params-section.tsx @@ -139,7 +139,8 @@ export function ParamsSection(): ReactElement { const [ctxInput, setCtxInput] = useState(String(store.contextLength)); const ctxAnchorRef = useRef(null); const ctxItems = CONTEXT_LENGTHS.map(String); - const visionImageSizePresets = [384, 512, 768, 1024, 1536, 2048]; + // Backend validator allows [256, 2048]; offer the full span. + const visionImageSizePresets = [256, 384, 512, 768, 1024, 1536, 2048]; // Keep input in sync when the store value changes externally // (e.g. model defaults being applied after model selection). @@ -953,6 +954,16 @@ export function ParamsSection(): ReactElement { Default + {store.visionImageSize != null && + !visionImageSizePresets.includes( + store.visionImageSize, + ) && ( + + {store.visionImageSize} + + )} {visionImageSizePresets.map((size) => ( {size} diff --git a/studio/frontend/src/features/studio/sections/training-section.tsx b/studio/frontend/src/features/studio/sections/training-section.tsx index 46f97c358f..56c0cc22ef 100644 --- a/studio/frontend/src/features/studio/sections/training-section.tsx +++ b/studio/frontend/src/features/studio/sections/training-section.tsx @@ -80,7 +80,11 @@ export function TrainingSection() { }; const handleSaveConfig = () => { - const yamlStr = serializeConfigToYaml(store, store.isVisionModel); + // Match the API mapper gate so exported YAML never carries + // vision_image_size for non-image datasets. + const includeVisionFields = + store.isVisionModel && store.isDatasetImage === true; + const yamlStr = serializeConfigToYaml(store, includeVisionFields); const blob = new Blob([yamlStr], { type: "text/yaml" }); const url = URL.createObjectURL(blob); const a = document.createElement("a");