Files
2026-07-13 13:17:40 +08:00

127 lines
3.4 KiB
Python

import sys
import pytest
import ray
from ray.data.llm import SGLangEngineProcessorConfig, build_processor
def test_chat_template():
chat_template = """
{% if messages[0]['role'] == 'system' %}
{% set offset = 1 %}
{% else %}
{% set offset = 0 %}
{% endif %}
{{ bos_token }}
{% for message in messages %}
{% if (message['role'] == 'user') != (loop.index0 % 2 == offset) %}
{{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}
{% endif %}
{{ '<|im_start|>' + message['role'] + '\n' + message['content'] | trim + '<|im_end|>\n' }}
{% endfor %}
{% if add_generation_prompt %}
{{ '<|im_start|>assistant\n' }}
{% endif %}
"""
processor_config = SGLangEngineProcessorConfig(
model_source="unsloth/Llama-3.2-1B-Instruct",
engine_kwargs=dict(
context_length=2048,
disable_cuda_graph=True,
dtype="half",
),
batch_size=16,
concurrency=1,
chat_template_stage={"enabled": True, "chat_template": chat_template},
tokenize_stage=True,
detokenize_stage=True,
)
processor = build_processor(
processor_config,
preprocess=lambda row: dict(
messages=[
{"role": "system", "content": "You are a calculator"},
{"role": "user", "content": f"{row['id']} ** 3 = ?"},
],
sampling_params=dict(
temperature=0.3,
max_new_tokens=50, # SGLang uses max_new_tokens instead of max_tokens
),
),
postprocess=lambda row: {
"resp": row["generated_text"],
},
)
ds = ray.data.range(60)
ds = ds.map(lambda x: {"id": x["id"], "val": x["id"] + 5})
ds = processor(ds)
ds = ds.materialize()
outs = ds.take_all()
assert len(outs) == 60
assert all("resp" in out for out in outs)
@pytest.mark.parametrize(
"tp_size,dp_size,concurrency",
[
(2, 1, 2),
(2, 2, 1),
],
)
def test_sglang_llama_parallel(tp_size, dp_size, concurrency):
"""Test SGLang with Llama model using different parallelism configurations."""
runtime_env = {}
processor_config = SGLangEngineProcessorConfig(
model_source="unsloth/Llama-3.2-1B-Instruct",
engine_kwargs=dict(
context_length=2048,
tp_size=tp_size,
dp_size=dp_size,
dtype="half",
),
runtime_env=runtime_env,
tokenize_stage=True,
detokenize_stage=True,
batch_size=16,
concurrency=concurrency,
)
processor = build_processor(
processor_config,
preprocess=lambda row: dict(
messages=[
{"role": "system", "content": "You are a calculator"},
{"role": "user", "content": f"{row['id']} ** 3 = ?"},
],
sampling_params=dict(
temperature=0.3,
max_new_tokens=50,
),
),
postprocess=lambda row: {
"resp": row["generated_text"],
},
)
ds = ray.data.range(120)
ds = ds.map(lambda x: {"id": x["id"], "val": x["id"] + 5})
ds = processor(ds)
ds = ds.materialize()
# Verify results
outs = ds.take_all()
assert len(outs) == 120
assert all("resp" in out for out in outs)
if __name__ == "__main__":
sys.exit(pytest.main(["-v", __file__]))