Skip to content

Commit a020ac7

Browse files
test(sglang): serve FLUX.2 diffusion on SageMaker instead of VAE decode
Replace the diffusers-only VAE decode test with a real SGLang serving test. The decode test loaded AutoencoderKLFlux2 via diffusers and never exercised SGLang, so it did not validate SGLang's diffusion serving path. - sagemaker_entrypoint.sh: add an SM_SGLANG_ENGINE gate (default "llm", unchanged) so SM_SGLANG_ENGINE=diffusion launches sglang.multimodal_gen.runtime.launch_server instead of the LLM engine. - sagemaker test: deploy FLUX.2-klein-4B (the ungated, servable FLUX.2 pipeline) via the diffusion engine and assert /v1/images/generations returns image data. - drop the sglang_flux_vae_decode_test.sh script and its model-tests entry.
1 parent 4175faa commit a020ac7

4 files changed

Lines changed: 100 additions & 54 deletions

File tree

.github/config/model-tests/sglang-model-tests.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,6 @@ smoke-test:
3838
fleet: "x86-g6xl-runner"
3939
extra_args: "--tp 1 --context-length 4096 --dtype bfloat16"
4040

41-
# FLUX.2-small-decoder is a distilled VAE decoder (AutoencoderKLFlux2), a
42-
# FLUX.2 pipeline component rather than a servable model — validated via a
43-
# decode test (see test_script) instead of the default LLM serving smoke
44-
# test.
45-
- name: "flux2-small-decoder"
46-
s3_model: "flux2-small-decoder.tar.gz"
47-
fleet: "x86-g6xl-runner"
48-
test_script: "sglang_flux_vae_decode_test.sh"
49-
extra_args: ""
5041
- name: "locate-anything-3b"
5142
s3_prefix: "s3://dlc-cicd-models/vlm-models"
5243
s3_model: "locate-anything-3b.tar.gz"

scripts/docker/sglang/sagemaker_entrypoint.sh

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,19 @@ echo "Starting server"
1212
PREFIX="SM_SGLANG_"
1313
ARG_PREFIX="--"
1414

15+
# Engine selector (default: llm). Set SM_SGLANG_ENGINE=diffusion to serve a
16+
# FLUX.2 / diffusion pipeline via sglang.multimodal_gen instead of the LLM
17+
# engine. This var controls the launch module and is NOT forwarded as a flag.
18+
ENGINE=$(echo "${SM_SGLANG_ENGINE:-llm}" | tr '[:upper:]' '[:lower:]')
19+
1520
ARGS=()
1621

1722
while IFS='=' read -r key value; do
23+
# SM_SGLANG_ENGINE selects the launch module; it is not a server flag.
24+
if [ "$key" = "${PREFIX}ENGINE" ]; then
25+
continue
26+
fi
27+
1828
arg_name=$(echo "${key#"${PREFIX}"}" | tr '[:upper:]' '[:lower:]' | tr '_' '-')
1929

2030
# Handle boolean flags: true -> flag only, false -> skip entirely
@@ -46,5 +56,11 @@ if ! [[ " ${ARGS[@]} " =~ " --model-path " ]]; then
4656
ARGS+=(--model-path "${SM_SGLANG_MODEL_PATH:-/opt/ml/model}")
4757
fi
4858

49-
echo "Running command: exec python3 -m sglang.launch_server ${ARGS[@]}"
50-
exec python3 -m sglang.launch_server "${ARGS[@]}"
59+
if [ "$ENGINE" = "diffusion" ]; then
60+
LAUNCH_MODULE="sglang.multimodal_gen.runtime.launch_server"
61+
else
62+
LAUNCH_MODULE="sglang.launch_server"
63+
fi
64+
65+
echo "Running command: exec python3 -m ${LAUNCH_MODULE} ${ARGS[@]}"
66+
exec python3 -m "${LAUNCH_MODULE}" "${ARGS[@]}"

