feat(devgen/providers):improve provider error handling and response parsing
This commit is contained in:
6 files changed
+64
-39
No files matched your search
@@ -1,24 +0,0 @@
|
||||
def get_provider(name):
|
||||
name_lower = name.lower()
|
||||
if name_lower == "gemini":
|
||||
from devgen.providers.gemini import GeminiProvider
|
||||
|
||||
return GeminiProvider()
|
||||
elif name_lower == "openai":
|
||||
from devgen.providers.openai import OpenaiProvider
|
||||
|
||||
return OpenaiProvider()
|
||||
elif name_lower == "huggingface":
|
||||
from devgen.providers.huggingface import HuggingfaceProvider
|
||||
|
||||
return HuggingfaceProvider()
|
||||
elif name_lower == "openrouter":
|
||||
from devgen.providers.openrouter import OpenrouterProvider
|
||||
|
||||
return OpenrouterProvider()
|
||||
elif name_lower == "anthropic":
|
||||
from devgen.providers.anthropic import AnthropicProvider
|
||||
|
||||
return AnthropicProvider()
|
||||
|
||||
raise NotImplementedError(f"Provider '{name}' is not implemented yet.")
|
||||
@@ -9,7 +9,10 @@ class AnthropicProvider:
|
||||
) -> str:
|
||||
"""Generates a response using the Anthropic API."""
|
||||
if not api_key:
|
||||
raise ValueError("Anthropic API key is required.")
|
||||
raise ValueError(
|
||||
"Anthropic API key is missing. "
|
||||
"Set it via `devgen setup config` or pass --api-key."
|
||||
)
|
||||
|
||||
try:
|
||||
client = anthropic.Anthropic(api_key=api_key)
|
||||
|
||||
@@ -15,7 +15,10 @@ class GeminiProvider:
|
||||
recommended model.
|
||||
"""
|
||||
if not api_key:
|
||||
raise ValueError("Gemini API key is required.")
|
||||
raise ValueError(
|
||||
"Gemini API key is missing. "
|
||||
"Set it via `devgen setup config` or pass --api-key."
|
||||
)
|
||||
|
||||
client = genai.Client(api_key=api_key)
|
||||
|
||||
|
||||
@@ -15,7 +15,10 @@ class HuggingfaceProvider:
|
||||
) -> str:
|
||||
"""Generates a response using Hugging Face API."""
|
||||
if not api_key:
|
||||
raise ValueError("Hugging Face API token is required.")
|
||||
raise ValueError(
|
||||
"Hugging Face API token is missing. "
|
||||
"Set it via `devgen setup config` or pass --api-key."
|
||||
)
|
||||
|
||||
api_url = self.API_URL_TEMPLATE.format(model=model)
|
||||
headers = {"Authorization": f"Bearer {api_key}"}
|
||||
@@ -34,12 +37,31 @@ class HuggingfaceProvider:
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
|
||||
if isinstance(result, list) and "generated_text" in result[0]:
|
||||
if isinstance(result, list) and result and "generated_text" in result[0]:
|
||||
return result[0]["generated_text"].strip()
|
||||
elif isinstance(result, dict) and "error" in result:
|
||||
raise RuntimeError(f"Hugging Face API error: {result['error']}")
|
||||
err = result["error"]
|
||||
if "is currently loading" in str(err).lower():
|
||||
raise RuntimeError(
|
||||
f"Hugging Face model is loading: {err}. "
|
||||
"Wait a minute and retry, or pick a different model."
|
||||
)
|
||||
raise RuntimeError(f"Hugging Face API error: {err}")
|
||||
else:
|
||||
return str(result)
|
||||
raise RuntimeError(
|
||||
"Hugging Face returned an unexpected response shape. "
|
||||
"The model may not support text-generation."
|
||||
)
|
||||
|
||||
except requests.HTTPError as e:
|
||||
status = e.response.status_code if e.response is not None else "?"
|
||||
raise RuntimeError(
|
||||
f"Hugging Face request failed (HTTP {status}): {e}. "
|
||||
"Check the model id and your token permissions."
|
||||
) from e
|
||||
except requests.RequestException as e:
|
||||
raise RuntimeError(
|
||||
f"Hugging Face network error: {e}. Check your connection."
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Hugging Face generation failed: {e}")
|
||||
raise RuntimeError(f"Hugging Face generation failed: {e}") from e
|
||||
@@ -32,20 +32,35 @@ class OpenaiProvider:
|
||||
Returns:
|
||||
str: Generated response content.
|
||||
"""
|
||||
if not api_key:
|
||||
raise ValueError(
|
||||
"OpenAI API key is missing. "
|
||||
"Set it via `devgen setup config` or pass --api-key."
|
||||
)
|
||||
|
||||
# 1. Create a client instance with the API key.
|
||||
try:
|
||||
client = OpenAI(api_key=api_key)
|
||||
except Exception as e:
|
||||
# Add error handling if the client fails to initialize
|
||||
raise RuntimeError(f"Failed to initialize OpenAI client: {e}")
|
||||
raise RuntimeError(
|
||||
f"Failed to initialize OpenAI client: {e}. "
|
||||
"Verify the key is valid and that the `openai` package is installed."
|
||||
) from e
|
||||
|
||||
# Remove debug from kwargs if present
|
||||
kwargs.pop("debug", None)
|
||||
|
||||
# 2. Use the modern API syntax: client.chat.completions.create
|
||||
response = client.chat.completions.create(
|
||||
model=model or self.DEFAULT_MODEL,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
**kwargs,
|
||||
)
|
||||
try:
|
||||
response = client.chat.completions.create(
|
||||
model=model or self.DEFAULT_MODEL,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
**kwargs,
|
||||
)
|
||||
except Exception as e:
|
||||
raise RuntimeError(
|
||||
f"OpenAI request failed: {e}. "
|
||||
"Check the model name, API key permissions, and your account quota."
|
||||
) from e
|
||||
return response.choices[0].message.content.strip()
|
||||
@@ -11,7 +11,10 @@ class OpenrouterProvider:
|
||||
) -> str:
|
||||
"""Generates a response using OpenRouter."""
|
||||
if not api_key:
|
||||
raise ValueError("OpenRouter API key is required.")
|
||||
raise ValueError(
|
||||
"OpenRouter API key is missing. "
|
||||
"Set it via `devgen setup config` or pass --api-key."
|
||||
)
|
||||
|
||||
try:
|
||||
client = OpenAI(
|
||||
@@ -33,4 +36,7 @@ class OpenrouterProvider:
|
||||
)
|
||||
return response.choices[0].message.content.strip()
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"OpenRouter generation failed: {e}")
|
||||
raise RuntimeError(
|
||||
f"OpenRouter request failed: {e}. "
|
||||
"Verify the model id (e.g. `openai/gpt-4o`) and your API key credits."
|
||||
) from e
|
||||
Reference in new issue
Block a user