Call LLM via the provider with retries.
(self, user_content: str)
| 465 | return FailureReason.PROVIDER_ERROR |
| 466 | |
| 467 | def _call_llm(self, user_content: str) -> ChunkResult: |
| 468 | """Call LLM via the provider with retries.""" |
| 469 | messages = self._build_messages(user_content) |
| 470 | |
| 471 | provider = self.provider |
| 472 | retryable = provider.retryable_exceptions |
| 473 | |
| 474 | last_err: Exception | None = None |
| 475 | for attempt in range(3): |
| 476 | try: |
| 477 | content, usage = provider.call(user_content) |
| 478 | data, raw = process_llm_result(content) |
| 479 | return ChunkResult( |
| 480 | data=data, |
| 481 | messages=messages, |
| 482 | raw_response=raw, |
| 483 | usage=usage, |
| 484 | ) |
| 485 | except ExtractionError: |
| 486 | raise |
| 487 | except retryable as e: |
| 488 | last_err = e |
| 489 | wait = 2**attempt |
| 490 | logger.warning( |
| 491 | "LLM call attempt %d failed (%s), retrying in %ds", |
| 492 | attempt + 1, |
| 493 | e, |
| 494 | wait, |
| 495 | ) |
| 496 | time.sleep(wait) |
| 497 | except Exception as e: |
| 498 | raise ExtractionError( |
| 499 | f"LLM call failed: {e}", |
| 500 | reason_class=self._classify_provider_error(e), |
| 501 | ) from e |
| 502 | |
| 503 | raise ExtractionError( |
| 504 | f"LLM call failed after 3 attempts: {last_err}", |
| 505 | reason_class=self._classify_provider_error(last_err) |
| 506 | if last_err is not None |
| 507 | else FailureReason.PROVIDER_ERROR, |
| 508 | ) from last_err |
| 509 | |
| 510 | @staticmethod |
| 511 | def _build_user_content(chunk: str, chunk_info: str) -> str: |