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...
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:
- Guardar los datos (Nodos y Relaciones): Neo4j persiste a disco cada
batchmediante consultasMERGE. Si el proceso se interrumpe, los datos generados hasta ese instante no se pierden. - 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
Chunkexiste (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):
- Crear/Actualizar la estructura del Libro y Chunks.
- Hacer
MERGEde Entidades y Relaciones. - Marcar el
Chunkconstatus: 'PROCESSED'. - 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 (
book→nodos→relaciones). 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'.