Fix: Hardened AI project generation with stable model fallback and better logging (Phase 9)
Browse files- backend/routers/generator.py +18 -3
- backend/services/config.py +2 -8
backend/routers/generator.py
CHANGED
|
@@ -74,23 +74,38 @@ async def generate_project(
|
|
| 74 |
# 3. Call Groq
|
| 75 |
provider_config = config_service.get_provider_config("groq")
|
| 76 |
api_key = provider_config.get("api_key") or settings.GROQ_API_KEY
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
client = groq.AsyncGroq(api_key=api_key)
|
| 78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
response = await client.chat.completions.create(
|
| 80 |
-
model=
|
| 81 |
messages=[
|
| 82 |
{"role": "system", "content": system_prompt},
|
| 83 |
{"role": "user", "content": user_message}
|
| 84 |
],
|
| 85 |
temperature=0.3,
|
| 86 |
max_tokens=2048,
|
|
|
|
| 87 |
response_format={"type": "json_object"}
|
| 88 |
)
|
| 89 |
|
| 90 |
response_text = response.choices[0].message.content
|
|
|
|
| 91 |
data = _parse_json_output(response_text)
|
| 92 |
return data
|
| 93 |
|
| 94 |
except Exception as e:
|
| 95 |
-
logger.
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
# 3. Call Groq
|
| 75 |
provider_config = config_service.get_provider_config("groq")
|
| 76 |
api_key = provider_config.get("api_key") or settings.GROQ_API_KEY
|
| 77 |
+
|
| 78 |
+
if not api_key:
|
| 79 |
+
logger.error("GROQ_API_KEY is missing in settings and config")
|
| 80 |
+
raise HTTPException(status_code=500, detail="GROQ_API_KEY not configured")
|
| 81 |
+
|
| 82 |
client = groq.AsyncGroq(api_key=api_key)
|
| 83 |
|
| 84 |
+
# Use llama3-70b-8192 as a more stable fallback/default
|
| 85 |
+
model_name = provider_config.get("default_model") or "llama3-70b-8192"
|
| 86 |
+
logger.info("Calling Groq with model: %s", model_name)
|
| 87 |
+
|
| 88 |
response = await client.chat.completions.create(
|
| 89 |
+
model=model_name,
|
| 90 |
messages=[
|
| 91 |
{"role": "system", "content": system_prompt},
|
| 92 |
{"role": "user", "content": user_message}
|
| 93 |
],
|
| 94 |
temperature=0.3,
|
| 95 |
max_tokens=2048,
|
| 96 |
+
# Note: Not all Groq models support json_object mode perfectly yet
|
| 97 |
response_format={"type": "json_object"}
|
| 98 |
)
|
| 99 |
|
| 100 |
response_text = response.choices[0].message.content
|
| 101 |
+
logger.debug("Groq raw response: %s", response_text)
|
| 102 |
data = _parse_json_output(response_text)
|
| 103 |
return data
|
| 104 |
|
| 105 |
except Exception as e:
|
| 106 |
+
logger.exception("Project generation failed")
|
| 107 |
+
error_msg = str(e)
|
| 108 |
+
# Handle specific Groq errors if possible
|
| 109 |
+
if "api_key" in error_msg.lower():
|
| 110 |
+
error_msg = "Invalid or missing API Key"
|
| 111 |
+
raise HTTPException(status_code=500, detail=f"AI Generation failed: {error_msg}")
|
backend/services/config.py
CHANGED
|
@@ -56,7 +56,7 @@ class ConfigService:
|
|
| 56 |
|
| 57 |
# Defaults used when DB has no config entry for a provider
|
| 58 |
_DEFAULTS: Dict[str, Any] = {
|
| 59 |
-
"groq": {"enabled": True, "default_model": "
|
| 60 |
"openai": {"enabled": True, "default_model": "gpt-4o", "temperature": 0.7, "max_tokens": 4096},
|
| 61 |
"openrouter": {"enabled": True, "default_model": "google/gemini-2.0-flash", "temperature": 0.7, "max_tokens": 8192},
|
| 62 |
"gemini": {"enabled": True, "default_model": "gemini-2.0-flash", "temperature": 0.7, "max_tokens": 8192},
|
|
@@ -100,11 +100,5 @@ class ConfigService:
|
|
| 100 |
return cls._cache[cache_key]
|
| 101 |
except Exception:
|
| 102 |
pass
|
| 103 |
-
|
| 104 |
return default
|
| 105 |
-
|
| 106 |
-
@classmethod
|
| 107 |
-
def invalidate_cache(cls) -> None:
|
| 108 |
-
cls._cache.clear()
|
| 109 |
-
|
| 110 |
-
config_service = ConfigService()
|
|
|
|
| 56 |
|
| 57 |
# Defaults used when DB has no config entry for a provider
|
| 58 |
_DEFAULTS: Dict[str, Any] = {
|
| 59 |
+
"groq": {"enabled": True, "default_model": "llama3-70b-8192", "temperature": 0.7, "max_tokens": 4096},
|
| 60 |
"openai": {"enabled": True, "default_model": "gpt-4o", "temperature": 0.7, "max_tokens": 4096},
|
| 61 |
"openrouter": {"enabled": True, "default_model": "google/gemini-2.0-flash", "temperature": 0.7, "max_tokens": 8192},
|
| 62 |
"gemini": {"enabled": True, "default_model": "gemini-2.0-flash", "temperature": 0.7, "max_tokens": 8192},
|
|
|
|
| 100 |
return cls._cache[cache_key]
|
| 101 |
except Exception:
|
| 102 |
pass
|
| 103 |
+
|
| 104 |
return default
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|