Source document
Protocolo de crecimiento
Spanish text, transcribed from the repository. The unformatted
source is
growth-protocol.md.
Cómo decide el enjambre qué hacer con un nodo que se acaba de unir, sin reiniciar nada y sin apagar ningún pipeline.
1. El problema
Un clúster doméstico no es estático: un portátil se enciende, un mini-PC se añade, un móvil deja de estar disponible. Reiniciar el enjambre cada vez que cambia el hardware convierte el sistema en un juguete.
El protocolo de crecimiento responde a una sola pregunta: dado un nodo nuevo y el plan actual, ¿cuál es el mejor uso para ese hardware?
2. Puntuación de extensión (FSENNL)
El marco de referencia es FSENNL (Federated Self-Expanding Neural Network Learning): decide cuándo y dónde expandir combinando la información de Fisher de los parámetros con el perfil del dispositivo.
El plano de control solo puede observar la parte del dispositivo, así que implementa esa mitad:
score = w_vram · vram_gb
+ w_ram · ram_gb
+ w_npu · npu_tops
- w_lat · latency_ms
| Peso | Valor por defecto | Motivo |
|---|---|---|
w_vram | 1.0 | Es el recurso escaso: los expertos y el contexto compiten por ella. |
w_ram | 0.25 | Abundante en equipos domésticos; sirve para expertos, no para latencia. |
w_npu | 1.5 | Un nodo con NPU ejecuta un fragmento completo sin competir por el bus de la GPU. |
w_lat | 0.05 | 20 ms de latencia cuestan una capa de capacidad: la red es el límite físico. |
La puntuación se recalcula en el plano de control, no se acepta la que anuncia el nodo. Un nodo puede estar desactualizado o medir mal su propia latencia, y el crecimiento no debe depender de una cifra que no se puede auditar. El campo extension_score del contrato Protobuf es informativo.
Umbral de extensión
ExtensionWeights::extend_threshold (6.0 por defecto) separa a los nodos que pueden sostener un tramo nuevo de los que solo pueden replicar. Un nodo por debajo del umbral no es inútil: sumando réplicas mejora el throughput y la tolerancia a fallos.
3. La decisión
growth_decision(new_node, current_plan) es una cascada explícita, en orden de prioridad:
flowchart TD
A[Nodo nuevo] --> B{¿Faltan pipelines<br/>para lo pedido?}
B -->|Sí| R1[Replicate<br/>copia completa]
B -->|No| C{¿Réplicas medias<br/>< objetivo 2.0?}
C -->|Sí| R2[Replicate<br/>reduce riesgo de failover]
C -->|No| D{¿Telomerasa + modelo local<br/>y score ≥ umbral?}
D -->|Sí| E[AddExpert<br/>aporta conocimiento propio]
D -->|No| F{¿score ≥ umbral?}
F -->|Sí| G[ExtendDepth<br/>capas nuevas al final]
F -->|No| R3[Replicate<br/>nodo débil, solo redundancia]
Por qué este orden
- Faltan pipelines — es la ganancia más directa: una copia entera más del modelo. Nada de lo demás compite con eso.
- Faltan réplicas — sin dos copias por capa, un failover no tiene a quién recurrir. La redundancia es requisito del Pilar A, no un lujo.
- Aporta inteligencia — si el nodo ya trae una IA local con telomerasa y además tiene capacidad, su valor no es más cómputo del mismo modelo, sino conocimiento distinto. Ese es el caso de Composition of Experts.
- Puede alargar — con capacidad suficiente, aporta capas nuevas al final del pipeline (Growing Transformers: composición modular sobre un sustrato congelado).
- Nodo débil — replicar es lo único honesto que se puede ofrecer.
4. Las tres acciones
Replicate
{
"action": "replicate",
"pipeline_id": "ncm-base#0",
"layers": [{ "first": 0, "last": 7 }, { "first": 8, "last": 11 }],
"reason": "réplicas medias 1.00 < objetivo 2.00; laptop reduce el riesgo de failover"
}
El orquestador re-ejecuta plan_swarm con el nodo añadido y target_pipelines + 1. El plan nuevo se valida antes de desplegarse; si no encaja, no se toca nada.
ExtendDepth
{
"action": "extend_depth",
"pipeline_id": "ncm-base#0",
"new_layers": 8,
"reason": "puntuación 20.90 >= 6.00; beast extiende el modelo 8 capas"
}
Las capas nuevas son proporcionales a la VRAM declarada (layers_per_vram_gb, una capa por GB por defecto) y se acotan a la mitad del modelo: crecer más de golpe convertiría la expansión en una migración y el sustrato dejaría de estar congelado.
AddExpert
{
"action": "add_expert",
"expert_id": "ncm-vision@seer",
"model_id": "ncm-vision",
"reason": "seer tiene IA local con telomerasa y puntuación 49.85 >= 6.00; entra como experto"
}
El experto se planifica con plan_swarm_named sobre su propio modelo y luego se fusiona con merge_expert, que mantiene los pipelines base vivos y añade los del experto. El enrutador distingue unos de otros por el campo model_id de la petición.
5. Aplicación atómica
apply_growth(plan, nodes, new_node, action) es una función pura: recalcula el plan completo y lo valida. No muta el plan anterior ni habla con la red.
let action = growth_decision(&newcomer, &plan)?;
let grown = apply_growth(&plan, &nodes, &newcomer, &action)?;
grown.validate()?; // invariantes del enjambre
cluster.deploy(&grown).await?; // aquí sí se toca la red
Si validate() falla, el orquestador descarta el plan nuevo y sigue con el viejo. Esa es la propiedad que hace que el crecimiento no pueda degradar el servicio: el plan nuevo existe completo antes de que nadie dependa de él.
6. Invariantes que se verifican
| Invariante | Qué rompe si se viola |
|---|---|
Cada pipeline cubre 0..model_layers de forma contigua | Un salto se quedaría sin capas que ejecutar. |
| Cada capa tiene al menos un nodo | Petición imposible de servir. |
deployments de un nodo = unión de sus etapas | Un nodo cargaría fragmentos que nadie le pide, o le faltarían. |
El reparto suma exactamente model_layers | Capas huérfanas o duplicadas dentro de una copia. |
| El plan es determinista para la misma entrada | Dos orquestadores calcularían planes distintos. |
7. Límites honestos
- El crecimiento es de hardware, no de conocimiento. Añadir un nodo añade copias o profundidad; la inteligencia nueva solo llega por la telomerasa.
ExtendDepthno reentrena el sustrato. Las capas nuevas se inicializan y hay que ajustarlas; el planificador decide dónde crecer, no cómo entrenar.- La decisión es codiciosa. No planifica a cinco nodos vista: reacciona a cada llegada. Con hardware que llega en ráfaga conviene llamar a
plan_swarmuna vez con todos.