"""render_automatic_eda — EDA completo one-shot: perfil → ctx → PDF + PPTX + MD. Pipeline impuro del grupo de capacidad `eda`. Dada UNA tabla DuckDB (o PostgreSQL), produce el informe AutomaticEDA COMPLETO en sus tres formatos a la vez (PDF móvil A5 + PPTX 16:9 + Markdown autocontenido para pegar a un LLM) con los capítulos POBLADOS, en una sola llamada. Compone, sin reimplementar su lógica, varias funciones del registry: - profile_table : perfila la tabla end-to-end (TableProfile agregado), opcionalmente con modelos baratos y análisis de serie. - build_eda_render_ctx : construye el `ctx` con los DATOS CRUDOS que el TableProfile agregado no incluye (raw_numeric para modelos/geo, timeseries_raw para series, geo_points para el mapa, db_path/table para la agregación push-down). Sin él, esos capítulos degradan. - render_automatic_eda_pdf : renderiza el documento por capítulos a PDF. - render_automatic_eda_pptx : renderiza el mismo documento a PPTX. - render_automatic_eda_markdown : serializa el mismo documento a Markdown autocontenido (texto + tablas markdown, sin binarios) para incorporar a un LLM. El TableProfile agregado basta para portada/overview/distribuciones/calidad/ correlación, pero los capítulos `modelos`, `timeseries`, `geospatial` y `agregacion` necesitan datos crudos (los clusters proyectados sobre el PCA, la serie valor-vs-tiempo, los puntos lat/lon, las filas para el groupby/pivot). `build_eda_render_ctx` los muestrea (LIMIT + push-down, sin traer la tabla entera a RAM) y los entrega en `ctx`; este pipeline los pasa como `meta['ctx']` a ambos renderers para que el informe salga completo. Estilo dict-no-throw del grupo `eda`: nunca lanza; captura cualquier error y degrada a `{"status": "error", "error": str}`. """ import os from datetime import datetime, timezone from datascience import ( build_eda_render_ctx, render_automatic_eda_markdown, render_automatic_eda_pdf, render_automatic_eda_pptx, run_eda_models, ) from pipelines.profile_table import profile_table # Tokens de almacenamiento por backend (para la portada del informe). _STORAGE = {"duckdb": "DuckDB", "postgres": "PostgreSQL"} # Presets de consumo CPU/LLM: cada profile_level fija SOLO los DEFAULTS de los # flags que controlan el coste (un flag explícito del caller siempre prima sobre # el preset). model_opts != None marca el camino "modelos baratos" (lite): los # modelos NO los corre profile_table (que ejecutaría KMeans + IsolationForest), # sino run_eda_models con esa granularidad, de modo que el coste CPU de los # multivariantes nunca se paga. model_opts None => modelos completos como hasta # ahora (profile_table los corre con todos los algoritmos). _PROFILE_PRESETS = { # Bajo consumo: sin LLM, sin serie, sample reducido y modelos limitados a # PCA + normalidad (sin KMeans ni IsolationForest, lo caro en CPU). Vistazo # rápido y barato de una tabla. "lite": { "run_models": True, "run_series": False, "run_llm": False, "sample": 2000, "model_opts": {"run_kmeans": False, "run_isolation": False}, }, # Default: idéntico al comportamiento histórico del pipeline (modelos # completos, serie temporal, sin LLM, sample 5000). "standard": { "run_models": True, "run_series": True, "run_llm": False, "sample": 5000, "model_opts": None, }, # Máximo: standard + narrativa LLM (interpretación del perfil y de los # capítulos modelos/geospatial/agregacion). Es la única parte que gasta # tokens del modelo. "full": { "run_models": True, "run_series": True, "run_llm": True, "sample": 5000, "model_opts": None, }, } def render_automatic_eda( db_path: str, table: str, backend: str = "duckdb", sample: int = None, run_models: bool = None, run_series: bool = None, run_llm: bool = None, profile_level: str = "standard", out_dir: str = "reports", basename: str = None, ctx_extra: dict = None, emit_md: bool = True, ) -> dict: """Perfila una tabla y emite el informe AutomaticEDA completo (PDF + PPTX). Args: db_path: ruta al archivo DuckDB, o DSN PostgreSQL si backend="postgres". table: nombre de la tabla a perfilar. backend: "duckdb" (default) o "postgres". sample: máximo de filas/valores muestreados por columna para el perfil y para los datos crudos del ctx (LIMIT). Default None => lo fija el preset de profile_level (lite=2000, standard/full=5000). run_models: corre los modelos baratos (PCA/KMeans/IsolationForest/normalidad). Necesario para que el capítulo `modelos` pinte los clusters sobre el plano PCA. Default None => lo fija el preset (True en los tres niveles); en `lite` los modelos se limitan a PCA + normalidad (ver profile_level). run_series: calcula el análisis de serie temporal por columna numérica. Necesario para el análisis del capítulo `timeseries` (la gráfica de evolución sale de los datos crudos del ctx aunque run_series sea False). Default None => lo fija el preset (standard/full=True, lite=False). run_llm: hace la interpretación LLM del perfil y ACTIVA además la narrativa LLM de los capítulos modelos/geospatial/ agregacion (títulos de segmento, descripción de la zona, selección de agregaciones). Con False esos capítulos usan su derivación cuantitativa (siguen completos, sin llamadas de red). Default None => lo fija el preset (full=True, lite/standard=False). profile_level: preset de consumo CPU/LLM. Mapea a defaults de los flags anteriores; un flag explícito SIEMPRE prima sobre el preset (el preset solo fija el default cuando el flag se deja en None): - "lite" bajo consumo: run_llm=False, run_series=False, sample=2000 y modelos limitados a **PCA + normalidad** (SIN KMeans ni IsolationForest, que es lo caro en CPU). Pensado para un vistazo rápido y barato. El capítulo `modelos` sale con PCA + normalidad, sin el scatter de clusters. - "standard" (default): comportamiento histórico — modelos completos (PCA/KMeans/IsolationForest/normalidad), serie temporal, sin LLM. - "full" standard + narrativa LLM (run_llm=True). Ejemplo de precedencia: profile_level="lite" con run_llm=True explícito => el LLM SÍ se ejecuta (el flag explícito gana al preset). out_dir: directorio de salida (se crea si no existe). Default "reports". basename: nombre base de los archivos sin extensión. Default "aeda_