Text Generation
Transformers
Safetensors
qwen3
custom_generate
conversational
text-generation-inference
Instructions to use radia/speculative-cascades with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use radia/speculative-cascades with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="radia/speculative-cascades") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("radia/speculative-cascades") model = AutoModelForCausalLM.from_pretrained("radia/speculative-cascades", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use radia/speculative-cascades with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "radia/speculative-cascades" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "radia/speculative-cascades", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/radia/speculative-cascades
- SGLang
How to use radia/speculative-cascades with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "radia/speculative-cascades" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "radia/speculative-cascades", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "radia/speculative-cascades" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "radia/speculative-cascades", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use radia/speculative-cascades with Docker Model Runner:
docker model run hf.co/radia/speculative-cascades
Radi Akbar commited on
Commit ·
f82937a
1
Parent(s): 40ed325
New generate function
Browse files- custom_generate/generate.py +303 -7
custom_generate/generate.py
CHANGED
|
@@ -14,21 +14,25 @@ In addition, I will modify this using my own method which is immaturely called s
|
|
| 14 |
import copy
|
| 15 |
import torch
|
| 16 |
import logging
|
| 17 |
-
|
|
|
|
| 18 |
from transformers import GenerationConfig, LogitsProcessorList, StoppingCriteriaList
|
| 19 |
from transformers.generation.utils import (
|
| 20 |
-
|
| 21 |
GenerateNonBeamOutput,
|
| 22 |
GenerateEncoderDecoderOutput,
|
| 23 |
GenerateDecoderOnlyOutput,
|
| 24 |
-
_split_model_outputs
|
| 25 |
)
|
|
|
|
| 26 |
from transformers.generation.candidate_generator import (
|
| 27 |
_prepare_attention_mask,
|
| 28 |
_prepare_token_type_ids,
|
| 29 |
)
|
| 30 |
from typing import Optional, Union
|
| 31 |
|
|
|
|
|
|
|
| 32 |
def _speculative_sampling(
|
| 33 |
candidate_input_ids,
|
| 34 |
candidate_logits,
|
|
@@ -123,7 +127,7 @@ def _speculative_sampling(
|
|
| 123 |
|
| 124 |
return valid_tokens, n_matches
|
| 125 |
|
| 126 |
-
def
|
| 127 |
model,
|
| 128 |
input_ids: torch.LongTensor,
|
| 129 |
logits_processor: LogitsProcessorList,
|
|
@@ -192,14 +196,14 @@ def generate(
|
|
| 192 |
# The cache must be dynamic for assisted generation, and the check must happen AFTER preparing cache
|
| 193 |
if not model_kwargs["use_cache"]:
|
| 194 |
model_kwargs["use_cache"] = True
|
| 195 |
-
|
| 196 |
if generation_config.cache_implementation in ["static", "hybrid", "sliding_window"] or (
|
| 197 |
"past_key_values" in model_kwargs
|
| 198 |
and hasattr(model_kwargs["past_key_values"], "layers")
|
| 199 |
and any(getattr(l, "is_compileable", False) for l in model_kwargs["past_key_values"].layers)
|
| 200 |
):
|
| 201 |
generation_config.cache_implementation = "dynamic"
|
| 202 |
-
|
| 203 |
# Get the candidate generator, given the parameterization
|
| 204 |
candidate_generator = model._get_candidate_generator(
|
| 205 |
generation_config=generation_config,
|
|
@@ -428,4 +432,296 @@ def generate(
|
|
| 428 |
past_key_values=model_kwargs.get("past_key_values"),
|
| 429 |
)
|
| 430 |
else:
|
| 431 |
-
return input_ids
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
import copy
|
| 15 |
import torch
|
| 16 |
import logging
|
| 17 |
+
import inspect
|
| 18 |
+
import warnings
|
| 19 |
from transformers import GenerationConfig, LogitsProcessorList, StoppingCriteriaList
|
| 20 |
from transformers.generation.utils import (
|
| 21 |
+
GenerateOutput,
|
| 22 |
GenerateNonBeamOutput,
|
| 23 |
GenerateEncoderDecoderOutput,
|
| 24 |
GenerateDecoderOnlyOutput,
|
| 25 |
+
_split_model_outputs,
|
| 26 |
)
|
| 27 |
+
import logging
|
| 28 |
from transformers.generation.candidate_generator import (
|
| 29 |
_prepare_attention_mask,
|
| 30 |
_prepare_token_type_ids,
|
| 31 |
)
|
| 32 |
from typing import Optional, Union
|
| 33 |
|
| 34 |
+
logger = logging.getLogger(__name__)
|
| 35 |
+
|
| 36 |
def _speculative_sampling(
|
| 37 |
candidate_input_ids,
|
| 38 |
candidate_logits,
|
|
|
|
| 127 |
|
| 128 |
return valid_tokens, n_matches
|
| 129 |
|
| 130 |
+
def _speculative_cascades(
|
| 131 |
model,
|
| 132 |
input_ids: torch.LongTensor,
|
| 133 |
logits_processor: LogitsProcessorList,
|
|
|
|
| 196 |
# The cache must be dynamic for assisted generation, and the check must happen AFTER preparing cache
|
| 197 |
if not model_kwargs["use_cache"]:
|
| 198 |
model_kwargs["use_cache"] = True
|
| 199 |
+
raise ValueError("assisted generate requires `use_cache=True`")
|
| 200 |
if generation_config.cache_implementation in ["static", "hybrid", "sliding_window"] or (
|
| 201 |
"past_key_values" in model_kwargs
|
| 202 |
and hasattr(model_kwargs["past_key_values"], "layers")
|
| 203 |
and any(getattr(l, "is_compileable", False) for l in model_kwargs["past_key_values"].layers)
|
| 204 |
):
|
| 205 |
generation_config.cache_implementation = "dynamic"
|
| 206 |
+
raise ValueError("assisted generate is not supported with Static cache classes`")
|
| 207 |
# Get the candidate generator, given the parameterization
|
| 208 |
candidate_generator = model._get_candidate_generator(
|
| 209 |
generation_config=generation_config,
|
|
|
|
| 432 |
past_key_values=model_kwargs.get("past_key_values"),
|
| 433 |
)
|
| 434 |
else:
|
| 435 |
+
return input_ids
|
| 436 |
+
|
| 437 |
+
@torch.no_grad()
|
| 438 |
+
def generate(
|
| 439 |
+
model,
|
| 440 |
+
inputs: torch.Tensor | None = None,
|
| 441 |
+
generation_config: GenerationConfig | None = None,
|
| 442 |
+
logits_processor: LogitsProcessorList | None = None,
|
| 443 |
+
stopping_criteria: StoppingCriteriaList | None = None,
|
| 444 |
+
prefix_allowed_tokens_fn: Callable[[int, torch.Tensor], list[int]] | None = None,
|
| 445 |
+
synced_gpus: bool | None = None,
|
| 446 |
+
assistant_model: Optional["PreTrainedModel"] = None,
|
| 447 |
+
streamer: Optional["BaseStreamer"] = None,
|
| 448 |
+
negative_prompt_ids: torch.Tensor | None = None,
|
| 449 |
+
negative_prompt_attention_mask: torch.Tensor | None = None,
|
| 450 |
+
**kwargs,
|
| 451 |
+
) -> Union[GenerateOutput, torch.LongTensor]:
|
| 452 |
+
r"""
|
| 453 |
+
|
| 454 |
+
Generates sequences of token ids for models with a language modeling head.
|
| 455 |
+
|
| 456 |
+
<Tip warning={true}>
|
| 457 |
+
|
| 458 |
+
Most generation-controlling parameters are set in `generation_config` which, if not passed, will be set to the
|
| 459 |
+
model's default generation configuration. You can override any `generation_config` by passing the corresponding
|
| 460 |
+
parameters to generate(), e.g. `.generate(inputs, num_beams=4, do_sample=True)`.
|
| 461 |
+
|
| 462 |
+
For an overview of generation strategies and code examples, check out the [following
|
| 463 |
+
guide](../generation_strategies).
|
| 464 |
+
|
| 465 |
+
</Tip>
|
| 466 |
+
|
| 467 |
+
Parameters:
|
| 468 |
+
inputs (`torch.Tensor` of varying shape depending on the modality, *optional*):
|
| 469 |
+
The sequence used as a prompt for the generation or as model inputs to the encoder. If `None` the
|
| 470 |
+
method initializes it with `bos_token_id` and a batch size of 1. For decoder-only models `inputs`
|
| 471 |
+
should be in the format of `input_ids`. For encoder-decoder models *inputs* can represent any of
|
| 472 |
+
`input_ids`, `input_values`, `input_features`, or `pixel_values`.
|
| 473 |
+
generation_config ([`~generation.GenerationConfig`], *optional*):
|
| 474 |
+
The generation configuration to be used as base parametrization for the generation call. `**kwargs`
|
| 475 |
+
passed to generate matching the attributes of `generation_config` will override them. If
|
| 476 |
+
`generation_config` is not provided, the default will be used, which has the following loading
|
| 477 |
+
priority: 1) from the `generation_config.json` model file, if it exists; 2) from the model
|
| 478 |
+
configuration. Please note that unspecified parameters will inherit [`~generation.GenerationConfig`]'s
|
| 479 |
+
default values, whose documentation should be checked to parameterize generation.
|
| 480 |
+
logits_processor (`LogitsProcessorList`, *optional*):
|
| 481 |
+
Custom logits processors that complement the default logits processors built from arguments and
|
| 482 |
+
generation config. If a logit processor is passed that is already created with the arguments or a
|
| 483 |
+
generation config an error is thrown. This feature is intended for advanced users.
|
| 484 |
+
stopping_criteria (`StoppingCriteriaList`, *optional*):
|
| 485 |
+
Custom stopping criteria that complements the default stopping criteria built from arguments and a
|
| 486 |
+
generation config. If a stopping criteria is passed that is already created with the arguments or a
|
| 487 |
+
generation config an error is thrown. If your stopping criteria depends on the `scores` input, make
|
| 488 |
+
sure you pass `return_dict_in_generate=True, output_scores=True` to `generate`. This feature is
|
| 489 |
+
intended for advanced users.
|
| 490 |
+
prefix_allowed_tokens_fn (`Callable[[int, torch.Tensor], list[int]]`, *optional*):
|
| 491 |
+
If provided, this function constraints the beam search to allowed tokens only at each step. If not
|
| 492 |
+
provided no constraint is applied. This function takes 2 arguments: the batch ID `batch_id` and
|
| 493 |
+
`input_ids`. It has to return a list with the allowed tokens for the next generation step conditioned
|
| 494 |
+
on the batch ID `batch_id` and the previously generated tokens `inputs_ids`. This argument is useful
|
| 495 |
+
for constrained generation conditioned on the prefix, as described in [Autoregressive Entity
|
| 496 |
+
Retrieval](https://huggingface.co/papers/2010.00904).
|
| 497 |
+
synced_gpus (`bool`, *optional*):
|
| 498 |
+
Whether to continue running the while loop until max_length. Unless overridden, this flag will be set
|
| 499 |
+
to `True` if using `FullyShardedDataParallel` or DeepSpeed ZeRO Stage 3 with multiple GPUs to avoid
|
| 500 |
+
deadlocking if one GPU finishes generating before other GPUs. Otherwise, defaults to `False`.
|
| 501 |
+
assistant_model (`PreTrainedModel`, *optional*):
|
| 502 |
+
An assistant model that can be used to accelerate generation. The assistant model must have the exact
|
| 503 |
+
same tokenizer. The acceleration is achieved when forecasting candidate tokens with the assistant model
|
| 504 |
+
is much faster than running generation with the model you're calling generate from. As such, the
|
| 505 |
+
assistant model should be much smaller.
|
| 506 |
+
streamer (`BaseStreamer`, *optional*):
|
| 507 |
+
Streamer object that will be used to stream the generated sequences. Generated tokens are passed
|
| 508 |
+
through `streamer.put(token_ids)` and the streamer is responsible for any further processing.
|
| 509 |
+
negative_prompt_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 510 |
+
The negative prompt needed for some processors such as CFG. The batch size must match the input batch
|
| 511 |
+
size. This is an experimental feature, subject to breaking API changes in future versions.
|
| 512 |
+
negative_prompt_attention_mask (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
|
| 513 |
+
Attention_mask for `negative_prompt_ids`.
|
| 514 |
+
custom_generate (`str` or `Callable`, *optional*):
|
| 515 |
+
One of the following:
|
| 516 |
+
- `str` (Hugging Face Hub repository name): runs the custom `generate` function defined at
|
| 517 |
+
`custom_generate/generate.py` in that repository instead of the standard `generate` method. The
|
| 518 |
+
repository fully replaces the generation logic, and the return type may differ.
|
| 519 |
+
- `str` (local repository path): same as above but from a local path, `trust_remote_code` not required.
|
| 520 |
+
- `Callable`: `generate` will perform the usual input preparation steps, then call the provided callable to
|
| 521 |
+
run the decoding loop.
|
| 522 |
+
For more information, see [the docs](../../generation_strategies#custom-generation-methods).
|
| 523 |
+
kwargs (`dict[str, Any]`, *optional*):
|
| 524 |
+
Ad hoc parametrization of `generation_config` and/or additional model-specific kwargs that will be
|
| 525 |
+
forwarded to the `forward` function of the model. If the model is an encoder-decoder model, encoder
|
| 526 |
+
specific kwargs should not be prefixed and decoder specific kwargs should be prefixed with *decoder_*.
|
| 527 |
+
|
| 528 |
+
Return:
|
| 529 |
+
[`~utils.ModelOutput`] or `torch.LongTensor`: A [`~utils.ModelOutput`] (if `return_dict_in_generate=True`
|
| 530 |
+
or when `config.return_dict_in_generate=True`) or a `torch.LongTensor`.
|
| 531 |
+
|
| 532 |
+
If the model is *not* an encoder-decoder model (`model.config.is_encoder_decoder=False`), the possible
|
| 533 |
+
[`~utils.ModelOutput`] types are:
|
| 534 |
+
|
| 535 |
+
- [`~generation.GenerateDecoderOnlyOutput`],
|
| 536 |
+
- [`~generation.GenerateBeamDecoderOnlyOutput`]
|
| 537 |
+
|
| 538 |
+
If the model is an encoder-decoder model (`model.config.is_encoder_decoder=True`), the possible
|
| 539 |
+
[`~utils.ModelOutput`] types are:
|
| 540 |
+
|
| 541 |
+
- [`~generation.GenerateEncoderDecoderOutput`],
|
| 542 |
+
- [`~generation.GenerateBeamEncoderDecoderOutput`]
|
| 543 |
+
"""
|
| 544 |
+
# 1. Handle kwargs, `generation_config`, validate them and obtain generation mode
|
| 545 |
+
generation_mode_kwargs = model._extract_generation_mode_kwargs(
|
| 546 |
+
None,
|
| 547 |
+
kwargs,
|
| 548 |
+
synced_gpus,
|
| 549 |
+
assistant_model,
|
| 550 |
+
streamer,
|
| 551 |
+
)
|
| 552 |
+
|
| 553 |
+
# Check length values before updating the config with defaults. We'll use it later to define the final min/max length (# 6)
|
| 554 |
+
has_default_max_length = kwargs.get("max_length") is None and (
|
| 555 |
+
generation_config is None or generation_config.max_length is None
|
| 556 |
+
)
|
| 557 |
+
has_default_min_length = kwargs.get("min_length") is None and (
|
| 558 |
+
generation_config is None or generation_config.min_length is None
|
| 559 |
+
)
|
| 560 |
+
generation_config, model_kwargs = model._prepare_generation_config(generation_config, **kwargs)
|
| 561 |
+
|
| 562 |
+
generation_mode = generation_config.get_generation_mode(assistant_model)
|
| 563 |
+
decoding_method = _speculative_cascades
|
| 564 |
+
|
| 565 |
+
model._validate_model_kwargs(model_kwargs.copy())
|
| 566 |
+
model._validate_generation_mode(generation_mode, generation_config, generation_mode_kwargs)
|
| 567 |
+
|
| 568 |
+
# 2. Set generation parameters if not already defined
|
| 569 |
+
logits_processor = logits_processor if logits_processor is not None else LogitsProcessorList()
|
| 570 |
+
stopping_criteria = stopping_criteria if stopping_criteria is not None else StoppingCriteriaList()
|
| 571 |
+
|
| 572 |
+
accepts_attention_mask = "attention_mask" in set(inspect.signature(model.forward).parameters.keys())
|
| 573 |
+
requires_attention_mask = "encoder_outputs" not in model_kwargs
|
| 574 |
+
kwargs_has_attention_mask = model_kwargs.get("attention_mask", None) is not None
|
| 575 |
+
|
| 576 |
+
# 3. Define model inputs
|
| 577 |
+
inputs_tensor, model_input_name, model_kwargs = model._prepare_model_inputs(
|
| 578 |
+
inputs, generation_config.bos_token_id, model_kwargs
|
| 579 |
+
)
|
| 580 |
+
# Some generation modes (e.g. assisted) need `inputs_tensor` to rerun encoder.forward()
|
| 581 |
+
if "inputs_tensor" in inspect.signature(decoding_method).parameters.keys():
|
| 582 |
+
generation_mode_kwargs["inputs_tensor"] = inputs_tensor
|
| 583 |
+
batch_size = inputs_tensor.shape[0]
|
| 584 |
+
|
| 585 |
+
device = inputs_tensor.device
|
| 586 |
+
model._prepare_special_tokens(generation_config, kwargs_has_attention_mask, device=device)
|
| 587 |
+
|
| 588 |
+
# decoder-only models must use left-padding for batched generation.
|
| 589 |
+
if not model.config.is_encoder_decoder:
|
| 590 |
+
# If `input_ids` was given, check if the last id in any sequence is `pad_token_id`
|
| 591 |
+
# Note: If using, `inputs_embeds` this check does not work, because we want to be more hands-off.
|
| 592 |
+
if (
|
| 593 |
+
generation_config._pad_token_tensor is not None
|
| 594 |
+
and batch_size > 1
|
| 595 |
+
and len(inputs_tensor.shape) == 2
|
| 596 |
+
and torch.sum(inputs_tensor[:, -1] == generation_config._pad_token_tensor) > 0
|
| 597 |
+
):
|
| 598 |
+
logger.warning(
|
| 599 |
+
"A decoder-only architecture is being used, but right-padding was detected! For correct "
|
| 600 |
+
"generation results, please set `padding_side='left'` when initializing the tokenizer."
|
| 601 |
+
)
|
| 602 |
+
|
| 603 |
+
# 4. Define other model kwargs
|
| 604 |
+
# decoder-only models with inputs_embeds forwarding must use caching (otherwise we can't detect whether we are
|
| 605 |
+
# generating the first new token or not, and we only want to use the embeddings for the first new token)
|
| 606 |
+
if not model.config.is_encoder_decoder and model_input_name == "inputs_embeds":
|
| 607 |
+
generation_config.use_cache = True
|
| 608 |
+
|
| 609 |
+
if not kwargs_has_attention_mask and requires_attention_mask and accepts_attention_mask:
|
| 610 |
+
model_kwargs["attention_mask"] = model._prepare_attention_mask_for_generation(
|
| 611 |
+
inputs_tensor, generation_config, model_kwargs
|
| 612 |
+
)
|
| 613 |
+
elif kwargs_has_attention_mask:
|
| 614 |
+
# TODO (joao): generalize this check with other types of inputs
|
| 615 |
+
if model_input_name == "input_ids" and len(model_kwargs["attention_mask"].shape) > 2:
|
| 616 |
+
raise ValueError("`attention_mask` passed to `generate` must be 2D.")
|
| 617 |
+
|
| 618 |
+
if model.config.is_encoder_decoder and "encoder_outputs" not in model_kwargs:
|
| 619 |
+
# if model is encoder decoder encoder_outputs are created and added to `model_kwargs`
|
| 620 |
+
model_kwargs = model._prepare_encoder_decoder_kwargs_for_generation(
|
| 621 |
+
inputs_tensor, model_kwargs, model_input_name, generation_config
|
| 622 |
+
)
|
| 623 |
+
|
| 624 |
+
# 5. Prepare `input_ids` which will be used for auto-regressive generation
|
| 625 |
+
if model.config.is_encoder_decoder:
|
| 626 |
+
input_ids, model_kwargs = model._prepare_decoder_input_ids_for_generation(
|
| 627 |
+
batch_size=batch_size,
|
| 628 |
+
model_input_name=model_input_name,
|
| 629 |
+
model_kwargs=model_kwargs,
|
| 630 |
+
decoder_start_token_id=generation_config._decoder_start_token_tensor,
|
| 631 |
+
device=inputs_tensor.device,
|
| 632 |
+
)
|
| 633 |
+
else:
|
| 634 |
+
input_ids = inputs_tensor if model_input_name == "input_ids" else model_kwargs.pop("input_ids")
|
| 635 |
+
|
| 636 |
+
# Expand inputs depending on the generation mode
|
| 637 |
+
input_ids, model_kwargs = model._expand_inputs_for_generation(
|
| 638 |
+
input_ids=input_ids,
|
| 639 |
+
expand_size=max(generation_config.num_beams, generation_config.num_return_sequences),
|
| 640 |
+
is_encoder_decoder=model.config.is_encoder_decoder,
|
| 641 |
+
**model_kwargs,
|
| 642 |
+
)
|
| 643 |
+
|
| 644 |
+
if generation_config.token_healing:
|
| 645 |
+
input_ids = model.heal_tokens(input_ids, generation_mode_kwargs.get("tokenizer"))
|
| 646 |
+
|
| 647 |
+
if streamer is not None:
|
| 648 |
+
streamer.put(input_ids.cpu())
|
| 649 |
+
|
| 650 |
+
# 6. Prepare `max_length` depending on other stopping criteria.
|
| 651 |
+
input_ids_length = input_ids.shape[1]
|
| 652 |
+
generation_config = model._prepare_generated_length(
|
| 653 |
+
generation_config=generation_config,
|
| 654 |
+
has_default_max_length=has_default_max_length,
|
| 655 |
+
has_default_min_length=has_default_min_length,
|
| 656 |
+
model_input_name=model_input_name,
|
| 657 |
+
inputs_tensor=inputs_tensor,
|
| 658 |
+
input_ids_length=input_ids_length,
|
| 659 |
+
)
|
| 660 |
+
|
| 661 |
+
# If the model supports `logits_to_keep` in forward(), set it to 1 to avoid computing the whole
|
| 662 |
+
# logit matrix. This can save a lot of memory during the first forward pass. Note that assisted decoding
|
| 663 |
+
# dynamically overrides this value as it can need more than the last token logits
|
| 664 |
+
if model._supports_logits_to_keep() and "logits_to_keep" not in model_kwargs:
|
| 665 |
+
model_kwargs["logits_to_keep"] = 1
|
| 666 |
+
|
| 667 |
+
model._validate_generated_length(generation_config, input_ids_length, has_default_max_length)
|
| 668 |
+
|
| 669 |
+
# 7. Prepare the cache.
|
| 670 |
+
# - `model_kwargs` may be updated in place with a cache as defined by the parameters in `generation_config`.
|
| 671 |
+
# - different models have a different cache name expected by the model (default = "past_key_values")
|
| 672 |
+
# - `max_length`, prepared above, is used to determine the maximum cache length
|
| 673 |
+
max_cache_length = generation_config.max_length - 1
|
| 674 |
+
if (
|
| 675 |
+
inputs_tensor.shape[1] != input_ids_length
|
| 676 |
+
and model_input_name == "inputs_embeds"
|
| 677 |
+
and not model.config.is_encoder_decoder
|
| 678 |
+
):
|
| 679 |
+
max_cache_length += inputs_tensor.shape[1]
|
| 680 |
+
model._prepare_cache_for_generation(
|
| 681 |
+
generation_config, model_kwargs, generation_mode, batch_size, max_cache_length
|
| 682 |
+
)
|
| 683 |
+
|
| 684 |
+
if model.device.type != input_ids.device.type:
|
| 685 |
+
warnings.warn(
|
| 686 |
+
"You are calling .generate() with the `input_ids` being on a device type different"
|
| 687 |
+
f" than your model's device. `input_ids` is on {input_ids.device.type}, whereas the model"
|
| 688 |
+
f" is on {model.device.type}. You may experience unexpected behaviors or slower generation."
|
| 689 |
+
" Please make sure that you have put `input_ids` to the"
|
| 690 |
+
f" correct device by calling for example input_ids = input_ids.to('{model.device.type}') before"
|
| 691 |
+
" running `.generate()`.",
|
| 692 |
+
UserWarning,
|
| 693 |
+
)
|
| 694 |
+
|
| 695 |
+
# 8. Prepare logits processors and stopping criteria
|
| 696 |
+
prepared_logits_processor = model._get_logits_processor(
|
| 697 |
+
generation_config=generation_config,
|
| 698 |
+
input_ids_seq_length=input_ids_length,
|
| 699 |
+
encoder_input_ids=inputs_tensor,
|
| 700 |
+
prefix_allowed_tokens_fn=prefix_allowed_tokens_fn,
|
| 701 |
+
logits_processor=logits_processor,
|
| 702 |
+
device=inputs_tensor.device,
|
| 703 |
+
model_kwargs=model_kwargs,
|
| 704 |
+
negative_prompt_ids=negative_prompt_ids,
|
| 705 |
+
negative_prompt_attention_mask=negative_prompt_attention_mask,
|
| 706 |
+
)
|
| 707 |
+
prepared_stopping_criteria = model._get_stopping_criteria(
|
| 708 |
+
generation_config=generation_config,
|
| 709 |
+
stopping_criteria=stopping_criteria,
|
| 710 |
+
tokenizer=generation_mode_kwargs.get("tokenizer"),
|
| 711 |
+
)
|
| 712 |
+
|
| 713 |
+
# Set model_kwargs `use_cache` so we can use it later in forward runs
|
| 714 |
+
model_kwargs["use_cache"] = generation_config.use_cache
|
| 715 |
+
|
| 716 |
+
# 9. Call generation mode
|
| 717 |
+
result = decoding_method(
|
| 718 |
+
model,
|
| 719 |
+
input_ids,
|
| 720 |
+
logits_processor=prepared_logits_processor,
|
| 721 |
+
stopping_criteria=prepared_stopping_criteria,
|
| 722 |
+
generation_config=generation_config,
|
| 723 |
+
**generation_mode_kwargs,
|
| 724 |
+
**model_kwargs,
|
| 725 |
+
)
|
| 726 |
+
|
| 727 |
+
return result
|