[misc] Improve benchmark determinism and dataset API coverage (#33255)

This commit is contained in:
Liangsheng Yin
2026-08-02 01:39:50 -07:00
committed by GitHub
parent 06554515f4
commit 558c9bdcc2
6 changed files with 199 additions and 10 deletions
+4 -2
View File
@@ -67,11 +67,13 @@ def compute_random_lens(full_len: int, range_ratio: float, num: int) -> List[int
@lru_cache(maxsize=1)
def get_available_tokens(tokenizer):
"""Get valid token ids from the tokenizer vocabulary."""
return [
# Canonical order: vocab dict iteration order varies across tokenizers
# versions, which would break --seed reproducibility.
return sorted(
token_id
for token_id in tokenizer.get_vocab().values()
if isinstance(token_id, int)
]
)
def gen_prompt(tokenizer, token_num):
+8 -1
View File
@@ -1,4 +1,5 @@
import io
import random
import warnings
from argparse import Namespace
from dataclasses import dataclass
@@ -30,6 +31,7 @@ class ImageDataset(BaseDataset):
image_resolution: str
backend: str
random_image_count: bool
seed: int
@classmethod
def from_args(cls, args: Namespace) -> "ImageDataset":
@@ -44,10 +46,15 @@ class ImageDataset(BaseDataset):
image_resolution=args.image_resolution,
backend=args.backend,
random_image_count=args.random_image_count,
seed=args.seed,
)
def load(self, tokenizer=None, model_id=None) -> List[DatasetRow]:
processor = get_processor(model_id)
# Processor initialization may consume global RNG state. Reset it here so
# --seed fixes the generated prompts, image sizes, and image contents.
random.seed(self.seed)
np.random.seed(self.seed)
return sample_image_requests(
num_requests=self.num_requests,
image_count=self.image_count,
@@ -148,7 +155,7 @@ def create_mm_data_row(
prompt_str = f"<image>{text_prompt}"
# Calculate total tokens (text + vision)
if type(processor).__name__ == "KimiK25Processor":
if type(processor).__name__ in ("KimiK25Processor", "KimiK3Processor"):
medias = [{"type": "image", "image": img} for img in images]
prompt_len = processor(
text=prompt_str,
+15 -4
View File
@@ -1002,10 +1002,21 @@ def run_benchmark_internal(
"token_capacity", 1000000000
)
assert (
max_running_requests_per_dp > 0
), f"effective_max_running_requests_per_dp is not set, {max_running_requests_per_dp=}"
skip_max_running_requests_threshold = max_running_requests_per_dp * dp_size
# Router /get_server_info responses carry "router_manager"; worker
# responses never do, so its presence confirms a router by design.
if not internal_states and server_info.get("router_manager"):
print(
"WARNING: base_url points at a PD router; worker internal "
"states are unavailable, so the max-running-requests and "
"token-capacity skip guards are disabled."
)
skip_max_running_requests_threshold = float("inf")
skip_token_capacity_threshold = float("inf")
else:
assert (
max_running_requests_per_dp > 0
), f"effective_max_running_requests_per_dp is not set, {max_running_requests_per_dp=}"
skip_max_running_requests_threshold = max_running_requests_per_dp * dp_size
print(f"{max_running_requests_per_dp=}")
print(f"{dp_size=}")
+66 -2
View File
@@ -215,14 +215,78 @@ class ImageOpenAITestMixin(TestOpenAIMLLMServerBase):
with ThreadPoolExecutor(4) as executor:
list(executor.map(self.run_decode_with_image, image_ids))
def test_image_prefix_cache_reuse(self):
"""Image prefix (radix) cache correctness across requests.
Repeating an identical image must reuse the multimodal prefix without
changing the output, and a different image must NOT reuse the first
image's KV. This guards against image-token pad_value / feature-hash
regressions that would silently serve a cached *wrong* image's KV
(a correctness bug invisible to single-request tests). Pure greedy
request-level checks: no extra server flags, radix cache is on by
default.
"""
client = openai.Client(api_key=self.api_key, base_url=self.base_url)
def describe(url: str) -> str:
response = client.chat.completions.create(
model="default",
messages=[
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": url}},
{
"type": "text",
"text": "Describe this image in one sentence.",
},
],
},
],
temperature=0,
max_tokens=32,
**(self.get_vision_request_kwargs()),
)
assert response.usage.prompt_tokens > 0
content = response.choices[0].message.content
assert isinstance(content, str) and content
return content
# miss -> compute, then hit -> reuse the identical image's prefix
first = describe(IMAGE_MAN_IRONING_URL)
repeat = describe(IMAGE_MAN_IRONING_URL)
# a different image must be computed on its own, not reuse `first`'s KV
other = describe(IMAGE_SGL_LOGO_URL)
# the original image again, after a different one occupied the cache
first_again = describe(IMAGE_MAN_IRONING_URL)
self.assertEqual(
first,
repeat,
"Repeating an identical image changed the output; image prefix "
"reuse broke greedy determinism.",
)
self.assertEqual(
first,
first_again,
"The identical image after a different one changed the output; "
"image KV was cross-contaminated across requests.",
)
self.assertNotEqual(
first,
other,
"A different image produced an identical description; a wrong "
"image's KV may have been reused from the prefix cache.",
)
def verify_single_image_response(self, response):
assert response.choices[0].message.role == "assistant"
text = response.choices[0].message.content
assert isinstance(text, str)
# `driver` is for gemma-3-it
assert (
"man" in text or "person" or "driver" in text
assert any(
keyword in text for keyword in ("man", "person", "driver")
), f"text: {text}, should contain man, person or driver"
assert (
"cab" in text