stopping_criteria.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import time
  15. import warnings
  16. from abc import ABC
  17. from copy import deepcopy
  18. from typing import Optional
  19. import paddle
  20. class StoppingCriteria(ABC):
  21. """
  22. Abstract base class for all stopping criteria that can be applied during
  23. generation.
  24. """
  25. def __call__(self, input_ids: paddle.Tensor, logits: paddle.Tensor, **kwargs):
  26. raise NotImplementedError(
  27. f"{self.__class__} is an abstract class. "
  28. "StoppingCriteria needs to be subclassed"
  29. )
  30. class MaxTimeCriteria(StoppingCriteria):
  31. """
  32. This class can be used to stop generation whenever the full generation exceeds some amount of time. By default, the
  33. time will start being counted when you initialize this function. You can override this by passing an
  34. `initial_time`.
  35. Args:
  36. max_time (`float`):
  37. The maximum allowed time in seconds for the generation.
  38. initial_time (`float`, *optional*, defaults to `time.time()`):
  39. The start of the generation allowed time.
  40. """
  41. def __init__(self, max_time: float, initial_timestamp: Optional[float] = None):
  42. self.max_time = max_time
  43. self.initial_timestamp = (
  44. time.time() if initial_timestamp is None else initial_timestamp
  45. )
  46. def __call__(
  47. self, input_ids: paddle.Tensor, scores: paddle.Tensor, **kwargs
  48. ) -> bool:
  49. return time.time() - self.initial_timestamp > self.max_time
  50. class MaxLengthCriteria(StoppingCriteria):
  51. """
  52. This class can be used to stop generation whenever the full generated number of tokens exceeds `max_length`. Keep
  53. in mind for decoder-only type of transformers, [this will include the initial prompted tokens].
  54. Args:
  55. max_length (`int`):
  56. The maximum length that the output sequence can have in number of tokens.
  57. """
  58. def __init__(self, max_length: int):
  59. self.max_length = max_length
  60. def __call__(
  61. self, input_ids: paddle.Tensor, scores: paddle.Tensor, **kwargs
  62. ) -> bool:
  63. return input_ids.shape[-1] >= self.max_length
  64. class StoppingCriteriaList(list):
  65. def __call__(self, input_ids: paddle.Tensor, scores: paddle.Tensor, **kwargs):
  66. return any(criteria(input_ids, scores) for criteria in self)
  67. @property
  68. def max_length(self):
  69. for stopping_criterium in self:
  70. if isinstance(stopping_criterium, MaxLengthCriteria):
  71. return stopping_criterium.max_length
  72. return None
  73. def validate_stopping_criteria(
  74. stopping_criteria: StoppingCriteriaList, max_length: int
  75. ) -> StoppingCriteriaList:
  76. stopping_max_length = stopping_criteria.max_length
  77. new_stopping_criteria = deepcopy(stopping_criteria)
  78. if stopping_max_length is not None and stopping_max_length != max_length:
  79. warnings.warn(
  80. "You set different `max_length` for stopping criteria and `max_length` parameter",
  81. UserWarning,
  82. )
  83. elif stopping_max_length is None:
  84. new_stopping_criteria.append(MaxLengthCriteria(max_length=max_length))
  85. return new_stopping_criteria