Files
2026-05-04 23:44:11 +02:00

108 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: gliner_glirel_tuning
lang: py
domain: datascience
description: "Estudio empirico de GLiNER y GLiREL: distribucion de scores, sensibilidad a threshold/top_k/labels/idioma, calibracion de thresholds para extract_graph_hybrid"
tags: [nlp, gliner, glirel, thresholds]
uses_functions: []
uses_types: []
framework: "jupyterlab"
entry_point: "notebooks/main.ipynb"
dir_path: "projects/osint_graph/analysis/gliner_glirel_tuning"
repo_url: ""
---
## Notas
Estudio empirico de GLiNER y GLiREL: distribucion de scores, sensibilidad a threshold/top_k/labels/idioma, calibracion de thresholds para extract_graph_hybrid.
Tras varias jornadas el alcance se amplio: ahora cubre **6 modelos** (GLiNER, GLiREL, mREBEL, REBEL, GLiNER2, NuExtract 2.0-2B) + **OpenIE schema-less ES** con spaCy + reglas de dependencia. La conclusion ganadora vive en el vault `osint_nlp_models`.
## Notebooks (orden cronologico — ejecutados con outputs guardados)
| # | Notebook | Hallazgo clave |
|---|---|---|
| 01 | `notebooks/01_gliner_glirel_tuning.ipynb` | Calibracion thresholds GLiNER+GLiREL. Multilingue: labels EN funcionan sobre texto ES. snake_case verbal labels >> natural_long en GLiREL. |
| 02 | `notebooks/02_e2e_spanish_graph.ipynb` | E2E ES + grafo. Descubrimiento: GLiREL emite 51 falsos positivos en es_corporate_short a t=0.15; a t=0.30 solo 1 relacion (tambien falsa). **No hay sweet spot** en castellano. |
| 03 | `notebooks/03_mrebel_vs_glirel.ipynb` | mREBEL frase-a-frase: 8 tripletas crudas, 5 alineables, 4 inequivocamente correctas. Cero falsos absurdos. **PERO** licencia CC BY-NC-SA 4.0 (no comercial). |
| 04 | `notebooks/04_gliner2_winner.ipynb` ⭐ | GLiNER2 `fastino/gliner2-large-v1` (Apache 2.0, 340M, NER+RE joint). 6/8 correctas vs 4/5 mREBEL, 20× mas rapido. Funciona en OSINT castellano. **Modelo elegido**. |
| 05 | `notebooks/05_long_text_and_pdf.ipynb` | Pipeline PDF E2E sobre `politica_proteccion_datos.pdf` (BBVA, 89.882 chars). 67 chunks, 378 entidades, 54 relaciones, 97.9s total. |
| 06 | `notebooks/06_improvements.ipynb` | Mejoras GLiNER2: threshold 0.3 (vs 0.5 default) → +187% relaciones (71→204). Coref normalize+substring → 18% aislados (389→318). Descripciones por relacion **sin efecto**. `batch_extract` 25% **mas lento** en CPU. |
| 07 | `notebooks/07_nuextract_vs_gliner2.ipynb` | NuExtract 2.0-2B GPU sobre RTX 3070: load 7.1s, T1 2.88s vs CPU 25s (8.7×). PDF entero extrapolado 5.2 min vs GLiNER2 CPU 2.2 min — **2.6× mas lento incluso con GPU**. Calidad similar. **Descartado por velocidad**. |
| 08 | `notebooks/08_improving_gliner2.ipynb` | Label naming: snake_case verbal >> camelCase >> espacios. `include_confidence=True` permite threshold por relacion. Post-filter typed gratis y decisivo. GLiREL+allowed_head/tail post-hoc revive el modelo como complemento. |
| 09 | `notebooks/09_spacy_es_openie.ipynb` | spaCy ES `es_core_news_md` + reglas de dependencia: OpenIE schema-less en castellano. `(Enmanuel, querer, Ashlly)` con verbo del texto, 5ms/frase. Reglas pendientes V2: pasiva refleja, copulares, coref pronombres. |
## Hallazgos operativos consolidados
### Stack final recomendado para `graph_explorer`
```
Capa 1 (NER + RE schema-driven):
GLiNER2 (Apache 2.0)
+ threshold=0.3 (vs default 0.5)
+ snake_case verbal labels
+ include_confidence=True (para tuning fino)
Capa 2 (post-procesado puro, gratis):
filter_relations_by_entity_types ← descarta absurdos (Madrid president_of Persona)
merge_entity_aliases ← BBVA ⊂ Banco Bilbao Vizcaya...
aggregate_extraction_results ← dedupe + counter sobre N chunks
Capa 3 (chunking para texto largo):
chunk_with_overlap (max_chars=1500, overlap_sentences=2)
Capa 4 opcional (OpenIE schema-less complementaria):
spaCy es_core_news_md + extract_triples_spacy_es
```
Todo el stack esta como **funciones del registry** tras esta sesion (10 funciones en core/datascience/pipelines).
### Decisiones registradas en el vault
`vaults/osint_nlp_models/decisions/`:
- `2026-05-04-mrebel-over-glirel.md` — primera decision (mañana): mREBEL gana a GLiREL pero caveat licencia.
- `2026-05-04-gliner2-over-mrebel.md` ⭐ — decision final (tarde): GLiNER2 reemplaza a todos por velocidad + Apache 2.0 + multilingue ES nativo.
- `2026-05-04-license-constraint.md` — plan de contingencia si en algun momento se necesita comercial sin Apache 2.0.
### Modelos descartados y por que
| Modelo | Razon |
|---|---|
| **GLiREL** `jackboyla/glirel-large-v0` | 51 falsos positivos en ES corporate, sin sweet spot. Util quiza en EN tecnico (no probado). |
| **mREBEL large/base** | CC BY-NC-SA 4.0 (bloqueante comercial) + 25× mas lento que GLiNER2. Queda como fallback. |
| **REBEL EN-only** | Apache 2.0 pero requiere traducir ES→EN, +500ms-1s + riesgo nombres propios. |
| **NuExtract 2.0-2B** | 2.6× mas lento que GLiNER2 incluso con GPU. Mejor para "ficha rica" por entidad pero excesivo para grafo. |
| **triplet-extract EN-only** | Pierdes verbos del texto castellano al traducir; `(quiere, loves)` no es lo mismo. |
## Pendientes (tracked en issues)
- `dev/issues/0050-jupyter-exec-collab-client-failure.md` — bug `jupyter_exec` con cliente colaborativo.
- `projects/osint_graph/apps/graph_explorer/issues/0041-split-confidence-thresholds.md` — split `confidence_threshold` en `entity_threshold` + `relation_threshold`.
- `projects/osint_graph/apps/graph_explorer/issues/0042-gliner2-unified-extractor.md` ⭐ — sustituir GLiREL por GLiNER2 en `extract_graph_hybrid` del panel `paste_extract`.
- `dev/issues/0051-extraction-pipeline-followups.md` — funciones aun por construir (NuExtract loader, extract_graph_from_pdf, spaCy ES V2 rules, kernel startup fix). Ver issue.
## Como reproducir cualquier experimento
Cada notebook tiene su `build_notebook_*.py` y, cuando es pesado, su `run_*.py` que vuelca a JSON:
```bash
cd projects/osint_graph/analysis/gliner_glirel_tuning
./.venv/bin/python3 -u run_benchmark_v2.py # genera benchmark_v2.json
./.venv/bin/python3 build_notebook_gliner2.py # genera notebooks/04_gliner2_winner.ipynb
IPYTHONDIR=$(pwd)/.ipython ./.venv/bin/jupyter nbconvert \
--to notebook --execute notebooks/04_gliner2_winner.ipynb \
--output 04_gliner2_winner.ipynb --ExecutePreprocessor.timeout=600
```
JSONs de resultados (todos en la raiz del analysis):
- `benchmark_v2.json` — GLiNER2 sobre 4 corpora.
- `improvements.json` — 5 configs A-E sobre el PDF + coref.
- `nuextract_results.json` — NuExtract CPU baseline + GPU.
- `nuextract_full.json` — NuExtract GPU sobre PDF entero (179 chunks parsed OK).
- `mrebel_results.json` — mREBEL sobre es_corporate_short.
- `openie_results.json` — comparativa 3 paradigmas (triplet-extract EN, spaCy ES, GLiNER2).
## Playground
`projects/osint_graph/analysis/gliner_glirel_tuning/playground/` — server FastAPI + frontend Sigma.js sirviendo en `localhost:7878`. Aplica todo el stack de capas 1-3 sobre cualquier texto que pegues. Ver `playground/server.py` y `playground/index.html`.