mirror of
https://github.com/nubenetes/awesome-kubernetes.git
synced 2026-05-22 17:13:42 +00:00
96 lines
4.4 KiB
Python
96 lines
4.4 KiB
Python
import httpx
|
|
import asyncio
|
|
import random
|
|
import json
|
|
import re
|
|
from typing import Dict, Any, List, Optional
|
|
from src.config import GEMINI_API_KEYS, GEMINI_API_VERSION, GEMINI_MODELS
|
|
from src.logger import log_event
|
|
|
|
# Global para mantener el índice de la API Key actual
|
|
CURRENT_KEY_INDEX = 0
|
|
|
|
class GeminiDiagnostics:
|
|
def __init__(self):
|
|
self.attempts = []
|
|
|
|
def add_attempt(self, model: str, status: int, error: str = None, response_text: str = None):
|
|
self.attempts.append({
|
|
"model": model,
|
|
"status": status,
|
|
"error": error,
|
|
"response_preview": response_text[:200] if response_text else None
|
|
})
|
|
|
|
def get_report(self) -> str:
|
|
report = "DIAGNÓSTICO GEMINI:\n"
|
|
for i, a in enumerate(self.attempts):
|
|
report += f" {i+1}. [{a['model']}] Status: {a['status']}"
|
|
if a['error']: report += f" | Error: {a['error']}"
|
|
if a['response_preview']: report += f" | Resp: {a['response_preview']}"
|
|
report += "\n"
|
|
return report
|
|
|
|
async def call_gemini_with_retry(prompt: str, response_format: str = "json", max_retries: int = 3):
|
|
"""
|
|
Llama a la API de Gemini con rotación exhaustiva y REINTENTO REAL en 429.
|
|
"""
|
|
global CURRENT_KEY_INDEX
|
|
if not GEMINI_API_KEYS:
|
|
raise ValueError("No hay GEMINI_API_KEYS configuradas.")
|
|
|
|
diagnostics = GeminiDiagnostics()
|
|
|
|
async with httpx.AsyncClient() as client:
|
|
for key_attempt in range(len(GEMINI_API_KEYS)):
|
|
api_key = GEMINI_API_KEYS[CURRENT_KEY_INDEX]
|
|
|
|
for model in GEMINI_MODELS:
|
|
full_model_name = f"models/{model}"
|
|
api_url = f"https://generativelanguage.googleapis.com/{GEMINI_API_VERSION}/{full_model_name}:generateContent?key={api_key}"
|
|
|
|
# Reintentos por modelo (incluyendo 429)
|
|
for attempt in range(max_retries + 2):
|
|
try:
|
|
payload = {"contents": [{"parts": [{"text": prompt}]}]}
|
|
response = await client.post(api_url, json=payload, timeout=45)
|
|
|
|
if response.status_code == 200:
|
|
resp_json = response.json()
|
|
if 'candidates' in resp_json and resp_json['candidates']:
|
|
text_resp = resp_json['candidates'][0]['content']['parts'][0]['text']
|
|
if response_format == "json":
|
|
match = re.search(r'\{.*\}|\[.*\]', text_resp, re.DOTALL)
|
|
if match:
|
|
data = json.loads(match.group(0))
|
|
return data[0] if isinstance(data, list) and len(data) > 0 else data
|
|
diagnostics.add_attempt(model, 200, "JSON no encontrado", text_resp)
|
|
break
|
|
return text_resp
|
|
diagnostics.add_attempt(model, 200, "Sin candidates")
|
|
break
|
|
|
|
elif response.status_code == 429:
|
|
wait_time = (10 * (attempt + 1)) + random.random() * 5
|
|
log_event(f" [!] API 429 (Límite): Reintentando {model} en {wait_time:.1f}s... (Intento {attempt+1})")
|
|
await asyncio.sleep(wait_time)
|
|
continue # Reintentar el MISMO modelo
|
|
|
|
elif response.status_code in [500, 503, 504]:
|
|
diagnostics.add_attempt(model, response.status_code, "Server Error")
|
|
await asyncio.sleep(5)
|
|
continue
|
|
|
|
else:
|
|
diagnostics.add_attempt(model, response.status_code, "API Error", response.text)
|
|
break
|
|
|
|
except Exception as e:
|
|
diagnostics.add_attempt(model, 0, f"Excepción: {str(e)}")
|
|
break
|
|
|
|
CURRENT_KEY_INDEX = (CURRENT_KEY_INDEX + 1) % len(GEMINI_API_KEYS)
|
|
await asyncio.sleep(2)
|
|
|
|
raise Exception(f"Fallo crítico Gemini tras rotación exhaustiva.\n{diagnostics.get_report()}")
|