A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 14, 22:35 UTC
[Doc] Add example for Step3-VL (#22061)
Signed-off-by: Roger Wang <hey@rogerw.me>
Roger Wang committed
Aug 1, 2025 at 01:35 UTC
27a145e8931582fc74c1f46e0e4630c610b96160
2 files changed
+270
-211
examples/offline_inference/vision_language.py
+157
-127
@@ -423,32 +423,6 @@ def run_idefics3(questions: list[str], modality: str) -> ModelRequestData:
423
)
424
425
426
-# SmolVLM2-2.2B-Instruct
427
-def run_smolvlm(questions: list[str], modality: str) -> ModelRequestData:
428
- assert modality == "image"
429
- model_name = "HuggingFaceTB/SmolVLM2-2.2B-Instruct"
430
-
431
- engine_args = EngineArgs(
432
- model=model_name,
433
- max_model_len=8192,
434
- max_num_seqs=2,
435
- enforce_eager=True,
436
- mm_processor_kwargs={
437
- "max_image_size": {"longest_edge": 384},
438
- },
439
- limit_mm_per_prompt={modality: 1},
440
- )
441
- prompts = [
442
- (f"<|im_start|>User:<image>{question}<end_of_utterance>\nAssistant:")
443
- for question in questions
444
- ]
445
-
446
- return ModelRequestData(
447
- engine_args=engine_args,
448
- prompts=prompts,
449
- )
450
-
451
-
426
# Intern-S1
427
def run_interns1(questions: list[str], modality: str) -> ModelRequestData:
428
model_name = "internlm/Intern-S1"
@@ -522,44 +496,6 @@ def run_internvl(questions: list[str], modality: str) -> ModelRequestData:
496
)
497
498
525
-# Nemontron_VL
526
-def run_nemotron_vl(questions: list[str], modality: str) -> ModelRequestData:
527
- model_name = "nvidia/Llama-3.1-Nemotron-Nano-VL-8B-V1"
528
-
529
- engine_args = EngineArgs(
530
- model=model_name,
531
- trust_remote_code=True,
532
- max_model_len=8192,
533
- limit_mm_per_prompt={modality: 1},
534
- )
535
-
536
- assert modality == "image"
537
- placeholder = "<image>"
538
-
539
- tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
540
- messages = [
541
- [{"role": "user", "content": f"{placeholder}\n{question}"}]
542
- for question in questions
543
- ]
544
- prompts = tokenizer.apply_chat_template(
545
- messages, tokenize=False, add_generation_prompt=True
546
- )
547
-
548
- # Stop tokens for InternVL
549
- # models variants may have different stop tokens
550
- # please refer to the model card for the correct "stop words":
551
- # https://huggingface.co/OpenGVLab/InternVL2-2B/blob/main/conversation.py
552
- stop_tokens = ["<|endoftext|>", "<|im_start|>", "<|im_end|>", "<|end|>"]
553
- stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]
554
- stop_token_ids = [token_id for token_id in stop_token_ids if token_id is not None]
555
-
556
- return ModelRequestData(
557
- engine_args=engine_args,
558
- prompts=prompts,
559
- stop_token_ids=stop_token_ids,
560
- )
561
-
562
-
499
# Keye-VL
500
def run_keye_vl(questions: list[str], modality: str) -> ModelRequestData:
501
model_name = "Kwai-Keye/Keye-VL-8B-Preview"
@@ -615,6 +551,41 @@ def run_kimi_vl(questions: list[str], modality: str) -> ModelRequestData:
551
)
552
553
554
+def run_llama4(questions: list[str], modality: str) -> ModelRequestData:
555
+ assert modality == "image"
556
+
557
+ model_name = "meta-llama/Llama-4-Scout-17B-16E-Instruct"
558
+
559
+ engine_args = EngineArgs(
560
+ model=model_name,
561
+ max_model_len=8192,
562
+ max_num_seqs=4,
563
+ tensor_parallel_size=8,
564
+ gpu_memory_utilization=0.4,
565
+ limit_mm_per_prompt={modality: 1},
566
+ )
567
+
568
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
569
+ messages = [
570
+ [
571
+ {
572
+ "role": "user",
573
+ "content": [{"type": "image"}, {"type": "text", "text": f"{question}"}],
574
+ }
575
+ ]
576
+ for question in questions
577
+ ]
578
+ prompts = tokenizer.apply_chat_template(
579
+ messages, add_generation_prompt=True, tokenize=False
580
+ )
581
+ stop_token_ids = None
582
+ return ModelRequestData(
583
+ engine_args=engine_args,
584
+ prompts=prompts,
585
+ stop_token_ids=stop_token_ids,
586
+ )
587
+
588
+
589
# LLaVA-1.5
590
def run_llava(questions: list[str], modality: str) -> ModelRequestData:
591
assert modality == "image"
@@ -857,63 +828,66 @@ def run_mllama(questions: list[str], modality: str) -> ModelRequestData:
828
)
829
830
860
-def run_llama4(questions: list[str], modality: str) -> ModelRequestData:
831
+# Molmo
832
+def run_molmo(questions: list[str], modality: str) -> ModelRequestData:
833
assert modality == "image"
834
863
- model_name = "meta-llama/Llama-4-Scout-17B-16E-Instruct"
835
+ model_name = "allenai/Molmo-7B-D-0924"
836
837
engine_args = EngineArgs(
838
model=model_name,
867
- max_model_len=8192,
868
- max_num_seqs=4,
869
- tensor_parallel_size=8,
870
- gpu_memory_utilization=0.4,
839
+ trust_remote_code=True,
840
+ dtype="bfloat16",
841
limit_mm_per_prompt={modality: 1},
842
)
843
874
- tokenizer = AutoTokenizer.from_pretrained(model_name)
875
- messages = [
876
- [
877
- {
878
- "role": "user",
879
- "content": [{"type": "image"}, {"type": "text", "text": f"{question}"}],
880
- }
881
- ]
844
+ prompts = [
845
+ f"<|im_start|>user <image>\n{question}<|im_end|> \
846
+ <|im_start|>assistant\n"
847
for question in questions
848
]
884
- prompts = tokenizer.apply_chat_template(
885
- messages, add_generation_prompt=True, tokenize=False
886
- )
887
- stop_token_ids = None
849
+
850
return ModelRequestData(
851
engine_args=engine_args,
852
prompts=prompts,
891
- stop_token_ids=stop_token_ids,
853
)
854
855
895
-# Molmo
896
-def run_molmo(questions: list[str], modality: str) -> ModelRequestData:
897
- assert modality == "image"
898
-
899
- model_name = "allenai/Molmo-7B-D-0924"
856
+# Nemontron_VL
857
+def run_nemotron_vl(questions: list[str], modality: str) -> ModelRequestData:
858
+ model_name = "nvidia/Llama-3.1-Nemotron-Nano-VL-8B-V1"
859
860
engine_args = EngineArgs(
861
model=model_name,
862
trust_remote_code=True,
904
- dtype="bfloat16",
863
+ max_model_len=8192,
864
limit_mm_per_prompt={modality: 1},
865
)
866
908
- prompts = [
909
- f"<|im_start|>user <image>\n{question}<|im_end|> \
910
- <|im_start|>assistant\n"
867
+ assert modality == "image"
868
+ placeholder = "<image>"
869
+
870
+ tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
871
+ messages = [
872
+ [{"role": "user", "content": f"{placeholder}\n{question}"}]
873
for question in questions
874
]
875
+ prompts = tokenizer.apply_chat_template(
876
+ messages, tokenize=False, add_generation_prompt=True
877
+ )
878
+
879
+ # Stop tokens for InternVL
880
+ # models variants may have different stop tokens
881
+ # please refer to the model card for the correct "stop words":
882
+ # https://huggingface.co/OpenGVLab/InternVL2-2B/blob/main/conversation.py
883
+ stop_tokens = ["<|endoftext|>", "<|im_start|>", "<|im_end|>", "<|end|>"]
884
+ stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]
885
+ stop_token_ids = [token_id for token_id in stop_token_ids if token_id is not None]
886
887
return ModelRequestData(
888
engine_args=engine_args,
889
prompts=prompts,
890
+ stop_token_ids=stop_token_ids,
891
)
892
893
@@ -1274,10 +1248,11 @@ def run_qwen2_5_omni(questions: list[str], modality: str):
1248
)
1249
1250
1277
-# omni-research/Tarsier-7b
1278
-def run_tarsier(questions: list[str], modality: str) -> ModelRequestData:
1251
+# SkyworkR1V
1252
+def run_skyworkr1v(questions: list[str], modality: str) -> ModelRequestData:
1253
assert modality == "image"
1280
- model_name = "omni-research/Tarsier-7b"
1254
+
1255
+ model_name = "Skywork/Skywork-R1V-38B"
1256
1257
engine_args = EngineArgs(
1258
model=model_name,
@@ -1285,36 +1260,73 @@ def run_tarsier(questions: list[str], modality: str) -> ModelRequestData:
1260
max_model_len=4096,
1261
limit_mm_per_prompt={modality: 1},
1262
)
1288
- prompts = [(f"USER: <image>\n{question} ASSISTANT:") for question in questions]
1263
+
1264
+ tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
1265
+ messages = [
1266
+ [{"role": "user", "content": f"<image>\n{question}"}] for question in questions
1267
+ ]
1268
+ prompts = tokenizer.apply_chat_template(
1269
+ messages, tokenize=False, add_generation_prompt=True
1270
+ )
1271
+
1272
+ # Stop tokens for SkyworkR1V
1273
+ # https://huggingface.co/Skywork/Skywork-R1V-38B/blob/main/conversation.py
1274
+ stop_tokens = ["<|end▁of▁sentence|>", "<|endoftext|>"]
1275
+ stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]
1276
1277
return ModelRequestData(
1278
engine_args=engine_args,
1279
prompts=prompts,
1280
+ stop_token_ids=stop_token_ids,
1281
)
1282
1283
1296
-def run_tarsier2(questions: list[str], modality: str) -> ModelRequestData:
1297
- model_name = "omni-research/Tarsier2-Recap-7b"
1284
+# SmolVLM2-2.2B-Instruct
1285
+def run_smolvlm(questions: list[str], modality: str) -> ModelRequestData:
1286
+ assert modality == "image"
1287
+ model_name = "HuggingFaceTB/SmolVLM2-2.2B-Instruct"
1288
1289
engine_args = EngineArgs(
1290
model=model_name,
1301
- max_model_len=4096,
1302
- hf_overrides={"architectures": ["Tarsier2ForConditionalGeneration"]},
1291
+ max_model_len=8192,
1292
+ max_num_seqs=2,
1293
+ enforce_eager=True,
1294
+ mm_processor_kwargs={
1295
+ "max_image_size": {"longest_edge": 384},
1296
+ },
1297
limit_mm_per_prompt={modality: 1},
1298
)
1299
+ prompts = [
1300
+ (f"<|im_start|>User:<image>{question}<end_of_utterance>\nAssistant:")
1301
+ for question in questions
1302
+ ]
1303
1306
- if modality == "image":
1307
- placeholder = "<|image_pad|>"
1308
- elif modality == "video":
1309
- placeholder = "<|video_pad|>"
1304
+ return ModelRequestData(
1305
+ engine_args=engine_args,
1306
+ prompts=prompts,
1307
+ )
1308
+
1309
+
1310
+# Step3
1311
+def run_step3(questions: list[str], modality: str) -> ModelRequestData:
1312
+ assert modality == "image"
1313
+
1314
+ model_name = "stepfun-ai/step3-fp8"
1315
+
1316
+ # NOTE: Below are verified configurations for step3-fp8
1317
+ # on 8xH100 GPUs.
1318
+ engine_args = EngineArgs(
1319
+ model=model_name,
1320
+ max_num_batched_tokens=4096,
1321
+ gpu_memory_utilization=0.85,
1322
+ tensor_parallel_size=8,
1323
+ limit_mm_per_prompt={modality: 1},
1324
+ reasoning_parser="step3",
1325
+ )
1326
1327
prompts = [
1312
- (
1313
- "<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n"
1314
- f"<|im_start|>user\n<|vision_start|>{placeholder}<|vision_end|>"
1315
- f"{question}<|im_end|>\n"
1316
- "<|im_start|>assistant\n"
1317
- )
1328
+ "<|begin▁of▁sentence|> You are a helpful assistant. <|BOT|>user\n "
1329
+ f"<im_patch>{question} <|EOT|><|BOT|>assistant\n<think>\n"
1330
for question in questions
1331
]
1332
@@ -1324,11 +1336,10 @@ def run_tarsier2(questions: list[str], modality: str) -> ModelRequestData:
1336
)
1337
1338
1327
-# SkyworkR1V
1328
-def run_skyworkr1v(questions: list[str], modality: str) -> ModelRequestData:
1339
+# omni-research/Tarsier-7b
1340
+def run_tarsier(questions: list[str], modality: str) -> ModelRequestData:
1341
assert modality == "image"
1330
-
1331
- model_name = "Skywork/Skywork-R1V-38B"
1342
+ model_name = "omni-research/Tarsier-7b"
1343
1344
engine_args = EngineArgs(
1345
model=model_name,
@@ -1336,24 +1347,42 @@ def run_skyworkr1v(questions: list[str], modality: str) -> ModelRequestData:
1347
max_model_len=4096,
1348
limit_mm_per_prompt={modality: 1},
1349
)
1350
+ prompts = [(f"USER: <image>\n{question} ASSISTANT:") for question in questions]
1351
1340
- tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
1341
- messages = [
1342
- [{"role": "user", "content": f"<image>\n{question}"}] for question in questions
1343
- ]
1344
- prompts = tokenizer.apply_chat_template(
1345
- messages, tokenize=False, add_generation_prompt=True
1352
+ return ModelRequestData(
1353
+ engine_args=engine_args,
1354
+ prompts=prompts,
1355
)
1356
1348
- # Stop tokens for SkyworkR1V
1349
- # https://huggingface.co/Skywork/Skywork-R1V-38B/blob/main/conversation.py
1350
- stop_tokens = ["<|end▁of▁sentence|>", "<|endoftext|>"]
1351
- stop_token_ids = [tokenizer.convert_tokens_to_ids(i) for i in stop_tokens]
1357
+
1358
+def run_tarsier2(questions: list[str], modality: str) -> ModelRequestData:
1359
+ model_name = "omni-research/Tarsier2-Recap-7b"
1360
+
1361
+ engine_args = EngineArgs(
1362
+ model=model_name,
1363
+ max_model_len=4096,
1364
+ hf_overrides={"architectures": ["Tarsier2ForConditionalGeneration"]},
1365
+ limit_mm_per_prompt={modality: 1},
1366
+ )
1367
+
1368
+ if modality == "image":
1369
+ placeholder = "<|image_pad|>"
1370
+ elif modality == "video":
1371
+ placeholder = "<|video_pad|>"
1372
+
1373
+ prompts = [
1374
+ (
1375
+ "<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n"
1376
+ f"<|im_start|>user\n<|vision_start|>{placeholder}<|vision_end|>"
1377
+ f"{question}<|im_end|>\n"
1378
+ "<|im_start|>assistant\n"
1379
+ )
1380
+ for question in questions
1381
+ ]
1382
1383
return ModelRequestData(
1384
engine_args=engine_args,
1385
prompts=prompts,
1356
- stop_token_ids=stop_token_ids,
1386
)
1387
1388
@@ -1373,9 +1402,9 @@ model_example_map = {
1402
"idefics3": run_idefics3,
1403
"interns1": run_interns1,
1404
"internvl_chat": run_internvl,
1376
- "nemotron_vl": run_nemotron_vl,
1405
"keye_vl": run_keye_vl,
1406
"kimi_vl": run_kimi_vl,
1407
+ "llama4": run_llama4,
1408
"llava": run_llava,
1409
"llava-next": run_llava_next,
1410
"llava-next-video": run_llava_next_video,
@@ -1385,8 +1414,8 @@ model_example_map = {
1414
"minicpmv": run_minicpmv,
1415
"mistral3": run_mistral3,
1416
"mllama": run_mllama,
1388
- "llama4": run_llama4,
1417
"molmo": run_molmo,
1418
+ "nemotron_vl": run_nemotron_vl,
1419
"NVLM_D": run_nvlm_d,
1420
"ovis": run_ovis,
1421
"paligemma": run_paligemma,
@@ -1401,6 +1430,7 @@ model_example_map = {
1430
"qwen2_5_omni": run_qwen2_5_omni,
1431
"skywork_chat": run_skyworkr1v,
1432
"smolvlm": run_smolvlm,
1433
+ "step3": run_step3,
1434
"tarsier": run_tarsier,
1435
"tarsier2": run_tarsier2,
1436
}
examples/offline_inference/vision_language_multi_image.py
+113
-84
@@ -197,36 +197,55 @@ def load_h2ovl(question: str, image_urls: list[str]) -> ModelRequestData:
197
)
198
199
200
-def load_idefics3(question: str, image_urls: list[str]) -> ModelRequestData:
201
- model_name = "HuggingFaceM4/Idefics3-8B-Llama3"
200
+def load_hyperclovax_seed_vision(
201
+ question: str, image_urls: list[str]
202
+) -> ModelRequestData:
203
+ model_name = "naver-hyperclovax/HyperCLOVAX-SEED-Vision-Instruct-3B"
204
+ tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
205
203
- # The configuration below has been confirmed to launch on a single L40 GPU.
206
engine_args = EngineArgs(
207
model=model_name,
206
- max_model_len=8192,
207
- max_num_seqs=16,
208
- enforce_eager=True,
208
+ trust_remote_code=True,
209
+ max_model_len=16384,
210
limit_mm_per_prompt={"image": len(image_urls)},
210
- # if you are running out of memory, you can reduce the "longest_edge".
211
- # see: https://huggingface.co/HuggingFaceM4/Idefics3-8B-Llama3#model-optimizations
212
- mm_processor_kwargs={
213
- "size": {"longest_edge": 2 * 364},
214
- },
211
)
212
217
- placeholders = "\n".join(
218
- f"Image-{i}: <image>\n" for i, _ in enumerate(image_urls, start=1)
213
+ message = {"role": "user", "content": list()}
214
+ for _image_url in image_urls:
215
+ message["content"].append(
216
+ {
217
+ "type": "image",
218
+ "image": _image_url,
219
+ "ocr": "",
220
+ "lens_keywords": "",
221
+ "lens_local_keywords": "",
222
+ }
223
+ )
224
+ message["content"].append(
225
+ {
226
+ "type": "text",
227
+ "text": question,
228
+ }
229
)
220
- prompt = f"<|begin_of_text|>User:{placeholders}\n{question}<end_of_utterance>\nAssistant:" # noqa: E501
230
+
231
+ prompt = tokenizer.apply_chat_template(
232
+ [
233
+ message,
234
+ ],
235
+ tokenize=False,
236
+ add_generation_prompt=True,
237
+ )
238
+
239
return ModelRequestData(
240
engine_args=engine_args,
241
prompt=prompt,
242
+ stop_token_ids=None,
243
image_data=[fetch_image(url) for url in image_urls],
244
)
245
246
228
-def load_smolvlm(question: str, image_urls: list[str]) -> ModelRequestData:
229
- model_name = "HuggingFaceTB/SmolVLM2-2.2B-Instruct"
247
+def load_idefics3(question: str, image_urls: list[str]) -> ModelRequestData:
248
+ model_name = "HuggingFaceM4/Idefics3-8B-Llama3"
249
250
# The configuration below has been confirmed to launch on a single L40 GPU.
251
engine_args = EngineArgs(
@@ -235,17 +254,17 @@ def load_smolvlm(question: str, image_urls: list[str]) -> ModelRequestData:
254
max_num_seqs=16,
255
enforce_eager=True,
256
limit_mm_per_prompt={"image": len(image_urls)},
257
+ # if you are running out of memory, you can reduce the "longest_edge".
258
+ # see: https://huggingface.co/HuggingFaceM4/Idefics3-8B-Llama3#model-optimizations
259
mm_processor_kwargs={
239
- "max_image_size": {"longest_edge": 384},
260
+ "size": {"longest_edge": 2 * 364},
261
},
262
)
263
264
placeholders = "\n".join(
265
f"Image-{i}: <image>\n" for i, _ in enumerate(image_urls, start=1)
266
)
246
- prompt = (
247
- f"<|im_start|>User:{placeholders}\n{question}<end_of_utterance>\nAssistant:" # noqa: E501
248
- )
267
+ prompt = f"<|begin_of_text|>User:{placeholders}\n{question}<end_of_utterance>\nAssistant:" # noqa: E501
268
return ModelRequestData(
269
engine_args=engine_args,
270
prompt=prompt,
@@ -316,60 +335,13 @@ def load_internvl(question: str, image_urls: list[str]) -> ModelRequestData:
335
)
336
337
319
-def load_hyperclovax_seed_vision(
320
- question: str, image_urls: list[str]
321
-) -> ModelRequestData:
322
- model_name = "naver-hyperclovax/HyperCLOVAX-SEED-Vision-Instruct-3B"
323
- tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
324
-
325
- engine_args = EngineArgs(
326
- model=model_name,
327
- trust_remote_code=True,
328
- max_model_len=16384,
329
- limit_mm_per_prompt={"image": len(image_urls)},
330
- )
331
-
332
- message = {"role": "user", "content": list()}
333
- for _image_url in image_urls:
334
- message["content"].append(
335
- {
336
- "type": "image",
337
- "image": _image_url,
338
- "ocr": "",
339
- "lens_keywords": "",
340
- "lens_local_keywords": "",
341
- }
342
- )
343
- message["content"].append(
344
- {
345
- "type": "text",
346
- "text": question,
347
- }
348
- )
349
-
350
- prompt = tokenizer.apply_chat_template(
351
- [
352
- message,
353
- ],
354
- tokenize=False,
355
- add_generation_prompt=True,
356
- )
357
-
358
- return ModelRequestData(
359
- engine_args=engine_args,
360
- prompt=prompt,
361
- stop_token_ids=None,
362
- image_data=[fetch_image(url) for url in image_urls],
363
- )
364
-
338
+def load_llama4(question: str, image_urls: list[str]) -> ModelRequestData:
339
+ model_name = "meta-llama/Llama-4-Scout-17B-16E-Instruct"
340
366
-def load_llava(question: str, image_urls: list[str]) -> ModelRequestData:
367
- # NOTE: CAUTION! Original Llava models wasn't really trained on multi-image inputs,
368
- # it will generate poor response for multi-image inputs!
369
- model_name = "llava-hf/llava-1.5-7b-hf"
341
engine_args = EngineArgs(
342
model=model_name,
372
- max_num_seqs=16,
343
+ max_model_len=131072,
344
+ tensor_parallel_size=8,
345
limit_mm_per_prompt={"image": len(image_urls)},
346
)
347
@@ -397,11 +369,12 @@ def load_llava(question: str, image_urls: list[str]) -> ModelRequestData:
369
)
370
371
400
-def load_llava_next(question: str, image_urls: list[str]) -> ModelRequestData:
401
- model_name = "llava-hf/llava-v1.6-mistral-7b-hf"
372
+def load_llava(question: str, image_urls: list[str]) -> ModelRequestData:
373
+ # NOTE: CAUTION! Original Llava models wasn't really trained on multi-image inputs,
374
+ # it will generate poor response for multi-image inputs!
375
+ model_name = "llava-hf/llava-1.5-7b-hf"
376
engine_args = EngineArgs(
377
model=model_name,
404
- max_model_len=8192,
378
max_num_seqs=16,
379
limit_mm_per_prompt={"image": len(image_urls)},
380
)
@@ -430,11 +403,11 @@ def load_llava_next(question: str, image_urls: list[str]) -> ModelRequestData:
403
)
404
405
433
-def load_llava_onevision(question: str, image_urls: list[str]) -> ModelRequestData:
434
- model_name = "llava-hf/llava-onevision-qwen2-7b-ov-hf"
406
+def load_llava_next(question: str, image_urls: list[str]) -> ModelRequestData:
407
+ model_name = "llava-hf/llava-v1.6-mistral-7b-hf"
408
engine_args = EngineArgs(
409
model=model_name,
437
- max_model_len=16384,
410
+ max_model_len=8192,
411
max_num_seqs=16,
412
limit_mm_per_prompt={"image": len(image_urls)},
413
)
@@ -463,13 +436,12 @@ def load_llava_onevision(question: str, image_urls: list[str]) -> ModelRequestDa
436
)
437
438
466
-def load_llama4(question: str, image_urls: list[str]) -> ModelRequestData:
467
- model_name = "meta-llama/Llama-4-Scout-17B-16E-Instruct"
468
-
439
+def load_llava_onevision(question: str, image_urls: list[str]) -> ModelRequestData:
440
+ model_name = "llava-hf/llava-onevision-qwen2-7b-ov-hf"
441
engine_args = EngineArgs(
442
model=model_name,
471
- max_model_len=131072,
472
- tensor_parallel_size=8,
443
+ max_model_len=16384,
444
+ max_num_seqs=16,
445
limit_mm_per_prompt={"image": len(image_urls)},
446
)
447
@@ -954,6 +926,62 @@ def load_qwen2_5_vl(question: str, image_urls: list[str]) -> ModelRequestData:
926
)
927
928
929
+def load_smolvlm(question: str, image_urls: list[str]) -> ModelRequestData:
930
+ model_name = "HuggingFaceTB/SmolVLM2-2.2B-Instruct"
931
+
932
+ # The configuration below has been confirmed to launch on a single L40 GPU.
933
+ engine_args = EngineArgs(
934
+ model=model_name,
935
+ max_model_len=8192,
936
+ max_num_seqs=16,
937
+ enforce_eager=True,
938
+ limit_mm_per_prompt={"image": len(image_urls)},
939
+ mm_processor_kwargs={
940
+ "max_image_size": {"longest_edge": 384},
941
+ },
942
+ )
943
+
944
+ placeholders = "\n".join(
945
+ f"Image-{i}: <image>\n" for i, _ in enumerate(image_urls, start=1)
946
+ )
947
+ prompt = (
948
+ f"<|im_start|>User:{placeholders}\n{question}<end_of_utterance>\nAssistant:" # noqa: E501
949
+ )
950
+ return ModelRequestData(
951
+ engine_args=engine_args,
952
+ prompt=prompt,
953
+ image_data=[fetch_image(url) for url in image_urls],
954
+ )
955
+
956
+
957
+def load_step3(question: str, image_urls: list[str]) -> ModelRequestData:
958
+ model_name = "stepfun-ai/step3-fp8"
959
+
960
+ # NOTE: Below are verified configurations for step3-fp8
961
+ # on 8xH100 GPUs.
962
+ engine_args = EngineArgs(
963
+ model=model_name,
964
+ max_num_batched_tokens=4096,
965
+ gpu_memory_utilization=0.85,
966
+ tensor_parallel_size=8,
967
+ limit_mm_per_prompt={"image": len(image_urls)},
968
+ reasoning_parser="step3",
969
+ )
970
+
971
+ prompt = (
972
+ "<|begin▁of▁sentence|> You are a helpful assistant. <|BOT|>user\n "
973
+ f"{'<im_patch>' * len(image_urls)}{question} <|EOT|><|BOT|"
974
+ ">assistant\n<think>\n"
975
+ )
976
+ image_data = [fetch_image(url) for url in image_urls]
977
+
978
+ return ModelRequestData(
979
+ engine_args=engine_args,
980
+ prompt=prompt,
981
+ image_data=image_data,
982
+ )
983
+
984
+
985
def load_tarsier(question: str, image_urls: list[str]) -> ModelRequestData:
986
model_name = "omni-research/Tarsier-7b"
987
@@ -1006,16 +1034,16 @@ model_example_map = {
1034
"deepseek_vl_v2": load_deepseek_vl2,
1035
"gemma3": load_gemma3,
1036
"h2ovl_chat": load_h2ovl,
1037
+ "hyperclovax_seed_vision": load_hyperclovax_seed_vision,
1038
"idefics3": load_idefics3,
1039
"interns1": load_interns1,
1040
"internvl_chat": load_internvl,
1012
- "hyperclovax_seed_vision": load_hyperclovax_seed_vision,
1041
"keye_vl": load_keye_vl,
1042
"kimi_vl": load_kimi_vl,
1043
+ "llama4": load_llama4,
1044
"llava": load_llava,
1045
"llava-next": load_llava_next,
1046
"llava-onevision": load_llava_onevision,
1018
- "llama4": load_llama4,
1047
"mistral3": load_mistral3,
1048
"mllama": load_mllama,
1049
"NVLM_D": load_nvlm_d,
@@ -1028,6 +1056,7 @@ model_example_map = {
1056
"qwen2_vl": load_qwen2_vl,
1057
"qwen2_5_vl": load_qwen2_5_vl,
1058
"smolvlm": load_smolvlm,
1059
+ "step3": load_step3,
1060
"tarsier": load_tarsier,
1061
"tarsier2": load_tarsier2,
1062
}