executor_base.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. from abc import ABC, abstractmethod
  2. from typing import Dict, List, Optional, Set, Tuple
  3. from aphrodite.common.config import (CacheConfig, DeviceConfig, ModelConfig,
  4. ParallelConfig, SchedulerConfig,
  5. LoRAConfig, VisionLanguageConfig,
  6. SpeculativeConfig)
  7. from aphrodite.lora.request import LoRARequest
  8. from aphrodite.common.sequence import SamplerOutput, SequenceGroupMetadata
  9. class ExecutorBase(ABC):
  10. """Base class for all executors.
  11. An executor is responsible for executing the model on a specific device
  12. type (e.g., CPU, GPU, Neuron, etc.). Or it can be a distributed executor
  13. that can execute the model on multiple devices.
  14. """
  15. def __init__(
  16. self,
  17. model_config: ModelConfig,
  18. cache_config: CacheConfig,
  19. parallel_config: ParallelConfig,
  20. scheduler_config: SchedulerConfig,
  21. device_config: DeviceConfig,
  22. lora_config: Optional[LoRAConfig],
  23. vision_language_config: Optional[VisionLanguageConfig],
  24. speculative_config: Optional[SpeculativeConfig],
  25. ) -> None:
  26. self.model_config = model_config
  27. self.cache_config = cache_config
  28. self.lora_config = lora_config
  29. self.parallel_config = parallel_config
  30. self.scheduler_config = scheduler_config
  31. self.device_config = device_config
  32. self.vision_language_config = vision_language_config
  33. self.speculative_config = speculative_config
  34. self._init_executor()
  35. @abstractmethod
  36. def _init_executor(self) -> None:
  37. pass
  38. @abstractmethod
  39. def determine_num_available_blocks(self) -> Tuple[int, int]:
  40. """Determine the number of available blocks for the GPU KV cache and
  41. swappable CPU KV cache.
  42. Normally, this should simply delegate to the underlying Worker. Some
  43. ExecutorBase may require modification of the result, e.g. to ensure the
  44. selected cache sizes are compatible with all workers.
  45. Returns a Tuple[num_gpu_blocks, num_cpu_blocks], where num_gpu_blocks
  46. are blocks that are "active" on the device and can be appended to.
  47. num_cpu_blocks refers to "swapped" blocks in CPU memory and cannot be
  48. appended to.
  49. """
  50. raise NotImplementedError
  51. @abstractmethod
  52. def initialize_cache(self, num_gpu_blocks: int,
  53. num_cpu_blocks: int) -> None:
  54. """Initialize the KV cache with the given size in blocks.
  55. """
  56. raise NotImplementedError
  57. @abstractmethod
  58. def execute_model(
  59. self,
  60. seq_group_metadata_list: List[SequenceGroupMetadata],
  61. blocks_to_swap_in: Dict[int, int],
  62. blocks_to_swap_out: Dict[int, int],
  63. blocks_to_copy: Dict[int, List[int]],
  64. num_lookahead_slots: int,
  65. ) -> List[SamplerOutput]:
  66. """Executes one model step on the given sequences."""
  67. raise NotImplementedError
  68. @abstractmethod
  69. def add_lora(self, lora_request: LoRARequest) -> bool:
  70. raise NotImplementedError
  71. @abstractmethod
  72. def remove_lora(self, lora_id: int) -> bool:
  73. raise NotImplementedError
  74. @abstractmethod
  75. def list_loras(self) -> Set[int]:
  76. raise NotImplementedError
  77. @abstractmethod
  78. def check_health(self) -> None:
  79. """Checks if the executor is healthy. If not, it should raise an
  80. exception."""
  81. raise NotImplementedError
  82. class ExecutorAsyncBase(ExecutorBase):
  83. @abstractmethod
  84. async def execute_model_async(
  85. self,
  86. seq_group_metadata_list: List[SequenceGroupMetadata],
  87. blocks_to_swap_in: Dict[int, int],
  88. blocks_to_swap_out: Dict[int, int],
  89. blocks_to_copy: Dict[int, List[int]],
  90. num_lookahead_slots: int,
  91. ) -> SamplerOutput:
  92. """Executes one model step on the given sequences."""
  93. raise NotImplementedError
  94. async def check_health_async(self) -> None:
  95. """Checks if the executor is healthy. If not, it should raise an
  96. exception."""
  97. self.check_health()