refactor(providers): address PR #772 review round 2 — guard, naming, docs, tests

- _retry.py: replace `assert last_error is not None` with explicit
  `if last_error is None: raise RuntimeError(...)` so the original
  rate-limit error is preserved under `python -O`.
- openai.py: drop the `_retry_factory` alias chain; rename the bound
  decorator to `_retry_429` to match the pattern in mistral.py.
- mistral.py: comment the imports so future reviewers understand why
  `from mistralai.client import …` is the canonical path on 2.x (no
  top-level `__init__.py`; no `mistralai.models` subpackage either).
- docs/configuration.md: add `OPENAI_GENERATION_MODEL` and
  `OLLAMA_GENERATION_MODEL` rows to the env-var reference table.
- test_mistral.py: add direct unit test for the `_is_rate_limit`
  predicate (429 → True, 500 → False, missing-attr → False).
- test_registry.py: stub `mistralai.client.Mistral` in the registry
  picker test, mirroring the Ollama sibling, so the test doesn't
  depend on the SDK accepting arbitrary keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-05-08 18:11:57 +02:00
co-authored by Claude Opus 4.7
parent e360a7782b
commit 20f1770794
6 changed files with 33 additions and 7 deletions
+5 -5
View File
@@ -10,14 +10,14 @@ import logging
from openai import AsyncOpenAI, RateLimitError
from ._retry import retry_on_rate_limit as _retry_factory
from ._retry import retry_on_rate_limit
from .base import Provider
logger = logging.getLogger(__name__)
# OpenAI's RateLimitError is itself a 429-specific class, so the default
# is_rate_limit predicate ("always True") matches the previous behavior.
retry_on_rate_limit = _retry_factory(RateLimitError, provider_name="OpenAI")
_retry_429 = retry_on_rate_limit(RateLimitError, provider_name="OpenAI")
# Well-known embedding dimensions for OpenAI models
@@ -92,7 +92,7 @@ class OpenAIProvider(Provider):
"""Whether this provider supports text generation."""
return self.generation_model is not None
@retry_on_rate_limit
@_retry_429
async def embed(self, text: str) -> list[float]:
"""
Generate embedding vector for text.
@@ -173,7 +173,7 @@ class OpenAIProvider(Provider):
return all_embeddings
@retry_on_rate_limit
@_retry_429
async def _embed_batch_request(self, batch: list[str]) -> list[list[float]]:
"""Make a single batch embedding request with retry logic."""
assert self.embedding_model is not None # Type narrowing
@@ -208,7 +208,7 @@ class OpenAIProvider(Provider):
)
return self._dimension
@retry_on_rate_limit
@_retry_429
async def generate(self, prompt: str, max_tokens: int = 500) -> str:
"""
Generate text from a prompt.