Files
fn_registry/dev/issues/completed/0040-hybrid-extraction-pipeline.md
T

4.3 KiB

id, title, status, type, domain, scope, priority, depends, blocks, related, created, updated, tags
id title status type domain scope priority depends blocks related created updated tags
0040 Pipeline hibrido extraccion entidades+relaciones (regex + GLiNER/GLiREL + LLM fallback) completado feature
multi-app media
2026-05-17 2026-05-17

0040 — Pipeline hibrido extraccion entidades+relaciones (regex + GLiNER/GLiREL + LLM fallback)

Metadata

Campo Valor
ID 0040
Estado pendiente
Prioridad media
Tipo feature — Python pipeline (python/functions/pipelines/)

Dependencias

Bloquea-por: 0037 (IoC regex), 0038 (GLiNER), 0039 (GLiREL).

Desbloquea: flujo OSINT/grafo de produccion con coste predecible. Reusable desde apps en apps/*/ y desde notebooks en analysis/*/.


Objetivo

Pipeline que combina los tres extractores en cascada para obtener triplets (entidad, relacion, entidad) masivamente con buen coste/calidad:

  1. Capa regex (0037) — extrae IoCs tecnicos con precision 100%. Coste 0.
  2. Capa GLiNER (0038) — extrae entidades semanticas (person, organization, location, event...) zero-shot. Coste bajo.
  3. Capa GLiREL (0039) — relaciones zero-shot entre las entidades de capa 1+2.
  4. Capa LLM fallback (existente: extract_entities_llm + extract_relations_llm) — solo se invoca cuando confidence < threshold o sobre los chunks marcados como "complejos".

Output: (list[EntityCandidate], list[RelationCandidate]) listos para deduplicate_entitiesdeduplicate_relationsops_to_sigma_json / ops_to_rdf_triples.

Funcion a crear

Function ID Rol
extract_graph_hybrid_py_pipelines Pipeline orquestador. kind: pipeline, purity: impure, uses_functions: [...] con todos los anteriores

Contrato

def extract_graph_hybrid(
    chunks: list[str],
    entity_schema: list[dict],
    relation_types: list[str],
    gliner_model,                           # inyectado
    glirel_model,                           # inyectado
    llm_chat_json: Callable | None = None,  # opcional; si None, sin fallback LLM
    ioc_types: list[str] | None = None,     # None = todos
    confidence_threshold: float = 0.6,      # bajo este umbral se llama LLM
    languages: str = "Respond in Spanish.",
) -> tuple[list[EntityCandidate], list[RelationCandidate]]

Logica interna por chunk:

  1. extract_iocs(chunk, ioc_types)EntityCandidate con type_ref tecnico (ip/email/hash/...).
  2. extract_entities_gliner(chunk, entity_schema, gliner_model) → entidades semanticas.
  3. Si hay chunks con < N entidades o confidence baja y hay llm_chat_jsonextract_entities_llm sobre esos chunks; mergear.
  4. extract_relations_glirel(chunk, entities_del_chunk, relation_types, glirel_model).
  5. Si baja cobertura de relaciones y hay LLM → extract_relations_llm sobre el chunk.
  6. Devolver listas concatenadas (sin deduplicar — eso lo hace el caller con deduplicate_*).

Pureza

kind: pipelinepurity: impure (regla del registry). uses_functions: lista los 5+ extractores invocados. error_type: error_go_core.

Deliverables

  • python/functions/pipelines/extract_graph_hybrid.py + .md
  • Test de integracion en python/functions/pipelines/tests/test_extract_graph_hybrid.py con un corpus pequeño (2-3 textos OSINT realistas, mock del LLM).
  • .md documenta: cuando usar fallback LLM, latencia esperada por chunk, recomendacion de batch size.

Validacion

./fn run extract_graph_hybrid_py_pipelines

Bench end-to-end sobre 100 KB de texto:

  • Solo LLM (linea base actual): registrar tiempo y coste estimado.
  • Pipeline hibrido: registrar tiempo, coste (solo chunks con fallback) y delta de calidad vs solo-LLM.

Registrar resultados en el .md para tener referencia historica.

Notas

  • La deduplicacion fuzzy (Levenshtein + Union-Find) ya esta hecha en deduplicate_entities — NO replicar aqui.
  • IoCs y entidades semanticas pueden solapar (ej: GLiNER detecta apple.com como organization, regex como domain). Resolver dejando ambas con type_ref distinto y que deduplicate_entities con same_type_only=True no las mezcle. Documentar esta decision.
  • Pensar en un app apps/osint_extractor/ que use este pipeline + sigma viz como demo. Fuera de scope de este issue — proponer en proposals despues.