Async LLM call with timing output and debug logging.
(
model: str, messages: list[dict], step_name: str, raise_on_truncation: bool = False, **kwargs
)
| 432 | |
| 433 | |
| 434 | async def _llm_call_async( |
| 435 | model: str, messages: list[dict], step_name: str, raise_on_truncation: bool = False, **kwargs |
| 436 | ) -> str: |
| 437 | """Async LLM call with timing output and debug logging.""" |
| 438 | messages = _prepare_messages(model, messages) |
| 439 | extra_headers = get_extra_headers() |
| 440 | if extra_headers: |
| 441 | kwargs.setdefault("extra_headers", extra_headers) |
| 442 | timeout = get_timeout() |
| 443 | if timeout is not None: |
| 444 | kwargs.setdefault("timeout", timeout) |
| 445 | logger.debug("LLM request [%s]:\n%s", step_name, _fmt_messages(messages)) |
| 446 | if kwargs: |
| 447 | logger.debug("LLM kwargs [%s]: %s", step_name, kwargs) |
| 448 | |
| 449 | t0 = time.time() |
| 450 | |
| 451 | response = await litellm.acompletion(model=model, messages=messages, **kwargs) |
| 452 | content = response.choices[0].message.content or "" |
| 453 | truncated = _warn_if_truncated(response, step_name, kwargs.get("max_tokens")) |
| 454 | |
| 455 | elapsed = time.time() - t0 |
| 456 | sys.stdout.write(f" {step_name}... {_format_usage(elapsed, response.usage)}\n") |
| 457 | sys.stdout.flush() |
| 458 | logger.debug( |
| 459 | "LLM response [%s]:\n%s", step_name, content[:500] + ("..." if len(content) > 500 else "") |
| 460 | ) |
| 461 | if raise_on_truncation and truncated: |
| 462 | raise TruncatedResponseError( |
| 463 | f"LLM [{step_name}] hit the length limit; skipping to avoid a truncated page" |
| 464 | ) |
| 465 | return content.strip() |
| 466 | |
| 467 | |
| 468 | async def _llm_call_page_async(model: str, messages: list[dict], step_name: str, **kwargs) -> str: |