feat(eda): wiring AutomaticEDA — build_eda_render_ctx + pipeline render_automatic_eda + profile_table(emit_automatic)
Conecta el motor AutomaticEDA con los datos crudos para que los 4 capítulos
dependientes de ctx (modelos, timeseries, geospatial, agregacion) salgan
POBLADOS en vez de degradar a una nota.
- build_eda_render_ctx (datascience, impure, dict-no-throw): dado db_path+table
y el TableProfile agregado, construye el ctx con los datos crudos que el
perfil no incluye: raw_numeric {col:[float|None]} alineado por fila (modelos /
geospatial), timeseries_raw {time_col,t,series} vía extract_timeseries_raw,
geo_points {lats,lons} desde el par lat/lon detectado, y db_path/table para el
groupby/pivot push-down de agregacion. Muestrea con LIMIT (no trae la tabla
entera a RAM). Compone detect_time_column / extract_timeseries_raw /
detect_latlon_columns / duckdb_query_readonly (imports lazy para evitar ciclo).
- render_automatic_eda (pipeline): one-shot perfil -> ctx -> PDF + PPTX con los
11 capítulos poblados; devuelve rutas + manifest de versiones por capítulo.
- profile_table: flag aditivo emit_automatic=True emite el AutomaticEDA PDF+PPTX
además del flujo legacy (emit_pdf/render_eda_pdf intacto). Nuevas claves de
retorno aeda_pdf_path / aeda_pptx_path / aeda_manifest_path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -32,11 +32,14 @@ from datascience import (
|
||||
acf_pacf,
|
||||
adf_kpss_stationarity,
|
||||
association_matrix,
|
||||
build_eda_render_ctx,
|
||||
column_quality_score,
|
||||
describe_numeric,
|
||||
eda_llm_insights,
|
||||
exploratory_caveats,
|
||||
infer_semantic_type,
|
||||
render_automatic_eda_pdf,
|
||||
render_automatic_eda_pptx,
|
||||
render_eda_markdown,
|
||||
render_eda_pdf,
|
||||
run_eda_models,
|
||||
@@ -385,6 +388,7 @@ def profile_table(
|
||||
run_llm: bool = False,
|
||||
run_series: bool = False,
|
||||
emit_pdf: bool = False,
|
||||
emit_automatic: bool = False,
|
||||
report_dir: str = "reports",
|
||||
write_report: bool = True,
|
||||
) -> dict:
|
||||
@@ -412,6 +416,15 @@ def profile_table(
|
||||
emit_pdf: si True (default False) renderiza un PDF multipagina vertical
|
||||
(legible en movil) del perfil junto al report markdown y devuelve su
|
||||
ruta en pdf_path.
|
||||
emit_automatic: si True (default False) emite ademas el informe
|
||||
AutomaticEDA COMPLETO en sus dos formatos (PDF A5 movil + PPTX 16:9)
|
||||
con los 11 capitulos del motor por capitulos. Construye el contexto
|
||||
de datos crudos con build_eda_render_ctx (raw_numeric para modelos/
|
||||
geo, timeseries_raw para series, geo_points para el mapa, db_path/
|
||||
table para la agregacion push-down) para que los capitulos modelos/
|
||||
timeseries/geospatial/agregacion salgan poblados, no degradados. Es
|
||||
ADITIVO: no sustituye a emit_pdf (render_eda_pdf). Sus rutas vuelven
|
||||
en aeda_pdf_path / aeda_pptx_path / aeda_manifest_path.
|
||||
report_dir: directorio donde escribir los reports si write_report.
|
||||
Default "reports". Se crea si no existe.
|
||||
write_report: si True (default), escribe un report markdown + un JSON
|
||||
@@ -727,12 +740,51 @@ def profile_table(
|
||||
except Exception: # noqa: BLE001
|
||||
pdf_path = None
|
||||
|
||||
# Informe AutomaticEDA completo (PDF + PPTX por capitulos). Aditivo:
|
||||
# convive con emit_pdf (render_eda_pdf) sin sustituirlo. Construye el ctx
|
||||
# con los datos crudos para que modelos/timeseries/geospatial/agregacion
|
||||
# salgan poblados; degrada por clave si build_eda_render_ctx falla.
|
||||
aeda_pdf_path = None
|
||||
aeda_pptx_path = None
|
||||
aeda_manifest_path = None
|
||||
if emit_automatic:
|
||||
try:
|
||||
os.makedirs(report_dir, exist_ok=True)
|
||||
base_ctx = {
|
||||
"dataset_name": table,
|
||||
"source_origin": db_path,
|
||||
"storage": "DuckDB" if backend == "duckdb" else (
|
||||
"PostgreSQL" if backend == "postgres" else backend),
|
||||
}
|
||||
if run_llm:
|
||||
base_ctx.update({"run_cluster_llm": True,
|
||||
"run_geo_llm": True, "run_agg_llm": True})
|
||||
ctx = build_eda_render_ctx(
|
||||
db_path, table, prof, backend=backend, sample=sample,
|
||||
base_ctx=base_ctx)
|
||||
meta = {"title": f"EDA — {table}", "ctx": ctx}
|
||||
aeda_pdf_target = os.path.join(report_dir,
|
||||
f"aeda_{table}_{ts}.pdf")
|
||||
aeda_pptx_target = os.path.join(report_dir,
|
||||
f"aeda_{table}_{ts}.pptx")
|
||||
rpdf = render_automatic_eda_pdf(prof, aeda_pdf_target, meta) or {}
|
||||
rpptx = render_automatic_eda_pptx(
|
||||
prof, aeda_pptx_target, meta) or {}
|
||||
aeda_pdf_path = rpdf.get("path")
|
||||
aeda_pptx_path = rpptx.get("path")
|
||||
aeda_manifest_path = rpdf.get("manifest_path")
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
|
||||
return {
|
||||
"status": "ok",
|
||||
"profile": prof,
|
||||
"report_md_path": report_md_path,
|
||||
"report_json_path": report_json_path,
|
||||
"pdf_path": pdf_path,
|
||||
"aeda_pdf_path": aeda_pdf_path,
|
||||
"aeda_pptx_path": aeda_pptx_path,
|
||||
"aeda_manifest_path": aeda_manifest_path,
|
||||
}
|
||||
except Exception as e: # noqa: BLE001
|
||||
return {"status": "error", "error": str(e)}
|
||||
|
||||
Reference in New Issue
Block a user