Saltar al contenido principal

Comunidades y Leiden

Las comunidades son la capa intermedia entre "puntos sueltos en un grafo" y "respuestas inteligentes a preguntas temáticas". Si el grafo es el esqueleto, las comunidades son los órganos: agrupaciones funcionales que dan estructura a la información.

El problema que resuelven​

Un grafo de 5.000 entidades es difícil de razonar. Una pregunta como "¿de qué trata todo esto?" no se responde mirando 5.000 puntos individuales — se responde mirando clústeres densamente conectados que representan temas coherentes.

Ahí entra el algoritmo Leiden.

Qué hace Leiden​

Leiden es un algoritmo de detección de comunidades en grafos. Toma como entrada un grafo (los nodos son entidades, las aristas son relaciones con peso), y devuelve una partición jerárquica de los nodos en grupos densos.

Densamente conectado quiere decir: muchas aristas adentro del grupo, pocas aristas hacia afuera. Eso suele coincidir con temas semánticos coherentes.

Tres propiedades importantes​

  1. Jerárquico: Leiden produce varios niveles de clústeres. Un nivel coarse (pocos grupos grandes) y niveles finos (muchos grupos chicos). En GRAIL elegimos qué nivel usar con community_level.

  2. Reproducible: con la misma semilla (community.seed en grail.yaml), la partición es determinística. Útil para tests y benchmarks.

  3. Multi-nivel inteligente: a diferencia de Louvain (su predecesor), Leiden garantiza que cada subcomunidad sea conexa y resuelve el problema de "resolution limit". Es decir, no fusiona artificialmente grupos chicos que deberían quedar separados.

Tres niveles, una decisión​

Después de correr Leiden, GRAIL te deja elegir qué granularidad usar:

community_levelComportamientoCuándo conviene
"coarsest" (default)Pocas comunidades grandesReportes globales temáticos amplios
"finest"Muchas comunidades chicasAnálisis detallado, dashboards
"all"Todas las jerarquíasCuando quieres ambas vistas
Un entero (ej. 2)Nivel específicoCasos avanzados

Configurable en grail.yaml:

community:
community_level: "coarsest"
min_report_size: 3 # ignora comunidades de < 3 entidades

Reportes de comunidad​

Una vez que tienes las comunidades, GRAIL le pide al LLM que escriba un reporte narrativo por cada una:

{
"title": "Sistema GES y guarantías de salud",
"summary": "Esta comunidad agrupa entidades relacionadas con el sistema GES...",
"findings": [
{
"summary": "FONASA cubre el 100% del costo...",
"explanation": "Según la Ley 19.966, FONASA tiene obligación de..."
}
],
"rank": 8.5
}

Este reporte es lo que global consulta. Sin él, "¿cuáles son los temas centrales?" sería irresoluble sin leer el corpus completo.

Carpetas como comunidades (modo memoria)​

En modo memoria, GRAIL no necesita correr Leiden para identificar comunidades — la estructura de carpetas bajo memories/ ya las declara:

memories/
├── work/
│ ├── clients/acme/ ← una comunidad
│ └── clients/zorp/ ← otra comunidad
├── personal/
│ └── learning/python/ ← una comunidad
└── decisions/
└── 2026-q2/ ← una comunidad

Cada entidad puede pertenecer a varias comunidades a la vez (multi-pertenencia). Acme puede aparecer en work/clients/acme/ pero también en decisions/2026-q2/.

Cuándo conviene correr consolidate​

Folders-as-communities funciona bien hasta cierto punto. Pero cuando el grafo crece, conviene combinar lo declarado con lo descubierto:

grail consolidate ./mi-memoria

Esto corre el análisis estructural sobre el grafo y propone:

  • discover_community: "Estas entidades están densamente conectadas pero no comparten carpeta — son una comunidad emergente".
  • split_folder: "Esta carpeta tiene dos clústeres distintos — convendría dividirla".

Tú decides aceptar o rechazar. Nada muta sin tu consentimiento.

Detalles técnicos​

ConfiguraciónDefaultPara qué
community.max_cluster_size10Límite superior de tamaño de cluster por nivel
community.use_lcctrueSi usar solo el componente conectado más grande
community.min_community_size1Comunidades más chicas se descartan
community.embedding_merge_eps0.95Umbral DBSCAN para mergear entidades casi-duplicadas antes de Leiden

Ver docs/glossary.md del repo para la lista completa.

Siguiente paso​