main
py 80 lines 3.24 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """Unit tests for the token-offsets request/response protocol wiring:
4 the request flag flowing into ``TokenizeParams`` and the ``GenerateRequest``
5 serialization boundary. End-to-end behavior is covered by
6 ``tests/entrypoints/scale_out/render/test_render.py``; plain Pydantic field
7 storage is not retested here.
8 """
9
10 from unittest.mock import Mock
11
12 from vllm.config import ModelConfig
13 from vllm.entrypoints.openai.chat_completion.protocol import ChatCompletionRequest
14 from vllm.entrypoints.openai.completion.protocol import CompletionRequest
15 from vllm.entrypoints.scale_out.token_in_token_out.protocol import GenerateRequest
16 from vllm.sampling_params import SamplingParams
17
18
19 def _model_config() -> Mock:
20 model_config = Mock(spec=ModelConfig)
21 model_config.max_model_len = 128
22 return model_config
23
24
25 def test_completion_flag_forwarded_to_tok_params():
26 """build_tok_params must forward return_token_offsets, defaulting to
27 False (zero behavioral change for existing callers) and coercing JSON
28 null to False via the bool() guard."""
29 cfg = _model_config()
30
31 default = CompletionRequest(model="m", prompt="hi")
32 assert default.build_tok_params(cfg).return_token_offsets is False
33
34 on = CompletionRequest(model="m", prompt="hi", return_token_offsets=True)
35 assert on.build_tok_params(cfg).return_token_offsets is True
36
37 null = CompletionRequest(model="m", prompt="hi", return_token_offsets=None)
38 assert null.build_tok_params(cfg).return_token_offsets is False
39
40
41 def test_chat_flag_forwarded_to_tok_params():
42 """Chat build_tok_params has its own (max_completion_tokens) branch, so
43 its return_token_offsets forwarding is verified independently."""
44 cfg = _model_config()
45 messages = [{"role": "user", "content": "hi"}]
46
47 default = ChatCompletionRequest(model="m", messages=messages)
48 assert default.build_tok_params(cfg).return_token_offsets is False
49
50 on = ChatCompletionRequest(model="m", messages=messages, return_token_offsets=True)
51 assert on.build_tok_params(cfg).return_token_offsets is True
52
53 null = ChatCompletionRequest(
54 model="m", messages=messages, return_token_offsets=None
55 )
56 assert null.build_tok_params(cfg).return_token_offsets is False
57
58
59 def test_generate_request_token_offsets_default_none():
60 """Defaults to None so existing /v1/.../render responses are unchanged."""
61 req = GenerateRequest(token_ids=[1, 2, 3], sampling_params=SamplingParams())
62 assert req.token_offsets is None
63
64
65 def test_generate_request_token_offsets_survive_json_round_trip():
66 """GenerateRequest crosses the disagg serialization boundary; the
67 tuple[int, int] offsets must survive model_dump and re-validate."""
68 req = GenerateRequest(
69 token_ids=[10, 20],
70 sampling_params=SamplingParams(),
71 token_offsets=[(0, 1), (1, 3)],
72 )
73 dumped = req.model_dump()
74 assert dumped["token_offsets"] == [(0, 1), (1, 3)]
75 # Re-validate from the dumped dict (sampling_params doesn't round-trip
76 # cleanly via dump, so re-inject a fresh instance).
77 again = GenerateRequest.model_validate(
78 {**dumped, "sampling_params": SamplingParams()}
79 )
80 assert again.token_offsets == [(0, 1), (1, 3)]