data.py 8.01 KB
Newer Older
1
2
from typing import (TYPE_CHECKING, Any, Dict, Generic, Iterable, List,
                    Optional, Tuple, Union)
3

4
from typing_extensions import NotRequired, TypedDict, TypeVar
5
6

if TYPE_CHECKING:
7
    from vllm.multimodal import MultiModalDataDict
8
9
10
11
12
13
14
15


class TextPrompt(TypedDict):
    """Schema for a text prompt."""

    prompt: str
    """The input text to be tokenized before passing to the model."""

16
    multi_modal_data: NotRequired["MultiModalDataDict"]
17
18
19
20
21
    """
    Optional multi-modal data to pass to the model,
    if the model supports it.
    """

22
23
24
25
26
27
28
29
    mm_processor_kwargs: NotRequired[Dict[str, Any]]
    """
    Optional multi-modal processor kwargs to be forwarded to the
    multimodal input mapper & processor. Note that if multiple modalities
    have registered mappers etc for the model being considered, we attempt
    to pass the mm_processor_kwargs to each of them.
    """

30
31
32
33
34
35
36

class TokensPrompt(TypedDict):
    """Schema for a tokenized prompt."""

    prompt_token_ids: List[int]
    """A list of token IDs to pass to the model."""

37
    multi_modal_data: NotRequired["MultiModalDataDict"]
38
39
40
41
42
    """
    Optional multi-modal data to pass to the model,
    if the model supports it.
    """

43
44
45
46
47
48
49
50
    mm_processor_kwargs: NotRequired[Dict[str, Any]]
    """
    Optional multi-modal processor kwargs to be forwarded to the
    multimodal input mapper & processor. Note that if multiple modalities
    have registered mappers etc for the model being considered, we attempt
    to pass the mm_processor_kwargs to each of them.
    """

51

52
SingletonPrompt = Union[str, TextPrompt, TokensPrompt]
53
"""
54
Set of possible schemas for a single LLM input:
55
56
57

- A text prompt (:class:`str` or :class:`TextPrompt`)
- A tokenized prompt (:class:`TokensPrompt`)
58
59
60
61
62

Note that "singleton" is as opposed to a data structure
which encapsulates multiple prompts, i.e. of the sort
which may be utilized for encoder/decoder models when
the user desires to express both the encoder & decoder
63
prompts explicitly, i.e. :class:`ExplicitEncoderDecoderPrompt`
64

65
A prompt of type :class:`SingletonPrompt` may be employed
66
67
68
69
as (1) input to a decoder-only model, (2) input to
the encoder of an encoder/decoder model, in the scenario
where the decoder-prompt is not specified explicitly, or
(3) as a member of a larger data structure encapsulating
70
more than one prompt, i.e. :class:`ExplicitEncoderDecoderPrompt`
71
72
"""

73
_T1_co = TypeVar("_T1_co",
74
75
                 bound=SingletonPrompt,
                 default=SingletonPrompt,
76
77
                 covariant=True)
_T2_co = TypeVar("_T2_co",
78
79
                 bound=SingletonPrompt,
                 default=SingletonPrompt,
80
                 covariant=True)
81

82
83
84

# TODO: Make fields ReadOnly once mypy supports it
class ExplicitEncoderDecoderPrompt(TypedDict, Generic[_T1_co, _T2_co]):
85
86
87
    """
    Represents an encoder/decoder model input prompt,
    comprising an explicit encoder prompt and a decoder prompt.
88

89
90
91
    The encoder and decoder prompts, respectively, may be formatted
    according to any of the :class:`SingletonPrompt` schemas,
    and are not required to have the same schema.
92

93
94
95
    Only the encoder prompt may have multi-modal data. mm_processor_kwargs
    should be at the top-level, and should not be set in the encoder/decoder
    prompts, since they are agnostic to the encoder/decoder.
96

97
    Note that an :class:`ExplicitEncoderDecoderPrompt` may not
98
    be used as an input to a decoder-only model,
99
    and that the :code:`encoder_prompt` and :code:`decoder_prompt`
100
    fields of this data structure themselves must be
101
    :class:`SingletonPrompt` instances.
102
103
    """

104
    encoder_prompt: _T1_co
105

106
    decoder_prompt: Optional[_T2_co]
107

108
109
    mm_processor_kwargs: NotRequired[Dict[str, Any]]

110

111
PromptType = Union[SingletonPrompt, ExplicitEncoderDecoderPrompt]
112
113
114
115
116
117
118
119
120
121
122
"""
Set of possible schemas for an LLM input, including
both decoder-only and encoder/decoder input types:

- A text prompt (:class:`str` or :class:`TextPrompt`)
- A tokenized prompt (:class:`TokensPrompt`)
- A single data structure containing both an encoder and a decoder prompt
  (:class:`ExplicitEncoderDecoderPrompt`)
"""


