An asynchronous wrapper for LLMEngine. This class is used to wrap the LLMEngine class to make it asynchronous. It uses asyncio to create a background loop that keeps processing incoming requests. The LLMEngine is kicked by the generate method when there are requests in the waiting q
| 230 | |
| 231 | |
| 232 | class AsyncLLMEngine: |
| 233 | """An asynchronous wrapper for LLMEngine. |
| 234 | |
| 235 | This class is used to wrap the LLMEngine class to make it asynchronous. It |
| 236 | uses asyncio to create a background loop that keeps processing incoming |
| 237 | requests. The LLMEngine is kicked by the generate method when there |
| 238 | are requests in the waiting queue. The generate method yields the outputs |
| 239 | from the LLMEngine to the caller. |
| 240 | |
| 241 | NOTE: For the comprehensive list of arguments, see `LLMEngine`. |
| 242 | |
| 243 | Args: |
| 244 | worker_use_ray: Whether to use Ray for model workers. Required for |
| 245 | distributed execution. Should be the same as |
| 246 | `parallel_config.worker_use_ray`. |
| 247 | engine_use_ray: Whether to make LLMEngine a Ray actor. If so, the |
| 248 | async frontend will be executed in a separate process as the |
| 249 | model workers. |
| 250 | log_requests: Whether to log the requests. |
| 251 | start_engine_loop: If True, the background task to run the engine |
| 252 | will be automatically started in the generate call. |
| 253 | *args, *kwargs: Arguments for LLMEngine. |
| 254 | """ |
| 255 | |
| 256 | _engine_class: Type[_AsyncLLMEngine] = _AsyncLLMEngine |
| 257 | |
| 258 | def __init__(self, |
| 259 | worker_use_ray: bool, |
| 260 | engine_use_ray: bool, |
| 261 | *args, |
| 262 | log_requests: bool = True, |
| 263 | max_log_len: Optional[int] = None, |
| 264 | start_engine_loop: bool = True, |
| 265 | **kwargs) -> None: |
| 266 | self.worker_use_ray = worker_use_ray |
| 267 | self.engine_use_ray = engine_use_ray |
| 268 | self.log_requests = log_requests |
| 269 | self.max_log_len = max_log_len |
| 270 | self.engine = self._init_engine(*args, **kwargs) |
| 271 | |
| 272 | self.background_loop = None |
| 273 | # We need to keep a reference to unshielded |
| 274 | # task as well to prevent it from being garbage |
| 275 | # collected |
| 276 | self._background_loop_unshielded = None |
| 277 | self.start_engine_loop = start_engine_loop |
| 278 | self._request_tracker = RequestTracker() |
| 279 | |
| 280 | @property |
| 281 | def is_running(self) -> bool: |
| 282 | return (self.background_loop is not None |
| 283 | and not self.background_loop.done()) |
| 284 | |
| 285 | def start_background_loop(self) -> None: |
| 286 | """Start the background loop.""" |
| 287 | if self.is_running: |
| 288 | raise RuntimeError("Background loop is already running.") |
| 289 | self._request_tracker.init_event() |
nothing calls this directly
no outgoing calls
no test coverage detected