feat(devgen/providers): normalize token limit error handling
Add token limit error detection and formatting across all provider modules to surface clear diagnostics when context windows are exceeded, improving error messages and preventing silent failures. New Features - Introduce `is_token_limit_error` checks in Anthropic, Gemini, Hugging Face, Ollama, OpenAI, and OpenRouter providers. - Use `format_token_limit_error` to generate user‑friendly error messages for token limit overs. Enhancements - Centralize token limit error handling for consistent diagnostics across providers. - Explicitly re‑raise `RuntimeError` in Hugging Face to preserve original behavior. Bug Fixes - None
This commit is contained in:
6 files changed
+37
-1
No files matched your search
@@ -1,5 +1,7 @@
|
||||
import anthropic
|
||||
|
||||
from devgen.utils import format_token_limit_error, is_token_limit_error
|
||||
|
||||
|
||||
class AnthropicProvider:
|
||||
"""Generates content using Anthropic's Claude models."""
|
||||
@@ -23,4 +25,9 @@ class AnthropicProvider:
|
||||
)
|
||||
return message.content[0].text.strip()
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Anthropic generation failed: {e}")
|
||||
if is_token_limit_error(e):
|
||||
raise RuntimeError(format_token_limit_error("Anthropic", e)) from e
|
||||
raise RuntimeError(
|
||||
f"Anthropic generation failed: {e}. "
|
||||
"Check the model id and your account credits."
|
||||
) from e
|
||||
@@ -2,6 +2,8 @@ import time
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
|
||||
from devgen.utils import format_token_limit_error, is_token_limit_error
|
||||
|
||||
|
||||
class GeminiProvider:
|
||||
"""Generates content using Google's Gemini models."""
|
||||
@@ -40,6 +42,10 @@ class GeminiProvider:
|
||||
return response.text.strip()
|
||||
except Exception as e:
|
||||
error_msg = str(e).upper()
|
||||
# Token / context-window overflow is not retryable — no point
|
||||
# backing off, the prompt is just too big.
|
||||
if is_token_limit_error(e):
|
||||
raise RuntimeError(format_token_limit_error("Gemini", e)) from e
|
||||
# Check for 429 or ResourceExhausted in common error formats
|
||||
if any(
|
||||
x in error_msg
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import requests
|
||||
|
||||
from devgen.utils import format_token_limit_error, is_token_limit_error
|
||||
|
||||
|
||||
class HuggingfaceProvider:
|
||||
"""Generates content using Hugging Face Inference API."""
|
||||
@@ -46,6 +48,10 @@ class HuggingfaceProvider:
|
||||
f"Hugging Face model is loading: {err}. "
|
||||
"Wait a minute and retry, or pick a different model."
|
||||
)
|
||||
if is_token_limit_error(err):
|
||||
raise RuntimeError(
|
||||
format_token_limit_error("Hugging Face", err)
|
||||
) from err
|
||||
raise RuntimeError(f"Hugging Face API error: {err}")
|
||||
else:
|
||||
raise RuntimeError(
|
||||
@@ -55,6 +61,8 @@ class HuggingfaceProvider:
|
||||
|
||||
except requests.HTTPError as e:
|
||||
status = e.response.status_code if e.response is not None else "?"
|
||||
if is_token_limit_error(e):
|
||||
raise RuntimeError(format_token_limit_error("Hugging Face", e)) from e
|
||||
raise RuntimeError(
|
||||
f"Hugging Face request failed (HTTP {status}): {e}. "
|
||||
"Check the model id and your token permissions."
|
||||
@@ -63,5 +71,9 @@ class HuggingfaceProvider:
|
||||
raise RuntimeError(
|
||||
f"Hugging Face network error: {e}. Check your connection."
|
||||
) from e
|
||||
except RuntimeError:
|
||||
raise
|
||||
except Exception as e:
|
||||
if is_token_limit_error(e):
|
||||
raise RuntimeError(format_token_limit_error("Hugging Face", e)) from e
|
||||
raise RuntimeError(f"Hugging Face generation failed: {e}") from e
|
||||
@@ -1,3 +1,4 @@
|
||||
from devgen.utils import format_token_limit_error, is_token_limit_error
|
||||
|
||||
|
||||
class OllamaProvider:
|
||||
@@ -37,6 +38,8 @@ class OllamaProvider:
|
||||
**kwargs,
|
||||
)
|
||||
except Exception as e:
|
||||
if is_token_limit_error(e):
|
||||
raise RuntimeError(format_token_limit_error("Ollama", e)) from e
|
||||
raise RuntimeError(
|
||||
f"Ollama request failed (host={host}, model={chosen_model}): {e}. "
|
||||
"Is the Ollama server running? Start it with `ollama serve` and "
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from openai import OpenAI
|
||||
|
||||
from devgen.utils import format_token_limit_error, is_token_limit_error
|
||||
|
||||
|
||||
class OpenaiProvider:
|
||||
"""Generates a response string using the OpenAI ChatCompletion API based on the provided prompt and parameters. This method initializes an OpenAI client with the given API key, sends a chat completion request with specified model and additional parameters, and returns the content of the generated message.
|
||||
@@ -59,6 +61,8 @@ class OpenaiProvider:
|
||||
**kwargs,
|
||||
)
|
||||
except Exception as e:
|
||||
if is_token_limit_error(e):
|
||||
raise RuntimeError(format_token_limit_error("OpenAI", e)) from e
|
||||
raise RuntimeError(
|
||||
f"OpenAI request failed: {e}. "
|
||||
"Check the model name, API key permissions, and your account quota."
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from openai import OpenAI
|
||||
|
||||
from devgen.utils import format_token_limit_error, is_token_limit_error
|
||||
|
||||
|
||||
class OpenrouterProvider:
|
||||
"""Generates content using OpenRouter (OpenAI-compatible API)."""
|
||||
@@ -36,6 +38,8 @@ class OpenrouterProvider:
|
||||
)
|
||||
return response.choices[0].message.content.strip()
|
||||
except Exception as e:
|
||||
if is_token_limit_error(e):
|
||||
raise RuntimeError(format_token_limit_error("OpenRouter", e)) from e
|
||||
raise RuntimeError(
|
||||
f"OpenRouter request failed: {e}. "
|
||||
"Verify the model id (e.g. `openai/gpt-4o`) and your API key credits."
|
||||
|
||||
Reference in new issue
Block a user