fad4006f60
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
92 lines
3.3 KiB
Markdown
92 lines
3.3 KiB
Markdown
---
|
|
id: "0039"
|
|
title: "GLiREL relation extractor (zero-shot relations → triplets)"
|
|
status: completado
|
|
type: feature
|
|
domain: []
|
|
scope: multi-app
|
|
priority: media
|
|
depends: []
|
|
blocks: []
|
|
related: []
|
|
created: 2026-05-17
|
|
updated: 2026-05-17
|
|
tags: []
|
|
---
|
|
# 0039 — GLiREL relation extractor (zero-shot relations → triplets)
|
|
|
|
## Metadata
|
|
|
|
| Campo | Valor |
|
|
|-------|-------|
|
|
| **ID** | 0039 |
|
|
| **Estado** | pendiente |
|
|
| **Prioridad** | media |
|
|
| **Tipo** | feature — Python (`python/functions/datascience/`) |
|
|
|
|
## Dependencias
|
|
|
|
Bloquea-por: **0038** (las entidades vienen del extractor GLiNER o del LLM). Recomendado leer `extract_relations_llm_py_datascience` y `relation_candidate_py_datascience` para mantener contrato.
|
|
|
|
**Desbloquea:** 0040 (pipeline hibrido), extraccion de triplets `(sujeto, predicado, objeto)` masiva sin LLM.
|
|
|
|
---
|
|
|
|
## Objetivo
|
|
|
|
Wrapper sobre GLiREL (`jackboyla/glirel-large-v0`) que, dadas entidades ya extraidas y un set de tipos de relacion, devuelve `list[RelationCandidate]` con el mismo contrato que `extract_relations_llm`. Output natural en triplets `(from, relation_type, to)` reusables por `deduplicate_relations`, `merge_graphs` y `ops_to_sigma_json`.
|
|
|
|
## Funciones a crear
|
|
|
|
| Function ID | Rol |
|
|
|---|---|
|
|
| `glirel_load_model_py_datascience` | Carga + cachea el modelo. `purity: impure` |
|
|
| `extract_relations_glirel_py_datascience` | Extractor de relaciones. `purity: impure` |
|
|
|
|
## Contrato
|
|
|
|
```python
|
|
def glirel_load_model(
|
|
model_name: str = "jackboyla/glirel-large-v0",
|
|
device: str = "auto",
|
|
) -> "GLiREL": ...
|
|
|
|
def extract_relations_glirel(
|
|
text: str,
|
|
entities: list[EntityCandidate], # del paso anterior (GLiNER o LLM)
|
|
relation_types: list[str], # ej: ["works_for","owns","communicated_with"]
|
|
model: "GLiREL",
|
|
threshold: float = 0.5,
|
|
max_pairs: int = 0, # 0 = todas las parejas
|
|
) -> list[RelationCandidate]
|
|
```
|
|
|
|
GLiREL necesita los spans de las entidades (`attributes["start"]`/`end`), por eso 0038 los expone. Si la entidad viene del LLM y no tiene offsets, se buscan con `text.find(name)` como fallback (con warning).
|
|
|
|
## Pureza
|
|
|
|
Ambas `purity: impure`. `error_type: error_go_core`.
|
|
|
|
## Deliverables
|
|
|
|
- `python/functions/datascience/glirel_load_model.py` + `.md`
|
|
- `python/functions/datascience/extract_relations_glirel.py` + `.md`
|
|
- Tests con 2-3 textos donde las relaciones son explicitas (`X trabaja en Y`, `A llamo a B`), schema de 3-5 relation types.
|
|
- `pyproject.toml`: añadir `glirel` al extra `nlp`.
|
|
- Documentar limitacion: GLiREL es bueno para relaciones explicitas en el texto, malo para razonamiento implicito. Para esos casos seguir usando LLM (eso es lo que orquesta 0040).
|
|
|
|
## Validacion
|
|
|
|
```bash
|
|
./fn run extract_relations_glirel_py_datascience
|
|
```
|
|
|
|
Comparar precision/recall vs `extract_relations_llm` sobre el mismo corpus + entidades. Registrar en el `.md`.
|
|
|
|
## Notas
|
|
|
|
- Triplets: el output es `RelationCandidate(from_name, to_name, relation_type, ...)`. `from_name`/`to_name` deben coincidir con entidades del input — si no, descartar (igual que la version LLM).
|
|
- Si una `relation_type` no aparece en el output, no es un error — solo significa que GLiREL no encontro evidencia.
|
|
- `deduplicate_relations_py_datascience` ya soporta este formato sin cambios.
|
|
- Ver issue 0040 para combinar GLiREL con LLM-fallback en el mismo pipeline.
|