Radi Akbar commited on
Commit
f82937a
·
1 Parent(s): 40ed325

New generate function

Browse files
Files changed (1) hide show
  1. 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
- from warnings import warn
 
18
  from transformers import GenerationConfig, LogitsProcessorList, StoppingCriteriaList
19
  from transformers.generation.utils import (
20
- GenerationMixin,
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 generate(
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
- warn("assisted generate requires `use_cache=True`. It has been set automatically.")
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
- warn("assisted generate is not supported with Static cache classes`. Chagned `cache_implementation` to `dynamic`")
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