CoolFace
Apppublic

DeepRat/TrueEye_Reports

sourceHugging Facecreativeml-openrail-mupdated 11mo agoView on Hugging Face
0likes
main.py162 linesDownload Raw Back to root
1# main.py2import os3import uuid4import logging5from fastapi import FastAPI, HTTPException6from fastapi.middleware.cors import CORSMiddleware7from fastapi.responses import FileResponse, Response8from fastapi.staticfiles import StaticFiles9from pydantic import BaseModel10import requests11from typing import Optional, Any, Dict12 13# -------------------------------14# CONFIGURACIÓN DE LOGGING15# -------------------------------16logging.basicConfig(17    level=logging.INFO,18    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'19)20logger = logging.getLogger(__name__)21 22# -------------------------------23# CARGA DE SECRETS24# -------------------------------25FLOW_API_URL = os.getenv("FLOW_API_URL")26API_KEY        = os.getenv("LANGFLOW_API_KEY")27if not FLOW_API_URL:28    raise RuntimeError("❌ FLOW_API_URL no está definido. Agrégalo en los Secrets de Hugging Face.")29if not API_KEY:30    raise RuntimeError("❌ LANGFLOW_API_KEY no está definido. Agrégalo en los Secrets de Hugging Face.")31 32logger.info(f"✅ FLOW_API_URL configurado: {FLOW_API_URL[:30]}...")33logger.info(f"✅ LANGFLOW_API_KEY cargada (longitud {len(API_KEY)})")34 35# -------------------------------36# INICIALIZACIÓN DE LA APP37# -------------------------------38app = FastAPI()39app.add_middleware(40    CORSMiddleware,41    allow_origins=["*"],42    allow_methods=["*"],43    allow_headers=["*"],44)45 46app.mount("/static", StaticFiles(directory="static"), name="static")47 48@app.get("/")49async def serve_index():50    return FileResponse("static/index.html")51 52@app.get("/static/te.png")53async def serve_logo():54    logo_path = "static/te.png"55    if os.path.exists(logo_path):56        return FileResponse(logo_path)57    svg = '''<svg width="40" height="40" ...>...</svg>'''  # placeholder SVG58    return Response(svg, media_type="image/svg+xml", headers={"Cache-Control":"public, max-age=3600"})59 60# -------------------------------61# MODELOS DE Pydantic62# -------------------------------63class AnalyzeRequest(BaseModel):64    url: str65 66class AnalyzeResponse(BaseModel):67    result: str68    success: bool = True69    error: Optional[str] = None70 71# -------------------------------72# HELPER DE EXTRACCIÓN73# -------------------------------74def _extract_text_from_response(data: Any) -> Optional[str]:75    if isinstance(data, str):76        return data77    if isinstance(data, dict):78        for key in ("outputs","result","message","text","content"):79            val = data.get(key)80            if isinstance(val, str):81                return val82            elif val is not None:83                txt = _extract_text_from_response(val)84                if txt:85                    return txt86        for val in data.values():87            txt = _extract_text_from_response(val)88            if txt:89                return txt90    if isinstance(data, list):91        for item in data:92            txt = _extract_text_from_response(item)93            if txt:94                return txt95    return None96 97# -------------------------------98# ENDPOINT /analyze99# -------------------------------100@app.post("/analyze", response_model=AnalyzeResponse)101async def analyze(request: AnalyzeRequest):102    logger.info(f"📥 Recibida solicitud de análisis para URL: {request.url}")103    session_id = str(uuid.uuid4())104    payload = {105        "input_value":       request.url,106        "input_type":        "chat",107        "output_type":       "chat",108        "session_id":        session_id,109        "output_component":  "",110        "tweaks":            None111    }112    headers = {113        "Content-Type": "application/json",114        "User-Agent":    "TrueEye-HuggingFace-Space/1.0",115        "x-api-key":     API_KEY116    }117 118    try:119        logger.info("📤 Enviando petición a Langflow...")120        logger.debug(f"Payload: {payload}")121        resp = requests.post(FLOW_API_URL, json=payload, headers=headers, timeout=300)122        logger.info(f"📨 Respuesta recibida. Status: {resp.status_code}")123        resp.raise_for_status()124        data = resp.json()125        logger.debug(f"Respuesta JSON completa: {data}")126 127        # Extraer texto final128        result_text = _extract_text_from_response(data)129        if not result_text:130            logger.warning("⚠️ No se pudo extraer texto de la respuesta")131            result_text = "⚠️ Se procesó la solicitud pero no se pudo extraer el resultado."132 133        logger.info("✅ Análisis completado exitosamente")134        return AnalyzeResponse(result=result_text)135 136    except requests.exceptions.Timeout:137        logger.error("⏱️ Timeout en la petición a Langflow")138        return AnalyzeResponse(result="❌ Error: Timeout (el análisis tardó demasiado)", success=False, error="timeout")139 140    except requests.exceptions.HTTPError as e:141        body = e.response.text if e.response is not None else "<no body>"142        logger.error(f"🚫 Error HTTP {e.response.status_code if e.response else ''}: {body}")143        return AnalyzeResponse(144            result=f"❌ Error HTTP al llamar al Flow: {body}",145            success=False,146            error=f"http_{e.response.status_code if e.response else 'unknown'}"147        )148 149    except Exception as e:150        logger.exception("💥 Error inesperado en /analyze")151        return AnalyzeResponse(result=f"❌ Error inesperado: {e}", success=False, error="unknown")152 153# -------------------------------154# HEALTHCHECK155# -------------------------------156@app.get("/health")157async def health_check():158    return {159        "status": "healthy",160        "flow_url":   bool(FLOW_API_URL),161        "service":    "TrueEye Reports"162    }