b8c760d004
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
108 lines
6.9 KiB
Markdown
108 lines
6.9 KiB
Markdown
---
|
||
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`.
|