test/sglang/sagemaker/test_sm_endpoint.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,85 @@ def test_sglang_sagemaker_endpoint(model_endpoint, model_id):
118118

119119
LOGGER.info(f"Model response: {pformat(body)}")
120120
LOGGER.info("Inference test successful!")
121+
122+
123+
@pytest.fixture(scope="function")
124+
def flux_endpoint(aws_session, image_uri):
125+
"""Deploy a FLUX.2 diffusion endpoint via the sglang.multimodal_gen engine."""
126+
model_id = "black-forest-labs/FLUX.2-klein-4B"
127+
instance_type = "ml.g6e.xlarge"
128+
129+
cleaned_id = clean_string(model_id.split("/")[1], "_./")
130+
endpoint_name = random_suffix_name(f"sglang-{cleaned_id}", 50)
131+
model_name = endpoint_name
132+
133+
hf_token = get_hf_token(aws_session)
134+
role_arn = aws_session.resolve_role_arn(SAGEMAKER_ROLE)
135+
136+
model = endpoint_config = endpoint = None
137+
try:
138+
LOGGER.info(f"Creating FLUX.2 model: {model_name}")
139+
model = Model.create(
140+
model_name=model_name,
141+
primary_container=ContainerDefinition(
142+
image=image_uri,
143+
environment={
144+
"SM_SGLANG_MODEL_PATH": model_id,
145+
"SM_SGLANG_ENGINE": "diffusion",
146+
"HF_TOKEN": hf_token,
147+
},
148+
),
149+
execution_role_arn=role_arn,
150+
)
151+
152+
LOGGER.info(f"Creating endpoint config: {endpoint_name}")
153+
endpoint_config = EndpointConfig.create(
154+
endpoint_config_name=endpoint_name,
155+
production_variants=[
156+
ProductionVariant(
157+
variant_name="AllTraffic",
158+
model_name=model_name,
159+
initial_instance_count=1,
160+
instance_type=instance_type,
161+
inference_ami_version=INFERENCE_AMI_VERSION,
162+
container_startup_health_check_timeout_in_seconds=900,
163+
),
164+
],
165+
)
166+
167+
LOGGER.info(f"Deploying endpoint: {endpoint_name} (this may take 10-15 minutes)...")
168+
endpoint = Endpoint.create(
169+
endpoint_name=endpoint_name,
170+
endpoint_config_name=endpoint_name,
171+
)
172+
endpoint.wait_for_status("InService")
173+
LOGGER.info("FLUX.2 endpoint deployment completed successfully")
174+
175+
yield endpoint
176+
finally:
177+
_cleanup([endpoint, endpoint_config, model])
178+
179+
180+
def test_sglang_sagemaker_flux_diffusion_endpoint(flux_endpoint):
181+
"""FLUX.2 text-to-image generation through the SageMaker diffusion endpoint."""
182+
endpoint = flux_endpoint
183+
184+
payload = json.dumps(
185+
{
186+
"prompt": "a red cube on a white table",
187+
"num_inference_steps": 4,
188+
"width": 512,
189+
"height": 512,
190+
}
191+
)
192+
LOGGER.debug(f"Sending image-generation request with payload: {payload}")
193+
194+
result = endpoint.invoke(body=payload, content_type="application/json")
195+
body = json.loads(result.body.read())
196+
LOGGER.info("Image-generation request invoked successfully")
197+
198+
assert body, "Model response is empty, failing FLUX.2 endpoint test!"
199+
# OpenAI-style image response returns a non-empty `data` list of images.
200+
assert body.get("data"), f"No image data in FLUX.2 response: {pformat(body)}"
201+
202+
LOGGER.info("FLUX.2 diffusion inference test successful!")

test/sglang/scripts/sglang_flux_vae_decode_test.sh

Lines changed: 0 additions & 43 deletions
This file was deleted.

0 commit comments

Comments
 (0)