import json import anthropic import config client = anthropic.Anthropic(api_key=config.ANTHROPIC_API_KEY) SYSTEM_PROMPT = """ Eres un experto en optimización de campañas de Meta Ads (Facebook/Instagram) para generación de leads. Cada campaña corresponde a un producto o curso con un CPL objetivo (coste por lead) acordado. MODELO DE NEGOCIO: - El objetivo es maximizar el volumen de leads por debajo del CPL máximo rentable. - La frecuencia alta puede indicar saturación de audiencia. - El CTR y CPM son indicadores clave de relevancia creativa y competencia en subasta. REGLAS DE DECISIÓN: 1. CPL > CPL_máximo → REDUCIR_PRESUPUESTO o revisar creatividades/audiencias. 2. CPL <= CPL_máximo y volumen bajo → AUMENTAR_PRESUPUESTO si hay margen. 3. Frecuencia > 3.0 → considerar rotar creatividades o ampliar audiencia. 4. CTR < 1% → problema creativo, revisar anuncios. 5. Sin leads tras 3+ días de gasto → revisar configuración de conversión. Devuelve ÚNICAMENTE un JSON válido con esta estructura exacta, sin texto adicional ni markdown: { "accion": "PAUSAR | REDUCIR_PRESUPUESTO | AUMENTAR_PRESUPUESTO | MANTENER | REVISAR_CREATIVIDADES", "parametro": 1.0, "justificacion": "explicación breve", "consejo": "acción concreta y específica", "alerta": "texto si hay algo crítico, null si no", "confianza": 0.0 } """ def decide(analysis: dict) -> dict: response = client.messages.create( model="claude-haiku-4-5-20251001", max_tokens=400, system=SYSTEM_PROMPT, messages=[{ "role": "user", "content": ( f"Analiza esta campaña de Meta Ads y devuelve la decisión en JSON:\n\n" f"{json.dumps(analysis, ensure_ascii=False, indent=2)}" ), }], ) raw = response.content[0].text.strip() clean = raw.replace("```json", "").replace("```", "").strip() try: return json.loads(clean) except json.JSONDecodeError: return { "accion": "MANTENER", "parametro": 1.0, "justificacion": "Error parseando respuesta del agente.", "alerta": f"JSON inválido: {raw[:200]}", "confianza": 0.0, }