docs: issues 0041 (split thresholds) + 0042 (GLiNER2), supersedes mREBEL
Cierra el ciclo del analysis gliner_glirel_tuning: documenta en app.md el pipeline NER+RE disponible en el registry y abre los dos issues que faltan para cablearlo en extract_graph_hybrid + panel paste_extract. Archiva el 0042 original (mREBEL) tras la decision a favor de GLiNER2 (Apache 2.0, joint NER+RE, 20-30x mas rapido en CPU). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
---
|
||||
id: 0041
|
||||
title: Split confidence_threshold en entity_threshold + relation_threshold
|
||||
status: pending
|
||||
priority: medium
|
||||
created: 2026-05-04
|
||||
parent: 0013
|
||||
---
|
||||
|
||||
## Objetivo
|
||||
|
||||
`extract_graph_hybrid` y el panel `paste_extract` actualmente comparten un solo `confidence_threshold`. El analisis empirico (`projects/osint_graph/analysis/gliner_glirel_tuning/`) demuestra que las dos capas tienen distribuciones de score radicalmente distintas:
|
||||
|
||||
- **GLiNER** emite scores 0.92-0.99 en narrativa, 0.5-0.95 en OSINT. Threshold sano: **0.50-0.70**.
|
||||
- **GLiREL** emite scores 0.05-0.34. Threshold sano: **0.10-0.20**.
|
||||
- **mREBEL** (issue 0042) emite confianzas implicitas via `num_beams` — distinto modelo, distinto rango.
|
||||
|
||||
Un solo threshold global o filtra todas las relaciones (`t=0.6` mata GLiREL) o satura el grafo de entidades dudosas (`t=0.15` deja pasar entidades borderline).
|
||||
|
||||
## Cambios
|
||||
|
||||
### En `python/functions/pipelines/extract_graph_hybrid.py`
|
||||
|
||||
Aceptar dos thresholds opcionales con back-compat:
|
||||
|
||||
```python
|
||||
def extract_graph_hybrid(
|
||||
chunks, entity_schema, relation_types,
|
||||
gliner_model, glirel_model,
|
||||
llm_chat_json=None,
|
||||
confidence_threshold=0.6, # legacy, valor por defecto si los dos siguientes no se pasan
|
||||
entity_threshold=None, # nuevo — gobierna GLiNER + LLM-fallback de entidades
|
||||
relation_threshold=None, # nuevo — gobierna GLiREL + LLM-fallback de relaciones
|
||||
):
|
||||
if entity_threshold is None:
|
||||
entity_threshold = confidence_threshold
|
||||
if relation_threshold is None:
|
||||
relation_threshold = confidence_threshold
|
||||
...
|
||||
```
|
||||
|
||||
Pasar cada threshold a su capa respectiva (GLiNER `predict_entities(threshold=entity_threshold)`, GLiREL `predict_relations(threshold=relation_threshold)`).
|
||||
|
||||
### En `enrichers/paste_extract/run.py`
|
||||
|
||||
Aceptar `entity_threshold` y `relation_threshold` en `params`. Mantener `confidence_threshold` por compatibilidad. Defaults sugeridos en el manifest:
|
||||
|
||||
```yaml
|
||||
params:
|
||||
text: { type: string, required: true }
|
||||
use_hybrid: { type: bool, default: true }
|
||||
entity_threshold: { type: float, default: 0.50 }
|
||||
relation_threshold: { type: float, default: 0.15 }
|
||||
```
|
||||
|
||||
### En `extract_panel.cpp` / `extract_panel.h`
|
||||
|
||||
Reemplazar el slider unico por **dos sliders verticales** (mas el toggle `use_hybrid`):
|
||||
|
||||
```
|
||||
┌─ Extract config ─────────────────────────────┐
|
||||
│ ☑ Use hybrid (GLiNER + GLiREL) │
|
||||
│ │
|
||||
│ Entity threshold 0.50 [==== ] │
|
||||
│ Relation threshold 0.15 [== ] │
|
||||
└──────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Defaults: `entity_threshold=0.50`, `relation_threshold=0.15`.
|
||||
|
||||
### Tests
|
||||
|
||||
`tests/test_paste_extract.py`:
|
||||
|
||||
- Test que pasar solo `confidence_threshold` mantiene comportamiento legacy.
|
||||
- Test que pasar `entity_threshold=0.5, relation_threshold=0.1` aplica thresholds distintos a cada capa.
|
||||
- Test que la UI envia los dos parametros correctamente al subprocess.
|
||||
|
||||
## Definicion de hecho
|
||||
|
||||
- Pego un texto y veo entidades con confianza 0.5+ Y relaciones con confianza 0.15+ por defecto.
|
||||
- Mover el slider de relaciones a 0.05 me muestra mas relaciones (potencialmente espurias) sin afectar las entidades.
|
||||
- Mover el slider de entidades a 0.9 reduce las entidades sin tocar las relaciones.
|
||||
- El test legacy (`confidence_threshold` solo) sigue pasando.
|
||||
|
||||
## Datos que respaldan los defaults
|
||||
|
||||
Notebook `01_gliner_glirel_tuning.ipynb`, tabla "GLiNER thresholds" (corpus es_corporate, en_corporate, es_journalism). Notebook `02_e2e_spanish_graph.ipynb`, comparacion recall (t=0.15) vs precision (t=0.30) — ambos modos producen grafos validos por separado, no hay un punto medio compartido bueno.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Optimizacion automatica de thresholds (issue futuro).
|
||||
- Threshold por tipo de entidad (`person` mas estricto que `location`) — issue futuro.
|
||||
- Calibracion automatica con feedback del usuario (al hacer Apply, ajustar thresholds aprendiendo).
|
||||
|
||||
## Reversibilidad
|
||||
|
||||
Si los nuevos defaults producen mas ruido del esperado, basta con cambiarlos en el manifest. El esquema de dos thresholds es estrictamente mas expresivo que el legacy.
|
||||
|
||||
## Relacionado
|
||||
|
||||
- Issue 0042 — sustituir GLiREL por mREBEL. Si 0042 va primero, este issue cambia: `relation_threshold` se vuelve menos relevante (mREBEL no usa threshold continuo del mismo modo) pero `entity_threshold` sigue siendo necesario.
|
||||
Reference in New Issue
Block a user