# Cómo ejecutar el proyecto EKG-Python

Pasos para ejecutar el proyecto EKG-Python de principio a fin, verificados
sobre Python 3.12.

El material de esta carpeta (`material/proyecto/`) contiene el comprimido
`EKG-Python-proyecto.zip`. Al descomprimirlo se obtienen dos directorios que
son la raíz de trabajo de esta guía:

```
EKG-Python-proyecto/
├── grafo-ekg/     # Grafo RDF/OWL + SPARQL + SHACL (CPU, sin GPU)
└── sistema-rag/          # RAG + fine-tuning QLoRA del Sistema B (requiere GPU)
```

Descomprime y sitúate en la raíz:

```bash
unzip EKG-Python-proyecto.zip -d EKG-Python-proyecto
cd EKG-Python-proyecto
```

---

## (a) Requisitos

- Python 3.12 obligatorio; las versiones de las librerías están fijadas para
  ese intérprete.
- `pip` actualizado y módulo `venv`.
- Para los acentos y los caracteres SPARQL en la salida de consola se fija
  siempre la codificación UTF-8:

  ```bash
  export PYTHONIOENCODING=utf-8
  ```

  En Windows (PowerShell) el equivalente es:

  ```powershell
  $env:PYTHONIOENCODING = "utf-8"
  ```

- La parte del grafo (b) funciona en CPU, sin tarjeta gráfica.
- La parte RAG + fine-tuning (c) requiere una GPU NVIDIA. El proyecto está
  preparado para una RTX 5090 (arquitectura Blackwell, `sm_120`) con CUDA 12.8.

Comprueba la versión del intérprete antes de empezar:

```bash
python --version          # debe imprimir Python 3.12.x
```

---

## (b) Parte del GRAFO

Esta parte está verificada y ejecuta de principio a fin; produce las cifras
canónicas que se citan más abajo.

### 1. Entorno virtual e instalación

Desde la raíz del proyecto:

```bash
export PYTHONIOENCODING=utf-8
python -m venv .venv-grafo
source .venv-grafo/bin/activate          # Windows: .venv-grafo\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r grafo-ekg/requirements.txt
```

`grafo-ekg/requirements.txt` instala exactamente:

```
rdflib==7.6.0
owlrl==7.1.4
pyshacl==0.31.0
networkx==3.6.1
requests==2.34.2
```

### 2. Inferencia OWL-RL — `inferir.py`

```bash
cd grafo-ekg
python scripts/inferir.py
```

Carga el grafo canónico `ontologia/ekg-python-150.ttl`, aplica el cierre
deductivo OWL-RL y escribe `salidas/ekg-python-inferido.ttl`. Salida esperada:

```
Triples afirmados : 1772
Triples inferidos : 3014
Triples totales   : 4786
Grafo con cierre OWL-RL escrito en: .../salidas/ekg-python-inferido.ttl
```

El razonador lleva el grafo de 1772 → 4786 tríos.

### 3. Validación SHACL — `validar.py`

```bash
python scripts/validar.py
```

Valida tres grafos contra `ontologia/shapes-ekg.ttl` y escribe los informes en
`salidas/`. Salida esperada:

```
[Grafo principal] CONFORME  (violaciones: 0)  -> informe-shacl.txt
[Grafo + ejemplo invalido] NO CONFORME  (violaciones: 6)  -> informe-shacl-invalido.txt
[Grafo ampliado (150 conceptos)] CONFORME  (violaciones: 0)  -> informe-shacl-150.txt
```

El grafo principal es SHACL conforme, con 0 violaciones; el control negativo
(`ontologia/ejemplo-invalido.ttl`, con errores deliberados) produce exactamente
6 violaciones, lo que confirma que las formas detectan los datos mal formados.

### 4. Consultas SPARQL — `consultar.py`

```bash
python scripts/consultar.py                    # con inferencia OWL-RL
python scripts/consultar.py --sin-inferencia   # sin inferencia (contraste)
```

Ejecuta las consultas `.rq` de `consultas/` (omite la federada `08` y el
`UPDATE` `09`) y escribe `salidas/resultados-consultas-inferido.txt` y
`salidas/resultados-consultas-base.txt`. La evidencia de la inferencia RDFS es
la consulta `02_inferencia_conceptos.rq`, que devuelve 0 filas sin inferencia y
26 con inferencia.

### 5. Exportación a otros formatos

Si necesitas el grafo en otros formatos (opcional):

```bash
python scripts/exportar.py     # genera JSON-LD, N-Triples y RDF/XML en salidas/
```

Al terminar la parte del grafo, desactiva el entorno:

