main
py 142 lines 4.83 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 """This example demonstrates instantiating vLLM with a custom logits processor
5 class object.
6
7 For a basic example of implementing a custom logits processor, see
8 the `DummyLogitsProcessor` implementation in `vllm/test_utils.py`.
9
10 For testing purposes, a dummy logits processor is employed which, if
11 `target_token` is passed as a keyword argument to `SamplingParams.extra_args`,
12 will mask out all tokens except `target_token`.
13
14 A batch is constructed with `temperature=0.0` and 50% of requests specifying
15 `target_token`, and for these requests - and *only* these requests - we
16 expect the `target_token` to be decoded in each step, yielding an output
17 similar to that shown below:
18
19 Generated Outputs:
20 ------------------------------------------------------------
21 Prompt: 'Hello, my name is'
22 Output: " ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '"
23 ------------------------------------------------------------
24 Prompt: 'The president of the United States is'
25 Output: " not a racist. He is a racist.\nHe's a racist because he"
26 ------------------------------------------------------------
27 Prompt: 'The capital of France is'
28 Output: ' also also also also also also also also also also also also also
29 also also also'
30 ------------------------------------------------------------
31 Prompt: 'The future of AI is'
32 Output: ' in the hands of the people.\n\nThe future of AI is in the'
33 ------------------------------------------------------------
34 """
35
36 from typing import Any
37
38 import torch
39
40 from vllm import LLM, SamplingParams
41 from vllm.config import VllmConfig
42 from vllm.v1.sample.logits_processor import (
43 BatchUpdate,
44 LogitsProcessor,
45 )
46 from vllm.v1.sample.logits_processor.builtin import process_dict_updates
47
48
49 # Hypothetical custom logits processor
50 class DummyLogitsProcessor(LogitsProcessor):
51 """Fake logit processor to support unit testing and examples."""
52
53 @classmethod
54 def validate_params(cls, params: SamplingParams):
55 target_token: Any | None = params.extra_args and params.extra_args.get(
56 "target_token"
57 )
58 if target_token is not None and not isinstance(target_token, int):
59 raise ValueError(
60 f"target_token value {target_token} {type(target_token)} is not int"
61 )
62
63 def __init__(
64 self, vllm_config: VllmConfig, device: torch.device, is_pin_memory: bool
65 ):
66 self.req_info: dict[int, int] = {}
67
68 def is_argmax_invariant(self) -> bool:
69 return False
70
71 def update_state(self, batch_update: BatchUpdate | None):
72 def extract_extra_arg(params: SamplingParams) -> int | None:
73 self.validate_params(params)
74 return params.extra_args and params.extra_args.get("target_token")
75
76 process_dict_updates(
77 self.req_info,
78 batch_update,
79 # This function returns the LP's per-request state based on the
80 # request details, or None if this LP does not apply to the
81 # request.
82 lambda params, _, __: extract_extra_arg(params),
83 )
84
85 def apply(self, logits: torch.Tensor) -> torch.Tensor:
86 if not self.req_info:
87 return logits
88
89 # Save target values before modification
90 cols = torch.tensor(
91 list(self.req_info.values()), dtype=torch.long, device=logits.device
92 )
93 rows = torch.tensor(
94 list(self.req_info.keys()), dtype=torch.long, device=logits.device
95 )
96 values_to_keep = logits[rows, cols].clone()
97
98 # Mask all but target tokens
99 logits[rows] = float("-inf")
100 logits[rows, cols] = values_to_keep
101
102 return logits
103
104
105 # Sample prompts.
106 prompts = [
107 "Hello, my name is",
108 "The president of the United States is",
109 "The capital of France is",
110 "The future of AI is",
111 ]
112 # Create a mixture of requests which do and don't utilize the dummy logitproc
113 sampling_params_list = [
114 SamplingParams(temperature=0.0, extra_args={"target_token": 128}),
115 SamplingParams(temperature=0.0),
116 SamplingParams(temperature=0.0, extra_args={"target_token": 67}),
117 SamplingParams(temperature=0.0),
118 ]
119
120
121 def main():
122 # Create an LLM.
123 llm = LLM(
124 model="facebook/opt-125m",
125 logits_processors=[DummyLogitsProcessor],
126 )
127 # Generate texts from the prompts.
128 # The output is a list of RequestOutput objects
129 # that contain the prompt, generated text, and other information.
130 outputs = llm.generate(prompts, sampling_params_list)
131 # Print the outputs.
132 print("\nGenerated Outputs:\n" + "-" * 60)
133 for output in outputs:
134 prompt = output.prompt
135 generated_text = output.outputs[0].text
136 print(f"Prompt: {prompt!r}")
137 print(f"Output: {generated_text!r}")
138 print("-" * 60)
139
140
141 if __name__ == "__main__":
142 main()