From 7395ee833e61c62b8928bd2a6cab4b825313e2f1 Mon Sep 17 00:00:00 2001 From: Liangsheng Yin Date: Fri, 7 Aug 2026 01:22:22 -0700 Subject: [PATCH] [CI] Share VLM engines and prune launch matrices on the per-commit H100/H200 suites (#33944) --- .../streaming_session_fixture.py | 9 +++ .../breakable/test_breakable_cuda_graph.py | 4 +- .../lora/test_lora_overlap_loading.py | 2 +- .../mem_cache/test_post_capture_kv_sizing.py | 4 +- .../test_compressed_tensors_models.py | 0 .../test_generation_models.py | 0 .../{models => models_e2e}/test_inkling.py | 2 +- .../models_e2e/test_mimo_v2_flash.py | 4 +- .../models_e2e/test_minimax_m25_basic.py | 6 +- .../models_e2e/test_qwen3_next_models_mtp.py | 7 ++- .../test_transformers_backend_eval.py | 0 .../test_transformers_models.py | 0 .../{models => models_e2e}/test_vlm_models.py | 0 .../{models => models_e2e}/test_zaya.py | 0 .../sessions/test_streaming_session_swa.py | 35 +++--------- .../test_streaming_session_swa_extra.py | 35 ++++++++++++ .../vlm/test_vision_openai_server_a.py | 15 ++--- .../vlm/test_vision_openai_server_extra.py | 27 +++++++++ test/registered/vlm/test_vlm_input_format.py | 57 +++++++++++-------- 19 files changed, 134 insertions(+), 73 deletions(-) rename test/registered/{models => models_e2e}/test_compressed_tensors_models.py (100%) rename test/registered/{models => models_e2e}/test_generation_models.py (100%) rename test/registered/{models => models_e2e}/test_inkling.py (99%) rename test/registered/{models => models_e2e}/test_transformers_backend_eval.py (100%) rename test/registered/{models => models_e2e}/test_transformers_models.py (100%) rename test/registered/{models => models_e2e}/test_vlm_models.py (100%) rename test/registered/{models => models_e2e}/test_zaya.py (100%) create mode 100644 test/registered/sessions/test_streaming_session_swa_extra.py create mode 100644 test/registered/vlm/test_vision_openai_server_extra.py diff --git a/python/sglang/test/server_fixtures/streaming_session_fixture.py b/python/sglang/test/server_fixtures/streaming_session_fixture.py index fe7b8ca9b..f23babbe2 100644 --- a/python/sglang/test/server_fixtures/streaming_session_fixture.py +++ b/python/sglang/test/server_fixtures/streaming_session_fixture.py @@ -51,6 +51,15 @@ LEAK_FILLER = ( "We promptly judged antique ivory buckles for the next prize. " ) * 20 +SWA_MODEL = "openai/gpt-oss-20b" + +# Common gpt-oss-20b launch args. Matches TestSessionLatency/TestSWARadixCacheKL. +SWA_COMMON_ARGS = [ + "--mem-fraction-static", + "0.70", + "--cuda-graph-backend-prefill=disabled", +] + ABORT_REPRO_CONTEXT_LEN = 512 ABORT_REPRO_PAGE_SIZE = 256 ABORT_REPRO_GEN_LEN = 4 diff --git a/test/registered/cuda_graph/breakable/test_breakable_cuda_graph.py b/test/registered/cuda_graph/breakable/test_breakable_cuda_graph.py index 33dce0c45..9ad679fdd 100644 --- a/test/registered/cuda_graph/breakable/test_breakable_cuda_graph.py +++ b/test/registered/cuda_graph/breakable/test_breakable_cuda_graph.py @@ -24,7 +24,7 @@ from sglang.test.test_utils import ( ) # CI Registration — large suite to fit the integration test's server startup. -register_cuda_ci(est_time=79, stage="base-b", runner_config="1-gpu-large") +register_cuda_ci(est_time=60, stage="base-b", runner_config="1-gpu-large") register_amd_ci(est_time=200, suite="stage-c-test-large-8-gpu-amd-mi35x") @@ -388,7 +388,7 @@ class TestBreakableCudaGraph(CustomTestCase): base_url=self.base_url, model=self.model, eval_name="mgsm_en", - num_examples=1319, + num_examples=200, num_threads=1024, ) diff --git a/test/registered/lora/test_lora_overlap_loading.py b/test/registered/lora/test_lora_overlap_loading.py index 696f9528f..4d5d9f360 100644 --- a/test/registered/lora/test_lora_overlap_loading.py +++ b/test/registered/lora/test_lora_overlap_loading.py @@ -30,7 +30,7 @@ from sglang.test.lora_utils import ( ) from sglang.test.test_utils import CustomTestCase -register_cuda_ci(est_time=48, stage="base-b", runner_config="1-gpu-large") +register_cuda_ci(est_time=380, stage="base-b", runner_config="1-gpu-large") register_amd_ci(est_time=75, suite="stage-b-test-1-gpu-small-amd") diff --git a/test/registered/mem_cache/test_post_capture_kv_sizing.py b/test/registered/mem_cache/test_post_capture_kv_sizing.py index a641e12c9..1e029a0f3 100644 --- a/test/registered/mem_cache/test_post_capture_kv_sizing.py +++ b/test/registered/mem_cache/test_post_capture_kv_sizing.py @@ -28,7 +28,7 @@ from sglang.test.test_utils import ( ) # CI Registration -register_cuda_ci(est_time=240, stage="base-b", runner_config="1-gpu-large") +register_cuda_ci(est_time=100, stage="base-b", runner_config="1-gpu-large") STDOUT_FILENAME = "post_capture_kv_sizing_stdout.log" STDERR_FILENAME = "post_capture_kv_sizing_stderr.log" @@ -88,7 +88,7 @@ class TestPostCaptureKVSizing(CustomTestCase): base_url=self.base_url, model=self.model, eval_name="gsm8k", - num_examples=500, + num_examples=200, num_threads=1024, ) metrics = run_eval(args) diff --git a/test/registered/models/test_compressed_tensors_models.py b/test/registered/models_e2e/test_compressed_tensors_models.py similarity index 100% rename from test/registered/models/test_compressed_tensors_models.py rename to test/registered/models_e2e/test_compressed_tensors_models.py diff --git a/test/registered/models/test_generation_models.py b/test/registered/models_e2e/test_generation_models.py similarity index 100% rename from test/registered/models/test_generation_models.py rename to test/registered/models_e2e/test_generation_models.py diff --git a/test/registered/models/test_inkling.py b/test/registered/models_e2e/test_inkling.py similarity index 99% rename from test/registered/models/test_inkling.py rename to test/registered/models_e2e/test_inkling.py index 670b4d912..a84441a2a 100644 --- a/test/registered/models/test_inkling.py +++ b/test/registered/models_e2e/test_inkling.py @@ -31,7 +31,7 @@ from sglang.test.test_utils import ( popen_launch_server, ) -register_cuda_ci(est_time=600, stage="base-b", runner_config="1-gpu-large") +register_cuda_ci(est_time=250, stage="base-b", runner_config="1-gpu-large") # Defaults to the HF `test` revision; override MODEL/REVISION to point at a # local checkpoint. Empty REVISION drops the flag (for local paths). diff --git a/test/registered/models_e2e/test_mimo_v2_flash.py b/test/registered/models_e2e/test_mimo_v2_flash.py index e431b0f7a..74d377fd2 100644 --- a/test/registered/models_e2e/test_mimo_v2_flash.py +++ b/test/registered/models_e2e/test_mimo_v2_flash.py @@ -7,13 +7,11 @@ from sglang.test.kits.eval_accuracy_kit import GSM8KMixin from sglang.test.kits.spec_decoding_kit import SpecDecodingMixin from sglang.test.server_fixtures.default_fixture import DefaultServerBase -register_cuda_ci(est_time=350, stage="base-c", runner_config="8-gpu-h200") +register_cuda_ci(est_time=200, stage="base-c", runner_config="8-gpu-h200") class TestMiMoV2Flash(GSM8KMixin, SpecDecodingMixin, DefaultServerBase): gsm8k_accuracy_thres = 0.75 - gsm8k_num_questions = 1319 - gsm8k_num_threads = 1319 model = "XiaomiMiMo/MiMo-V2-Flash" other_args = [ diff --git a/test/registered/models_e2e/test_minimax_m25_basic.py b/test/registered/models_e2e/test_minimax_m25_basic.py index 2ec8fab56..0230ba7bd 100644 --- a/test/registered/models_e2e/test_minimax_m25_basic.py +++ b/test/registered/models_e2e/test_minimax_m25_basic.py @@ -14,7 +14,7 @@ from sglang.test.test_utils import ( write_github_step_summary, ) -register_cuda_ci(est_time=250, stage="base-c", runner_config="8-gpu-h200") +register_cuda_ci(est_time=160, stage="base-c", runner_config="8-gpu-h200") MINIMAX_M25_MODEL_PATH = "MiniMaxAI/MiniMax-M2.5" @@ -53,8 +53,8 @@ class TestMiniMaxM25Basic(CustomTestCase): args = SimpleNamespace( num_shots=20, data_path=None, - num_questions=1400, - parallel=1400, + num_questions=200, + parallel=200, max_new_tokens=512, host="http://127.0.0.1", port=int(self.base_url.split(":")[-1]), diff --git a/test/registered/models_e2e/test_qwen3_next_models_mtp.py b/test/registered/models_e2e/test_qwen3_next_models_mtp.py index 385d58f5a..8ffd70fc8 100644 --- a/test/registered/models_e2e/test_qwen3_next_models_mtp.py +++ b/test/registered/models_e2e/test_qwen3_next_models_mtp.py @@ -7,7 +7,7 @@ from sglang.test.kits.kl_divergence_kit import KLDivergenceMixin from sglang.test.kits.prefix_cache_branching_kit import PrefixCacheBranchingMixin from sglang.test.server_fixtures.default_fixture import DefaultServerBase -register_cuda_ci(est_time=430, stage="base-c", runner_config="4-gpu-h100") +register_cuda_ci(est_time=290, stage="base-c", runner_config="4-gpu-h100") QWEN3_NEXT_MODEL = "Qwen/Qwen3-Next-80B-A3B-Instruct" @@ -69,6 +69,11 @@ class TestQwen3NextMTPTopk( ] +@unittest.skip( + "Manual-only: topk == 1 is covered by TestQwen3NextMTPLazyV2 and extra_buffer " + "by TestQwen3NextMTPTopk. Kept runnable locally for the plain (topk=1, " + "extra_buffer) baseline." +) class TestQwen3NextMTPV2(GSM8KMixin, KLDivergenceMixin, DefaultServerBase): model = QWEN3_NEXT_MODEL gsm8k_accuracy_thres = 0.93 diff --git a/test/registered/models/test_transformers_backend_eval.py b/test/registered/models_e2e/test_transformers_backend_eval.py similarity index 100% rename from test/registered/models/test_transformers_backend_eval.py rename to test/registered/models_e2e/test_transformers_backend_eval.py diff --git a/test/registered/models/test_transformers_models.py b/test/registered/models_e2e/test_transformers_models.py similarity index 100% rename from test/registered/models/test_transformers_models.py rename to test/registered/models_e2e/test_transformers_models.py diff --git a/test/registered/models/test_vlm_models.py b/test/registered/models_e2e/test_vlm_models.py similarity index 100% rename from test/registered/models/test_vlm_models.py rename to test/registered/models_e2e/test_vlm_models.py diff --git a/test/registered/models/test_zaya.py b/test/registered/models_e2e/test_zaya.py similarity index 100% rename from test/registered/models/test_zaya.py rename to test/registered/models_e2e/test_zaya.py diff --git a/test/registered/sessions/test_streaming_session_swa.py b/test/registered/sessions/test_streaming_session_swa.py index f6a9b66a1..e18d1541b 100644 --- a/test/registered/sessions/test_streaming_session_swa.py +++ b/test/registered/sessions/test_streaming_session_swa.py @@ -1,3 +1,9 @@ +"""Per-commit streaming-session tests on a hybrid-SWA model. + +Baseline + large-page retract + abort-leak repro stay per-commit; the +mixed-chunk retract variant lives in test_streaming_session_swa_extra.py. +""" + import unittest from sglang.test.ci.ci_register import register_cuda_ci @@ -9,20 +15,12 @@ from sglang.test.server_fixtures.streaming_session_fixture import ( ABORT_REPRO_CHUNKED_PREFILL_SIZE, ABORT_REPRO_CONTEXT_LEN, ABORT_REPRO_PAGE_SIZE, + SWA_COMMON_ARGS, + SWA_MODEL, StreamingSessionServerBase, ) -register_cuda_ci(est_time=519, stage="base-b", runner_config="1-gpu-large") - - -SWA_MODEL = "openai/gpt-oss-20b" - -# Common gpt-oss-20b launch args. Matches TestSessionLatency/TestSWARadixCacheKL. -SWA_COMMON_ARGS = [ - "--mem-fraction-static", - "0.70", - "--cuda-graph-backend-prefill=disabled", -] +register_cuda_ci(est_time=390, stage="base-b", runner_config="1-gpu-large") class TestStreamingSessionSWA(StreamingSessionServerBase, StreamingSessionKitMixin): @@ -48,21 +46,6 @@ class TestStreamingSessionSWARetractLargePage( env_overrides = [("SGLANG_TEST_RETRACT", True)] -class TestStreamingSessionSWARetractMixedChunk( - StreamingSessionServerBase, StreamingSessionKitMixin -): - """SWA under retract decode with --enable-mixed-chunk.""" - - model = SWA_MODEL - extra_args = [ - "--chunked-prefill-size", - "128", - "--enable-mixed-chunk", - *SWA_COMMON_ARGS, - ] - env_overrides = [("SGLANG_TEST_RETRACT", True)] - - class TestStreamingSessionSWAAbortLeakRepro( StreamingSessionServerBase, AbortLeakReproKitMixin ): diff --git a/test/registered/sessions/test_streaming_session_swa_extra.py b/test/registered/sessions/test_streaming_session_swa_extra.py new file mode 100644 index 000000000..2fdc336b4 --- /dev/null +++ b/test/registered/sessions/test_streaming_session_swa_extra.py @@ -0,0 +1,35 @@ +"""Label-gated SWA streaming-session variants. + +CUDA-only: gpt-oss-20b is not part of the AMD streaming-session coverage. +""" + +import unittest + +from sglang.test.ci.ci_register import register_cuda_ci +from sglang.test.kits.streaming_session_kit import StreamingSessionKitMixin +from sglang.test.server_fixtures.streaming_session_fixture import ( + SWA_COMMON_ARGS, + SWA_MODEL, + StreamingSessionServerBase, +) + +register_cuda_ci(est_time=130, stage="extra-a", runner_config="1-gpu-large") + + +class TestStreamingSessionSWARetractMixedChunk( + StreamingSessionServerBase, StreamingSessionKitMixin +): + """SWA under retract decode with --enable-mixed-chunk.""" + + model = SWA_MODEL + extra_args = [ + "--chunked-prefill-size", + "128", + "--enable-mixed-chunk", + *SWA_COMMON_ARGS, + ] + env_overrides = [("SGLANG_TEST_RETRACT", True)] + + +if __name__ == "__main__": + unittest.main() diff --git a/test/registered/vlm/test_vision_openai_server_a.py b/test/registered/vlm/test_vision_openai_server_a.py index c0f7b7cf4..2284610b3 100644 --- a/test/registered/vlm/test_vision_openai_server_a.py +++ b/test/registered/vlm/test_vision_openai_server_a.py @@ -20,7 +20,7 @@ from sglang.test.vlm_utils import ( terminate_and_kill_process_tree, ) -register_cuda_ci(est_time=780, stage="base-b", runner_config="1-gpu-large") +register_cuda_ci(est_time=560, stage="base-b", runner_config="1-gpu-large") class TestLlavaServer(ImageOpenAITestMixin): @@ -43,17 +43,10 @@ class TestQwen3VLServer(ImageOpenAITestMixin, VideoOpenAITestMixin): extra_args = ["--cuda-graph-max-bs-decode=4"] -class TestQwen3OmniServer(OmniOpenAITestMixin): - model = "Qwen/Qwen3-Omni-30B-A3B-Instruct" - extra_args = [ # workaround to fit into H100 - "--mem-fraction-static=0.90", - "--disable-cuda-graph", - "--disable-fast-image-processor", - "--grammar-backend=none", - ] - - class TestQwen2VLContextLengthServer(CustomTestCase): + # --context-length 300 is calibrated to this model's mm-token expansion: + # it must sit above the warmup image's expanded length but below the test + # image's. A cheaper VLM needs the bound recalibrated, not just swapped. @classmethod def setUpClass(cls): cls.model = "Qwen/Qwen2-VL-7B-Instruct" diff --git a/test/registered/vlm/test_vision_openai_server_extra.py b/test/registered/vlm/test_vision_openai_server_extra.py new file mode 100644 index 000000000..59b42ea62 --- /dev/null +++ b/test/registered/vlm/test_vision_openai_server_extra.py @@ -0,0 +1,27 @@ +"""Label-gated vision/omni server launches too expensive for the per-commit +budget; the per-commit set lives in test_vision_openai_server_a.py.""" + +import unittest + +from sglang.test.ci.ci_register import register_cuda_ci +from sglang.test.vlm_utils import OmniOpenAITestMixin + +register_cuda_ci(est_time=180, stage="extra-a", runner_config="1-gpu-large") + + +class TestQwen3OmniServer(OmniOpenAITestMixin): + model = "Qwen/Qwen3-Omni-30B-A3B-Instruct" + extra_args = [ # workaround to fit into H100 + "--mem-fraction-static=0.90", + "--disable-cuda-graph", + "--disable-fast-image-processor", + "--grammar-backend=none", + ] + + +# Delete the mixin so it is not collected as a test case in its own right. +del OmniOpenAITestMixin + + +if __name__ == "__main__": + unittest.main() diff --git a/test/registered/vlm/test_vlm_input_format.py b/test/registered/vlm/test_vlm_input_format.py index 3f059f0f2..c952235fc 100644 --- a/test/registered/vlm/test_vlm_input_format.py +++ b/test/registered/vlm/test_vlm_input_format.py @@ -37,8 +37,9 @@ from sglang.srt.entrypoints.openai.protocol import ChatCompletionRequest from sglang.srt.parser.conversation import generate_chat_conv from sglang.srt.utils.common import is_cuda, is_xpu from sglang.srt.utils.hf_transformers_utils import _fix_added_tokens_encoding +from sglang.test.test_utils import CustomTestCase -register_cuda_ci(est_time=747, stage="base-b", runner_config="1-gpu-large") +register_cuda_ci(est_time=300, stage="base-b", runner_config="1-gpu-large") IMAGE_MAN_IRONING_URL = "https://raw.githubusercontent.com/sgl-project/sgl-test-files/refs/heads/main/images/man_ironing_on_back_of_suv.png" IMAGE_SGL_LOGO_URL = "https://raw.githubusercontent.com/sgl-project/sgl-test-files/refs/heads/main/images/sgl_logo.png" @@ -52,6 +53,7 @@ class VLMInputTestBase: chat_template = None processor = None visual = None # Should be a callable for precomputed embeddings + engine = None @classmethod def setUpClass(cls): @@ -76,25 +78,34 @@ class VLMInputTestBase: ) _fix_added_tokens_encoding(cls.processor.tokenizer) cls._init_visual() + cls._start_engine() @classmethod def _init_visual(cls): """Override in subclass to set up cls.visual as a callable for precomputed embeddings.""" raise NotImplementedError - def setUp(self): - self.engine = Engine( - model_path=self.model_path, - chat_template=self.chat_template, - device=self.device.type, + @classmethod + def _start_engine(cls): + # One engine per class: every test only reads through it. The tests are + # sync rather than async because the tokenizer manager pins handle_loop + # to the loop of the first request, so a per-test loop would strand it. + cls.engine = Engine( + model_path=cls.model_path, + chat_template=cls.chat_template, + device=cls.device.type, mem_fraction_static=0.8, enable_multimodal=True, disable_cuda_graph=True, trust_remote_code=True, ) - def tearDown(self): - self.engine.shutdown() + @classmethod + def tearDownClass(cls): + # CustomTestCase runs tearDownClass even when setUpClass raised. + if cls.engine is not None: + cls.engine.shutdown() + cls.engine = None def verify_response(self, output): # The goal is to check that the model roughly understands: @@ -157,25 +168,25 @@ class VLMInputTestBase: return inputs, text - async def test_accepts_image(self): + def test_accepts_image(self): req = self.get_completion_request() conv = generate_chat_conv(req, template_name=self.chat_template) text = conv.get_prompt() - output = await self.engine.async_generate( + output = self.engine.generate( prompt=text, image_data=self.main_image, sampling_params=dict(temperature=0.0, max_new_tokens=512), ) self.verify_response(output) - async def test_accepts_precomputed_embeddings(self): + def test_accepts_precomputed_embeddings(self): req = self.get_completion_request() processor_output, _ = self.get_processor_output(req=req) with torch.inference_mode(): precomputed_embeddings = self.__class__.visual(processor_output) - output = await self.engine.async_generate( + output = self.engine.generate( input_ids=processor_output["input_ids"][0].detach().cpu().tolist(), image_data=[ self._precomputed_image_data(processor_output, precomputed_embeddings) @@ -184,10 +195,10 @@ class VLMInputTestBase: ) self.verify_response(output) - async def test_accepts_processor_output(self): + def test_accepts_processor_output(self): req = self.get_completion_request() processor_output, prompt = self.get_processor_output(req=req) - output = await self.engine.async_generate( + output = self.engine.generate( input_ids=processor_output["input_ids"][0].detach().cpu().tolist(), image_data=[self._processor_output_image_data(processor_output)], sampling_params=dict(temperature=0.0, max_new_tokens=512), @@ -207,7 +218,7 @@ class VLMInputTestBase: raise NotImplementedError -class TestQwenVLUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTestCase): +class TestQwenVLUnderstandsImage(VLMInputTestBase, CustomTestCase): model_path = "Qwen/Qwen2.5-VL-3B-Instruct" chat_template = "qwen2-vl" @@ -234,7 +245,7 @@ class TestQwenVLUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTestC return dict(processor_output, format="processor_output") -class TestGemmaUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTestCase): +class TestGemmaUnderstandsImage(VLMInputTestBase, CustomTestCase): model_path = "google/gemma-3-4b-it" chat_template = "gemma-it" @@ -263,9 +274,7 @@ class TestGemmaUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTestCa # Updated Kimi-VL test to use the new input format. -class TestKimiVLImageUnderstandsImage( - VLMInputTestBase, unittest.IsolatedAsyncioTestCase -): +class TestKimiVLImageUnderstandsImage(VLMInputTestBase, CustomTestCase): model_path = "moonshotai/Kimi-VL-A3B-Instruct" chat_template = "kimi-vl" @@ -322,7 +331,7 @@ class TestKimiVLImageUnderstandsImage( # not for CI: too large # class TestLlama4ImageUnderstandsImage( -# VLMInputTestBase, unittest.IsolatedAsyncioTestCase +# VLMInputTestBase, CustomTestCase # ): # # Allow overriding via env for local/offline runs. # model_path = "meta-llama/Llama-4-Scout-17B-16E-Instruct" @@ -364,7 +373,7 @@ class TestKimiVLImageUnderstandsImage( # return dict(processor_output, format="processor_output") -# class TestLlavaUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTestCase): +# class TestLlavaUnderstandsImage(VLMInputTestBase, CustomTestCase): # model_path = "llava-hf/llava-1.5-7b-hf" # chat_template = "vicuna_v1.1" @@ -403,7 +412,7 @@ class TestKimiVLImageUnderstandsImage( # return dict(processor_output, format="processor_output") -class TestInternVLUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTestCase): +class TestInternVLUnderstandsImage(VLMInputTestBase, CustomTestCase): model_path = "OpenGVLab/InternVL2-2B" chat_template = "internvl-2-5" @@ -427,6 +436,7 @@ class TestInternVLUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTes cls.model_path, trust_remote_code=True ) cls._init_visual() + cls._start_engine() @classmethod def _init_visual(cls): @@ -591,7 +601,7 @@ class TestInternVLUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTes @unittest.skip("temporarily disabled: NaN in next_token_logits") -class TestMiniCPMVUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTestCase): +class TestMiniCPMVUnderstandsImage(VLMInputTestBase, CustomTestCase): model_path = "openbmb/MiniCPM-V-4" chat_template = "minicpmv" @@ -618,6 +628,7 @@ class TestMiniCPMVUnderstandsImage(VLMInputTestBase, unittest.IsolatedAsyncioTes cls.processor.tokenizer = get_tokenizer(cls.model_path, trust_remote_code=True) _fix_added_tokens_encoding(cls.processor.tokenizer) cls._init_visual() + cls._start_engine() @classmethod def _init_visual(cls):