fix: fix prefill-aware SWA floor tracking (#29520)
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
export const config = {
|
export const config = {
|
||||||
modelName: "Unlimited-OCR",
|
modelName: "Unlimited-OCR",
|
||||||
|
|
||||||
supportedHardware: ["h100", "h200", "b200", "b300", "gb200", "gb300"],
|
supportedHardware: ["h100"],
|
||||||
|
|
||||||
variants: [{ id: "default", label: "Default" }],
|
variants: [{ id: "default", label: "Default" }],
|
||||||
quantizations: [{ id: "default", label: "Default" }],
|
quantizations: [{ id: "default", label: "Default" }],
|
||||||
@@ -44,11 +44,6 @@ export const config = {
|
|||||||
|
|
||||||
dockerImages: {
|
dockerImages: {
|
||||||
h100: "lmsysorg/sglang:dev",
|
h100: "lmsysorg/sglang:dev",
|
||||||
h200: "lmsysorg/sglang:dev",
|
|
||||||
b200: "lmsysorg/sglang:dev",
|
|
||||||
b300: "lmsysorg/sglang:dev",
|
|
||||||
gb200: "lmsysorg/sglang:dev",
|
|
||||||
gb300: "lmsysorg/sglang:dev",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
github: {
|
github: {
|
||||||
@@ -72,106 +67,7 @@ export const config = {
|
|||||||
strategy: "balanced",
|
strategy: "balanced",
|
||||||
nodes: "single",
|
nodes: "single",
|
||||||
},
|
},
|
||||||
env: [],
|
verified: true,
|
||||||
flags: [
|
|
||||||
"--model-path {{MODEL_NAME}}",
|
|
||||||
"--attention-backend fa3",
|
|
||||||
"--page-size 1",
|
|
||||||
"--context-length 32768",
|
|
||||||
"--enable-custom-logit-processor",
|
|
||||||
"--disable-radix-cache",
|
|
||||||
"--host {{HOST_IP}}",
|
|
||||||
"--port {{PORT}}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
hw: "h200",
|
|
||||||
variant: "default",
|
|
||||||
quant: "default",
|
|
||||||
strategy: "balanced",
|
|
||||||
nodes: "single",
|
|
||||||
},
|
|
||||||
env: [],
|
|
||||||
flags: [
|
|
||||||
"--model-path {{MODEL_NAME}}",
|
|
||||||
"--attention-backend fa3",
|
|
||||||
"--page-size 1",
|
|
||||||
"--context-length 32768",
|
|
||||||
"--enable-custom-logit-processor",
|
|
||||||
"--disable-radix-cache",
|
|
||||||
"--host {{HOST_IP}}",
|
|
||||||
"--port {{PORT}}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
hw: "b200",
|
|
||||||
variant: "default",
|
|
||||||
quant: "default",
|
|
||||||
strategy: "balanced",
|
|
||||||
nodes: "single",
|
|
||||||
},
|
|
||||||
env: [],
|
|
||||||
flags: [
|
|
||||||
"--model-path {{MODEL_NAME}}",
|
|
||||||
"--attention-backend fa3",
|
|
||||||
"--page-size 1",
|
|
||||||
"--context-length 32768",
|
|
||||||
"--enable-custom-logit-processor",
|
|
||||||
"--disable-radix-cache",
|
|
||||||
"--host {{HOST_IP}}",
|
|
||||||
"--port {{PORT}}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
hw: "b300",
|
|
||||||
variant: "default",
|
|
||||||
quant: "default",
|
|
||||||
strategy: "balanced",
|
|
||||||
nodes: "single",
|
|
||||||
},
|
|
||||||
env: [],
|
|
||||||
flags: [
|
|
||||||
"--model-path {{MODEL_NAME}}",
|
|
||||||
"--attention-backend fa3",
|
|
||||||
"--page-size 1",
|
|
||||||
"--context-length 32768",
|
|
||||||
"--enable-custom-logit-processor",
|
|
||||||
"--disable-radix-cache",
|
|
||||||
"--host {{HOST_IP}}",
|
|
||||||
"--port {{PORT}}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
hw: "gb200",
|
|
||||||
variant: "default",
|
|
||||||
quant: "default",
|
|
||||||
strategy: "balanced",
|
|
||||||
nodes: "single",
|
|
||||||
},
|
|
||||||
env: [],
|
|
||||||
flags: [
|
|
||||||
"--model-path {{MODEL_NAME}}",
|
|
||||||
"--attention-backend fa3",
|
|
||||||
"--page-size 1",
|
|
||||||
"--context-length 32768",
|
|
||||||
"--enable-custom-logit-processor",
|
|
||||||
"--disable-radix-cache",
|
|
||||||
"--host {{HOST_IP}}",
|
|
||||||
"--port {{PORT}}",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match: {
|
|
||||||
hw: "gb300",
|
|
||||||
variant: "default",
|
|
||||||
quant: "default",
|
|
||||||
strategy: "balanced",
|
|
||||||
nodes: "single",
|
|
||||||
},
|
|
||||||
env: [],
|
env: [],
|
||||||
flags: [
|
flags: [
|
||||||
"--model-path {{MODEL_NAME}}",
|
"--model-path {{MODEL_NAME}}",
|
||||||
|
|||||||
@@ -723,8 +723,8 @@ class Req(ReqDllmMixin):
|
|||||||
# that preserve length would silently corrupt fill_ids.
|
# that preserve length would silently corrupt fill_ids.
|
||||||
self.output_ids = array("q")
|
self.output_ids = array("q")
|
||||||
# Full untruncated sequence: origin + output (+ DLLM mask block).
|
# Full untruncated sequence: origin + output (+ DLLM mask block).
|
||||||
# Kept in sync by _refresh_fill_ids; admission only updates fill_len,
|
# Kept in sync by _refresh_fill_ids; admission only updates
|
||||||
# never mutates this array's length.
|
# extend_range, never mutates this array's length.
|
||||||
self.full_untruncated_fill_ids = array("q")
|
self.full_untruncated_fill_ids = array("q")
|
||||||
self.extend_range: Optional[Range] = None
|
self.extend_range: Optional[Range] = None
|
||||||
self.dllm_initialized: bool = False
|
self.dllm_initialized: bool = False
|
||||||
|
|||||||
@@ -2622,8 +2622,9 @@ class Scheduler(
|
|||||||
|
|
||||||
# Stash (cache) the previous chunk only when it produced new KV
|
# Stash (cache) the previous chunk only when it produced new KV
|
||||||
# beyond what is already cached. A parked chunk (add_chunked_req
|
# beyond what is already cached. A parked chunk (add_chunked_req
|
||||||
# hybrid-SWA early-return) leaves fill_len == len(prefix_indices),
|
# hybrid-SWA early-return) leaves extend_range.end ==
|
||||||
# so there is nothing new to cache and stashing would be a no-op.
|
# len(prefix_indices), so there is nothing new to cache and
|
||||||
|
# stashing would be a no-op.
|
||||||
if self.chunked_req.extend_range.end > len(self.chunked_req.prefix_indices):
|
if self.chunked_req.extend_range.end > len(self.chunked_req.prefix_indices):
|
||||||
self.stash_chunked_request(self.chunked_req)
|
self.stash_chunked_request(self.chunked_req)
|
||||||
|
|
||||||
@@ -2970,7 +2971,7 @@ class Scheduler(
|
|||||||
|
|
||||||
if self.tp_worker.model_runner.prefill_aware_swa:
|
if self.tp_worker.model_runner.prefill_aware_swa:
|
||||||
for req in can_run_list:
|
for req in can_run_list:
|
||||||
req.swa_evict_floor = req.fill_len
|
req.swa_evict_floor = req.extend_range.end
|
||||||
|
|
||||||
# Record prefill stats for logging after forward.
|
# Record prefill stats for logging after forward.
|
||||||
new_batch.prefill_stats = PrefillStats.from_adder(
|
new_batch.prefill_stats = PrefillStats.from_adder(
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import base64
|
||||||
|
import io
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import openai
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
from sglang.test.ci.ci_register import register_cuda_ci
|
||||||
|
from sglang.test.vlm_utils import TestOpenAIMLLMServerBase
|
||||||
|
|
||||||
|
register_cuda_ci(est_time=240, stage="base-b", runner_config="1-gpu-large")
|
||||||
|
|
||||||
|
|
||||||
|
class TestUnlimitedOCRServer(TestOpenAIMLLMServerBase):
|
||||||
|
model = "baidu/Unlimited-OCR"
|
||||||
|
trust_remote_code = False
|
||||||
|
extra_args = [
|
||||||
|
"--attention-backend=fa3",
|
||||||
|
"--page-size=1",
|
||||||
|
"--context-length=4096",
|
||||||
|
"--max-total-tokens=4096",
|
||||||
|
"--enable-custom-logit-processor",
|
||||||
|
"--disable-radix-cache",
|
||||||
|
"--cuda-graph-max-bs-decode=4",
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _font(size: int):
|
||||||
|
for path in (
|
||||||
|
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
||||||
|
"/usr/share/fonts/truetype/liberation2/LiberationSans-Regular.ttf",
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
return ImageFont.truetype(path, size=size)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
return ImageFont.load_default()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _make_ocr_image_url(cls) -> str:
|
||||||
|
img = Image.new("RGB", (640, 360), "white")
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
draw.rectangle((24, 24, 616, 336), outline="black", width=4)
|
||||||
|
draw.text((72, 92), "SGLang OCR", fill="black", font=cls._font(56))
|
||||||
|
draw.text((72, 180), "12345", fill="black", font=cls._font(72))
|
||||||
|
|
||||||
|
buffer = io.BytesIO()
|
||||||
|
img.save(buffer, format="PNG")
|
||||||
|
encoded = base64.b64encode(buffer.getvalue()).decode("ascii")
|
||||||
|
return f"data:image/png;base64,{encoded}"
|
||||||
|
|
||||||
|
def test_single_image_chat_completion(self):
|
||||||
|
client = openai.Client(api_key=self.api_key, base_url=self.base_url)
|
||||||
|
|
||||||
|
response = client.chat.completions.create(
|
||||||
|
model="default",
|
||||||
|
messages=[
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": [
|
||||||
|
{"type": "text", "text": "document parsing."},
|
||||||
|
{
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {"url": self._make_ocr_image_url()},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
temperature=0,
|
||||||
|
max_tokens=64,
|
||||||
|
extra_body={"images_config": {"image_mode": "gundam"}},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.choices[0].message.role, "assistant")
|
||||||
|
text = response.choices[0].message.content
|
||||||
|
self.assertIsInstance(text, str)
|
||||||
|
self.assertIn("12345", text)
|
||||||
|
self.assertIn("sglang", text.lower())
|
||||||
|
self.assertGreater(response.usage.prompt_tokens, 0)
|
||||||
|
self.assertGreater(response.usage.completion_tokens, 0)
|
||||||
|
self.assertGreater(response.usage.total_tokens, 0)
|
||||||
|
|
||||||
|
|
||||||
|
del TestOpenAIMLLMServerBase
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user