123
class LLMInputs(TypedDict):
124
125
126
    """
    The inputs in :class:`~vllm.LLMEngine` before they are
    passed to the model executor.
127
128

    This specifies the data required for decoder-only models.
129
    """
130
    prompt_token_ids: List[int]
131
132
    """The token IDs of the prompt."""

133
    prompt: NotRequired[Optional[str]]
134
135
136
137
    """
    The original prompt text corresponding to the token IDs, if available.
    """

138
139
140
141
142
143
    multi_modal_data: NotRequired[Optional["MultiModalDataDict"]]
    """
    Optional multi-modal data to pass to the model,
    if the model supports it.
    """

144
145
146
147
148
149
150
151
    mm_processor_kwargs: NotRequired[Optional[Dict[str, Any]]]
    """
    Optional multi-modal processor kwargs to be forwarded to the
    multimodal input mapper & processor. Note that if multiple modalities
    have registered mappers etc for the model being considered, we attempt
    to pass the mm_processor_kwargs to each of them.
    """

152
153
154
155
156
157
158
159
160

class EncoderDecoderLLMInputs(LLMInputs):
    """
    The inputs in :class:`~vllm.LLMEngine` before they are
    passed to the model executor.

    This specifies the required data for encoder-decoder models.
    """
    encoder_prompt_token_ids: List[int]
161
162
163
164
165
166
167
168
    """The token IDs of the encoder prompt."""

    encoder_prompt: NotRequired[Optional[str]]
    """
    The original encoder prompt text corresponding to the token IDs, if
    available.
    """

169
170
171
172
173
174
    encoder_multi_modal_data: NotRequired[Optional["MultiModalDataDict"]]
    """
    Optional multi-modal data to pass to the encoder model,
    if the model supports it.
    """

175

176
177
_T1 = TypeVar("_T1", bound=SingletonPrompt, default=SingletonPrompt)
_T2 = TypeVar("_T2", bound=SingletonPrompt, default=SingletonPrompt)
178
179


180
181
182
def build_explicit_enc_dec_prompt(
    encoder_prompt: _T1,
    decoder_prompt: Optional[_T2],
183
    mm_processor_kwargs: Optional[Dict[str, Any]] = None,
184
) -> ExplicitEncoderDecoderPrompt[_T1, _T2]:
185
186
187
188
189
190
    if mm_processor_kwargs is None:
        mm_processor_kwargs = {}
    return ExplicitEncoderDecoderPrompt(
        encoder_prompt=encoder_prompt,
        decoder_prompt=decoder_prompt,
        mm_processor_kwargs=mm_processor_kwargs)
191
192
193
194
195


def zip_enc_dec_prompts(
    enc_prompts: Iterable[_T1],
    dec_prompts: Iterable[Optional[_T2]],
196
197
    mm_processor_kwargs: Optional[Union[Iterable[Dict[str, Any]],
                                        Dict[str, Any]]] = None,
198
) -> List[ExplicitEncoderDecoderPrompt[_T1, _T2]]:
199
    """
200
    Zip encoder and decoder prompts together into a list of
201
202
203
204
205
206
207
208
209
210
211
212
213
214
    :class:`ExplicitEncoderDecoderPrompt` instances. mm_processor_kwargs
    may also be provided; if a dict is passed, the same dictionary will be
    used for every encoder/decoder prompt. If an iterable is provided, it will
    be zipped with the encoder/decoder prompts.
    """
    if mm_processor_kwargs is None:
        mm_processor_kwargs = {}
    if isinstance(mm_processor_kwargs, Dict):
        return [
            build_explicit_enc_dec_prompt(encoder_prompt, decoder_prompt,
                                          mm_processor_kwargs)
            for (encoder_prompt,
                 decoder_prompt) in zip(enc_prompts, dec_prompts)
        ]
215
    return [
216
217
218
219
        build_explicit_enc_dec_prompt(encoder_prompt, decoder_prompt,
                                      mm_proc_kwargs)
        for (encoder_prompt, decoder_prompt, mm_proc_kwargs
             ) in zip(enc_prompts, dec_prompts, mm_processor_kwargs)
220
221
    ]

222

223
224
225
226
227
228
def to_enc_dec_tuple_list(
    enc_dec_prompts: Iterable[ExplicitEncoderDecoderPrompt[_T1, _T2]],
) -> List[Tuple[_T1, Optional[_T2]]]:
    return [(enc_dec_prompt["encoder_prompt"],
             enc_dec_prompt["decoder_prompt"])
            for enc_dec_prompt in enc_dec_prompts]
229
230
231
232
233
234
235
236
237
238
239
240
241
242


def __getattr__(name: str):
    if name == "PromptInput":
        import warnings

        msg = ("PromptInput has been renamed to PromptType. "
               "The original name will be removed in an upcoming version.")

        warnings.warn(DeprecationWarning(msg), stacklevel=2)

        return PromptType

    raise AttributeError(f"module {__name__!r} has no attribute {name!r}")