```bash
deactivate
cd ..
```

---

## (c) Parte RAG + fine-tuning

Esta parte ejecuta el Sistema B, el modelo base Qwen2.5-Coder-7B-Instruct
afinado con QLoRA para generar retroalimentación pedagógica de código en
español. Requiere una GPU NVIDIA, probado en RTX 5090 (32 GB).

### 1. Entorno virtual

```bash
export PYTHONIOENCODING=utf-8
python -m venv .venv-rag
source .venv-rag/bin/activate            # Windows: .venv-rag\Scripts\Activate.ps1
python -m pip install --upgrade pip
```

### 2. Instalar PyTorch desde el índice CUDA

La RTX 5090 (Blackwell, `sm_120`) necesita la build de CUDA 12.8. La rueda
publicada en PyPI es solo CPU y no sirve. Instala primero `torch` desde el
índice CUDA y después el resto de dependencias:

```bash
pip install torch --index-url https://download.pytorch.org/whl/cu128
pip install -r sistema-rag/requirements.txt
```

`sistema-rag/requirements.txt` incluye, entre otras,
`transformers==5.12.1`, `peft==0.19.1`, `datasets==5.0.0`,
`accelerate==1.14.0`, `bitsandbytes==0.49.2`, `safetensors==0.8.0`,
`sentencepiece==0.2.1`, `trl==1.6.0`, además de `rdflib`/`owlrl`/`pyshacl`
(para el RAG sobre el grafo) y `fastapi`/`uvicorn`/`pydantic` (interfaz web).

Comprueba que PyTorch ve la GPU:

```bash
python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))"
```

Debe imprimir una versión `...+cu128`, `True` y el nombre de la tarjeta.

### 3. Ejecutar la inferencia del Sistema B — `inferir_b.py`

```bash
cd sistema-rag
python scripts/inferir_b.py
```

La primera ejecución descarga el modelo base Qwen2.5-Coder-7B-Instruct desde
Hugging Face (no se redistribuye con el proyecto), lo carga en 4 bits (NF4) y
aplica encima el adaptador QLoRA `modelos/qlora-feedback-v3`. Para analizar tu
propio código:

```bash
python scripts/inferir_b.py --codigo "def suma(xs):
    total = 0
    for i in range(1, len(xs)):
        total += xs[i]
    return total"
```

Imprime el diagnóstico formativo (tipo de error, concepto implicado,
explicación divulgativa y técnica).

> Detalle de los adaptadores entrenados y de las formas alternativas de
> cargarlos (PEFT/Transformers y Ollama): ver `../modelos/MODELOS.md`.

### 4. Interfaz web

El proyecto trae también una interfaz web con FastAPI, opcional:

```bash
cd sistema-rag/web
uvicorn app:app --host 127.0.0.1 --port 8000
```

Abre `http://127.0.0.1:8000`. La interfaz compara sistemas; los sistemas A/C y
los modelos juez se sirven por Ollama (`http://localhost:11434`), por lo que
Ollama debe estar en marcha si quieres usar esas rutas (ver `MODELOS.md`).

### Requisitos de GPU

- Modelo base en 4 bits NF4: ~6 GB de VRAM.
- Fine-tuning QLoRA del 7B: cabe holgado en los 32 GB de la RTX 5090.
- Para CPU pura no hay ruta soportada de inferencia del 7B en este proyecto.

---

## (d) Notebook de Jupyter

El proyecto incluye un notebook que recorre el grafo de extremo a extremo
(`grafo-ekg/notebook/EKG-Python-proyecto-completo.ipynb`).

Con el entorno del grafo activado (apartado b.1), instala Jupyter y ábrelo:

```bash
export PYTHONIOENCODING=utf-8
source .venv-grafo/bin/activate          # Windows: .venv-grafo\Scripts\Activate.ps1
pip install jupyterlab
jupyter lab grafo-ekg/notebook/EKG-Python-proyecto-completo.ipynb
```

(Alternativa equivalente: `jupyter notebook <ruta-al-.ipynb>`.) Ejecuta las
celdas en orden con *Run All*; reproducen la inferencia, la validación SHACL y
las consultas SPARQL descritas en el apartado (b).

---

## Orden recomendado

1. (a) Verificar Python 3.12 y fijar `PYTHONIOENCODING=utf-8`.
2. (b) Grafo: `inferir.py` → `validar.py` → `consultar.py` (verificado).
3. (d) Notebook: reproducir el grafo de forma interactiva.
4. (c) RAG + fine-tuning: instalar `torch` cu128, requirements y `inferir_b.py`
   (requiere GPU).
