Este repositorio contiene el código utilizado para extraer, estructurar y clasificar las obligaciones ambientales contenidas en Resoluciones de Calificación Ambiental (RCA) del Sistema de Evaluación de Impacto Ambiental (SEIA) de Chile.
Fue desarrollado como parte del estudio "Uso de inteligencia artificial para la caracterización de la carga regulatoria ambiental de proyectos en desarrollo", de la Comisión Nacional de Evaluación y Productividad (CNEP) del Ministerio de Hacienda de Chile. El análisis de las 1.336 RCAs procesadas habría requerido aproximadamente un año de trabajo manual; este pipeline lo realiza de forma sistemática, escalable y reproducible.
Las RCAs son actos administrativos que aprueban proyectos de inversión, fijando las condiciones ambientales bajo las cuales deben ejecutarse. Cada RCA contiene cientos de obligaciones distribuidas en tablas y secciones de texto no estructurado. El objetivo de este pipeline es convertir ese texto en un dataset estructurado y analizable.
Los resultados finales se encuentran disponibles en Drive:
📂 Acceder a los resultados
/
├── archivos/ # RCAs en formato PDF (entrada del pipeline)
├── auxiliares/
│ ├── pas.xlsx # Listado de Permisos Ambientales Sectoriales
│ └── normativa*.xlsx # Normativa sectorial de referencia
├── resultados/
│ ├── doctr/ # Textos OCR (Parquet) — output etapa 1
│ ├── marcaje/ # Chunks marcados — output etapa 2
│ ├── gemini_ocr/ # Textos OCR vía Gemini — output etapa 3
│ ├── subconsiderandos/ # Tablas estructuradas — output etapa 4
│ ├── obligaciones/ # Obligaciones extraídas — output etapa 5
│ ├── intermedio/ # Archivos intermedios del postprocesamiento
│ └── postprocessing/ # Dataset final limpio — output etapa 6
├── seia.xlsx # Listado maestro de RCAs con metadatos
│
└── codigos/ # ← Este repositorio
├── 1_Doctr.ipynb
├── 2_Marcar.ipynb
├── 3_OCR_Pagado.ipynb
├── 4_subconsiderandos.ipynb
├── 4_aux/
│ ├── 4.1_Instrucciones.ipynb # Prompts para etapa 4
│ └── 4.2_Modelo_Datos.ipynb # Modelos Pydantic para etapa 4
├── 5_obligaciones.ipynb
├── 5_aux/
│ ├── 5.1_Instrucciones.ipynb # Prompts para etapa 5
│ └── 5.2_Modelo_Datos.ipynb # Modelos Pydantic para etapa 5
├── 6_postprocessing.ipynb
└── 6_aux/
├── 6.1_decretos_pas.ipynb # Separación por decretos y PAS
├── 6.2_duplicados_semanticos.ipynb
├── 6.3_contingencias_emergencias.ipynb
├── 6.4_fuentes.ipynb
├── 6.5_manuales.ipynb
└── 6.6_comprimir.ipynb
archivos/*.pdf
│
▼
[Etapa 1] 1_Doctr.ipynb
OCR dual: pdfplumber (texto nativo) → doctr (escaneados)
Output: resultados/doctr/Resultado_Consolidado.parquet
│
▼
[Etapa 2] 2_Marcar.ipynb
Identifica y marca las secciones relevantes del texto (mitigación,
PAS, seguimiento, contingencias, etc.)
Output: resultados/marcaje/chunk_*.parquet
│
▼
[Etapa 3] 3_OCR_Pagado.ipynb
OCR con Gemini para PDFs escaneados de baja calidad
Output: resultados/gemini_ocr/*.txt
│
▼
[Etapa 4] 4_subconsiderandos.ipynb
Extrae subconsiderandos estructurados usando GPT con structured output
Output: resultados/subconsiderandos/subconsiderandos_validos.xlsx
│
▼
[Etapa 5] 5_obligaciones.ipynb
Extrae obligaciones individuales de cada subconsiderando usando GPT
Output: resultados/obligaciones/gpt-4o-mini/obligaciones.xlsx
│
▼
[Etapa 6] 6_postprocessing.ipynb
Limpieza, deduplicación exacta y semántica, clasificación de
contingencias, normalización de fuentes normativas y compresión
Output: resultados/postprocessing/obligaciones_combinadas_corregidas.xlsx
Cada etapa lee el output de la anterior. Los notebooks *_aux/ contienen los prompts del sistema e instrucciones y los modelos Pydantic que estructuran las respuestas de los LLMs.
- Python 3.9+
- Clave de API de OpenAI (etapas 4, 5 y 6)
- Clave de API de Google (solo etapa 3, para OCR con Gemini)
pip install pandas numpy openpyxl openai python-dotenv pydantic transformers \
pdfplumber doctr-tf fuzzywuzzy python-Levenshtein tqdm docx2txtCrea un archivo .env en la raíz del proyecto con tus claves de API:
OPENAI_API_KEY=sk-...
GOOGLE_API_KEY=... # solo para etapa 3
Por defecto, cada notebook resuelve la raíz del proyecto como el directorio padre (..) asumiendo que se ejecuta desde la carpeta codigos/. Si lo ejecutas desde otro lugar, define la variable de entorno RCA_BASE_DIR:
# Linux / macOS
export RCA_BASE_DIR=/ruta/al/proyecto
# Windows (PowerShell)
$env:RCA_BASE_DIR = "C:\ruta\al\proyecto"Lee los PDFs de archivos/ aplicando una estrategia dual: primero intenta extraer el texto nativo con pdfplumber; si el documento es escaneado o el texto extraído es muy escaso, lo procesa con doctr (modelo CRNN/FAST). El resultado es un archivo Parquet con el texto por página de cada RCA.
Detecta las secciones canónicas de cada RCA (mitigación, plan de seguimiento, PAS, contingencias y emergencias, compromisos voluntarios, condiciones y exigencias) mediante fuzzy matching. El output son chunks de texto etiquetados por sección.
Para las páginas que no pudieron procesarse correctamente con doctr, utiliza la API de Gemini para realizar un OCR de mayor calidad. Complementa el output de la etapa 1.
Llama a GPT con structured output (modelos Pydantic en 4_aux/) para extraer las filas estructuradas que componen los subconsiderandos de cada sección, incluyendo campos como forma de cumplimiento, indicadores, normas, componente ambiental, fase del proyecto, entre otros.
Sobre los subconsiderandos estructurados, llama nuevamente a GPT para extraer y desglosar las obligaciones individuales. Maneja el proceso de forma incremental (checkpoint automático), dividiendo el texto en chunks según límites de tokens y deduplicando duplicados por numero_tabla.
Cadena de transformaciones aplicadas al dataset de obligaciones:
- Corrección de campos: mueve
tituloaresumendonde corresponde. - Eliminación de errores: descarta filas vacías o con valores genéricos (fuzzy matching).
- Deduplicación exacta: elimina duplicados por combinación de campos clave.
- Deduplicación semántica (
6_aux/6.2): usa embeddings de OpenAI para detectar obligaciones equivalentes expresadas de forma distinta. - Clasificación de contingencias (
6_aux/6.3): clasifica las obligaciones de la sección de contingencias y emergencias en tipologías y subtipologías (Riesgos Operacionales, Naturales, etc.) usando GPT con structured output. - Normalización de fuentes (
6_aux/6.4,6_aux/6.5): expande, estandariza y corrige las referencias normativas (decretos supremos, resoluciones, PAS), asociando cada obligación a su fuente de derecho. - Compresión final (
6_aux/6.6): agrupa todas las filas de una misma obligación en una única fila con columnasfuente_1,fuente_2, etc.
Este trabajo es parte de un esfuerzo más amplio de la CNEP por caracterizar la carga regulatoria ambiental en Chile. El dataset resultante permite medir la distribución de obligaciones por sección, tipo de medida, componente ambiental y fuente normativa, tanto para proyectos mineros como energéticos.
Para más información sobre el estudio y sus resultados, consulta el informe disponible en www.cnep.cl.
Este repositorio es publicado con fines de transparencia y reproducibilidad académica. El código puede reutilizarse libremente con atribución a la CNEP.