P
ponce.work Dupla Tech & AI
4 min de lectura

Pipelines de GraphRAG

Lección Aprendida: Checkpointing e Idempotencia en Pipelines de GraphRAG con Neo4j En pipelines de indexación de grafos del conocimiento (GraphRAG), es muy común confundir dos conceptos fundamentales: 1. **Guardar los datos (Nodos y Relaciones):** Ne...

#Python
#Architecture

Lección Aprendida: Checkpointing e Idempotencia en Pipelines de GraphRAG con Neo4j

Fecha: 2026-08-26
Área: Arquitectura de Software / GraphRAG / Neo4j
Impacto: Evitar reprocesamiento costoso (tokens/tiempo) tras interrupciones en la ingesta de grafos.


1. El Problema: Persistencia de Datos ≠ Persistencia de Estado

En pipelines de indexación de grafos del conocimiento (GraphRAG), es muy común confundir dos conceptos fundamentales:

  1. Guardar los datos (Nodos y Relaciones): Neo4j persiste a disco cada batch mediante consultas MERGE. Si el proceso se interrumpe, los datos generados hasta ese instante no se pierden.
  2. Guardar el marcador de posición (Checkpoint): Saber cuál fue el último chunk o lote procesado exitosamente.

El síntoma del descuido

Si detienes el proceso de indexación hoy (ejemplo: al 86%), al reiniciar el script este vuelve a empezar desde el chunk 0. Aunque los datos viejos no se dupliquen gracias al MERGE, el pipeline volverá a llamar al LLM para extraer entidades y relaciones de todo el texto previo, malgastando tiempo y dinero en tokens de API.


2. El Patrón de Solución: Idempotent Resume Pattern

Para que un pipeline de ingesta sea resiliente a interrupciones, debe seguir una estrategia de chequeo previo a nivel de unidad atómica.

       ┌────────────────────────┐
       │     Siguiente Chunk    │
       └───────────┬────────────┘
                   │
                   ▼
      ¿`(book_id + chunk_index)`
       tiene status: PROCESSED?
        ┌──────────┴──────────┐
     SÍ │                     │ NO
        ▼                     ▼
┌──────────────┐     ┌────────────────┐
│ Saltear Chunk│     │ Enviar al LLM  │
│ (0 costo LLM)│     │  (Extracción)  │
└──────────────┘     └───────┬────────┘
                             │
                             ▼
                     ┌────────────────┐
                     │  Transacción   │
                     │   Atómica en   │
                     │     Neo4j      │
                     └────────────────┘

3. Principios Clave de Diseño

A. Clave de Identificación Única (Posicional > Hash)

  • Regla: Utilizar una clave natural determinista compuesta por book_id + chunk_index.
  • Por qué no usar hash(contenido): Dos secciones distintas o repetidas dentro de un mismo documento pueden tener texto idéntico y colisionar. La posición estructural es superior al hash del contenido.

B. Marcador de Estado (status: PROCESSED)

  • No alcanza con consultar si el nodo Chunk existe (MATCH (c:Chunk)). Un crash a mitad de un proceso de batch podría dejar el nodo creado pero sus entidades/relaciones incompletas.
  • Se debe usar explícitamente un atributo de estado para distinguir lo completo de lo que quedó a medias.

C. Transaccionalidad Atómica

Para garantizar la integridad del checkpoint, todas las operaciones de un batch deben ejecutarse dentro de la misma transacción de base de datos (session.execute_write):

  1. Crear/Actualizar la estructura del Libro y Chunks.
  2. Hacer MERGE de Entidades y Relaciones.
  3. Marcar el Chunk con status: 'PROCESSED'.
  4. Commit de la transacción.

Nota: Si ocurre un fallo en cualquier paso del batch, la transacción realiza un rollback automático y el chunk permanece sin marcar, permitiendo un reintento limpio al reiniciar.


4. Anti-Patrones y Buenas Prácticas de Ingeniería

  • Evitar Sobre-Ingeniería: No se requieren orquestadores pesados como Airflow, Prefect o Temporal.io para pipelines locales o mono-nodo (ej. scripts en una OrangePi). El checkpoint in-process mediante consultas Cypher a Neo4j es suficiente, liviano y altamente eficiente.
  • Evitar llamados Cypher desarticulados: No flushear datos en múltiples commits independientes dentro del mismo batch (booknodosrelaciones). Todo debe empaquetarse en un único bloque atómico.

5. Checklist para Futuras Indexaciones de Grafos

  • Definir una clave natural única para cada fragmento de texto (doc_id + chunk_idx).
  • Crear un índice en Neo4j sobre la clave de los Chunks para que la verificación sea instantánea.
  • Implementar la consulta previa: MATCH (c:Chunk {book_id: $b, chunk_index: $i, status: 'PROCESSED'}) RETURN c.
  • Envolver la extracción del LLM y la persistencia en Cypher dentro de un flujo idempotente con status: 'PROCESSED'.