¿Qué es el Sistema Límbico?

El Sistema Límbico es una capa de scoring dinámico que se ejecuta sobre los resultados KNN de search_semantic, reordenando candidatos según cómo se ha utilizado el knowledge graph a lo largo del tiempo. Transforma una búsqueda puramente basada en similitud en una que también considera qué importa, qué es reciente y qué pertenece junto.

El nombre es una metáfora biológica deliberada. En el cerebro humano, el sistema límbico maneja tres funciones que este módulo replica computacionalmente:

  • Valencia emocional — los recuerdos importantes se refuerzan. Aquí, las entidades frecuentemente accedidas y bien conectadas puntúan más alto.
  • Olvido — los recuerdos no usados se desvanecen gradualmente. Aquí, las entidades no accedidas recientemente decaen en su score.
  • Asociación — las cosas que se disparan juntas se conectan. Aquí, las entidades que co-ocurren en resultados de búsqueda se refuerzan mutuamente.

La API de search_semantic extiende su output para incluir los scores calculados. Más allá del {name, entityType, observations, distance} original, cada resultado ahora incluye limbic_score (el score compuesto) y scoring (un desglose de cada componente).

:::note El Sistema Límbico no es un motor de búsqueda separado — es un re-ranker post-recuperación. Opera sobre candidatos ya retornados por KNN (o KNN+FTS5 en modo Búsqueda Híbrida). Sin candidatos que reordenar, no hace nada. :::

Las Cuatro Capacidades

CapacidadQué haceMetáfora biológica
SalienciaEntidades frecuentemente accedidas y bien conectadas rankean más altoValencia emocional — cosas importantes se recuerdan mejor
Decay TemporalEntidades no accedidas recientemente disminuyen gradualmente en rankOlvido — conocimiento sin usar se desvanece
Co-ocurrenciaEntidades que aparecen juntas frecuentemente se refuerzan entre síAsociación — cosas que disparan juntas, se cablean juntas
Decay Temporal de Co-ocurrenciaCo-ocurrencias recientes cuentan más que las antiguasAsociaciones recientes son más fuertes que las antiguas

Cada capacidad mapea a un factor en la fórmula de scoring. Son multiplicativos — un score fuerte requiere que los cuatro contribuyan.

Query Routing: Selección Dinámica de Estrategia

MCP Memory v2 selecciona automáticamente la mejor estrategia de scoring basada en las características de la consulta. Esto se llama query routing.

Las Tres Estrategias

EstrategiaPeso CosenoPeso LímbicoMejor Para
COSINE_HEAVY70%30%Queries factuales: definiciones, “qué es”, términos exactos
LIMBIC_HEAVY30%70%Queries exploratorias: “explícame todo”, contexto amplio
HYBRID_BALANCED50%50%Queries mixtas: relaciones, comparaciones

Algoritmo de Detección

La función detect_query_type() analiza características lingüísticas:

Reglas de scoring:
    - Palabras clave factuales ("qué es", "definición", "cómo funciona", "es un/una") → +2
    - Palabras clave intermedias ("relación", "diferencia", "ejemplos", "comparar") → +1
    - Palabras clave exploratorias ("explícame", "relación entre", "dime todo", "qué piensas") → -2
    - Longitud de query ≤3 palabras → +1 (factual)
    - Longitud de query ≥10 palabras → -1 (exploratoria)
    - K limit ≤3 → +1 (preciso/factual)
    - K limit ≥10 → -1 (exploratoria)

Routing final:
    - Score ≥ 2 → COSINE_HEAVY
    - Score ≤ -2 → LIMBIC_HEAVY
    - En otro caso → HYBRID_BALANCED

Fórmula de Blending

Cuando el routing selecciona COSINE_HEAVY o LIMBIC_HEAVY, el score final combina similitud coseno con score límbico normalizado:

COSINE_HEAVY:  final = 0.7 × cosine + 0.3 × limbic_norm
LIMBIC_HEAVY:  final = 0.3 × cosine + 0.7 × limbic_norm
HYBRID_BALANCED: final = 0.5 × cosine + 0.5 × limbic_norm

Donde limbic_norm es min-max normalizado a través del conjunto de candidatos.

Output de API

El campo routing_strategy se incluye en cada resultado de search_semantic:

{
  "results": [{
    "name": "FastMCP",
    "routing_strategy": "cosine_heavy",
    "limbic_score": 0.67,
    ...
  }]
}

Esto te permite entender por qué un resultado particular rankeó donde rankeó.

Fórmula de Scoring

El score límbico compuesto se calcula como:

score(e, q) = cosine_sim(q, e) × (1 + β_sal × importance(e)) × temporal_factor(e) × (1 + γ × cooc_boost(e, R))

Donde:

ComponenteRangoRol
cosine_sim(q, e)[0, 1]Relevancia base — similitud pura de embeddings desde KNN
(1 + β_sal × importance(e))[1, 1.5]Boost de salience — qué tan importante es la entidad
temporal_factor(e)[0.1, 1.0]Decaimiento temporal — qué tan reciente fue el acceso a la entidad
(1 + γ × cooc_boost(e, R))[1, ~1.05]Boost de co-ocurrencia — refuerzo por aparecer con entidades relacionadas

La fórmula es multiplicativa por diseño: un candidato que es similar, importante, reciente y co-ocurrente puntuará significativamente más alto que uno que solo coincide en similitud. A la inversa, una entidad decaída todavía puede rankear si es muy importante y relevante.

cosine_sim(q, e)

cosine_sim(q, e) = max(0, 1 - distance)

La similitud base viene directamente de la búsqueda KNN. distance es la distancia coseno almacenada en la tabla embeddings. El clamp max(0, ...) previene valores negativos para vectores distantes.

:::tip En modo Búsqueda Híbrida, las entidades encontradas solo por FTS5 (no KNN) tienen distance = None. Su relevancia base se estima a partir del score RRF normalizado: 0.2 + 0.6 × norm_rrf, mapeando al rango [0.2, 0.8]. :::

Subfórmula: importance(e)

importance(e) = access_norm × (1 + β_deg × degree_norm) × (1 + α_cons × consolidation)

Donde:

  • access_norm = log₂(1 + access_count) / log₂(1 + max_access)
  • degree_norm = min(degree, D_MAX) / D_MAX
  • consolidation = log₂(1 + access_days) / log₂(1 + max_access_days)
  • α_cons = 0.2 (ALPHA_CONS)

El score de importancia combina tres señales estructurales:

Frecuencia de acceso

El primer factor normaliza la frecuencia de acceso de una entidad relativa a la entidad más accedida en el conjunto de candidatos:

access_norm = log₂(1 + access_count) / log₂(1 + max_access)

El logaritmo comprime la escala para que la diferencia entre 1 y 10 accesos importe más que entre 100 y 110. Esto evita que entidades accedidas muchas veces por accidente dominen permanentemente.

Ejemplo numérico: una entidad con 10 accesos cuando el máximo en el conjunto es 20:

access_norm = log₂(11) / log₂(21) = 3.459 / 4.392 ≈ 0.787

No la mitad (0.5), sino ~0.79 — el logaritmo preserva más señal en cuentas bajas.

Grado del grafo

El segundo factor premia a las entidades con muchas relaciones en el knowledge graph:

degree_factor = (1 + β_deg × degree_norm)

Una entidad en el centro de un knowledge graph (muchas relaciones y ) probablemente sea más importante que una aislada. El grado se limita a D_MAX (15) para evitar que las entidades hub dominen.

Consolidación multi-día

El tercer factor captura si una entidad ha sido accedida en múltiples días distintos, indicando relevancia sostenida en vez de un pico puntual:

consolidation = log₂(1 + access_days) / log₂(1 + max_access_days)

Donde access_days es el número de días calendario distintos en los que la entidad ha sido accedida (registrado en la tabla entity_access). Esto previene que una entidad accedida 100 veces en una hora supere a otra accedida una vez por día durante un mes. La escala logarítmica mantiene el factor acotado — con α_cons = 0.2, el boost máximo por consolidación es de 1.2×.

Ejemplo combinado

Una entidad con 10 accesos (máximo 20), 8 relaciones (D_MAX = 15), y accedida en 5 días distintos (máximo 10):

access_norm    = log₂(11) / log₂(21) ≈ 0.787
degree_norm    = min(8, 15) / 15 = 0.533
consolidation  = log₂(6) / log₂(11) = 2.585 / 3.459 ≈ 0.747

importance = 0.787 × (1 + 0.15 × 0.533) × (1 + 0.2 × 0.747)
           = 0.787 × 1.080 × 1.149
           ≈ 0.977

La señal de grado añade un modesto boost del 8%, y la consolidación añade un boost de ~15% — ambas secundarias respecto a la frecuencia de acceso, que sigue siendo la señal primaria.

Subfórmula: temporal_factor(e)

temporal_factor(e) = max(TEMPORAL_FLOOR, exp(-LAMBDA_HOURLY × Δt_hours))

Donde:

  • Δt_hours = horas desde el último acceso a la entidad (vía search_semantic o open_nodes). Si la entidad nunca fue accedida, se usa created_at en su lugar.
  • LAMBDA_HOURLY = 0.0001 — la tasa de decaimiento exponencial por hora
  • TEMPORAL_FLOOR = 0.1 — el valor mínimo que puede alcanzar el factor

Características del decaimiento

Con LAMBDA_HOURLY = 0.0001, la vida media del decaimiento es:

vida media = ln(2) / 0.0001 ≈ 6931 horas ≈ 289 días

Este es un decaimiento lento por diseño. El knowledge graph es un recurso de larga duración — las entidades no deberían desaparecer de los resultados solo porque no se han necesitado por unas semanas. Pero a lo largo de meses y años, las entidades no usadas retroceden gradualmente.

Ejemplos numéricos

Tiempo desde último accesoΔt (horas)temporal_factor
1 hora10.9999
1 día240.9976
1 semana1680.9833
30 días7200.9305
90 días21600.8053
180 días43200.6485
1 año87660.4172
2 años175320.1740
3+ años26000+→ 0.1 (piso)

:::caution El piso de 0.1 significa que ninguna entidad se olvida completamente. Incluso una entidad de 5 años retiene un 10% de su señal temporal. Si necesitas expiración real (ej. para datos sensibles al tiempo), debes implementarla en la capa de aplicación. :::

Sub-fórmula: cooc_boost(e, R)

cooc_boost(e, R) = Σ_{r ∈ R, r ≠ e} log₂(1 + co_count(e, r)) × decay(last_co(e, r))

Esto suma los conteos de co-ocurrencia entre la entidad e y cada otra entidad r en el conjunto de resultados R, ponderados por decay temporal. El logaritmo suaviza la contribución:

co_countlog₂(1 + co_count)Multiplicador
11.00
52.58
103.4610×
505.6750×
1006.66100×

Decay Temporal de Co-ocurrencia

El factor decay(last_co) usa la misma vida media (~290 días) que compute_temporal_factor:

decay(last_co) = max(COOC_TEMPORAL_FLOOR, exp(-LAMBDA_HOURLY × Δt_hours))

Esto significa que las co-ocurrencias recientes boost más que las antiguas. Una entidad que apareció junto con otra ayer contribuye más al boost de co-ocurrencia que una que co-ocurrió hace 6 meses.

Tiempo desde co-ocurrenciaFactor de decay
1 hora0.9999
1 día0.9976
1 semana0.9833
30 días0.9305
90 días0.8053
1 año0.4172
2+ años→ 0.1 (piso)

:::tip La constante γ (GAMMA) es deliberadamente pequeña (0.01). Incluso un boost de co-ocurrencia de 5.0 solo añade 1 + 0.01 × 5.0 = 1.05 — una mejora del 5%. Esto previene que la co-ocurrencia domine el scoring, manteniéndola como desempate en vez de señal primaria. :::

Constantes Ajustables

Todas las constantes están a nivel de módulo en src/mcp_memory/scoring.py y son directamente editables.

ConstanteValorPropósitoEfecto de aumentar
BETA_SAL0.5Peso del boost de salience en el score compuestoMayor → importance importa más; una entidad con importance=1.0 obtiene boost de 1.5×
BETA_DEG0.15Peso del grado del grafo dentro de importanceMayor → las entidades bien conectadas puntúan más alto; bajo por diseño ya que el grado es secundario
D_MAX15Límite en el conteo de relaciones para normalización de gradoMayor → entidades con muchas relaciones siguen recibiendo boost; 15 es un umbral razonable para hubs
LAMBDA_HOURLY0.0001Tasa de decaimiento temporal por horaMayor → olvido más rápido; vida media actual ≈ 290 días
GAMMA0.01Peso del boost de co-ocurrencia en el score compuestoMayor → las entidades co-ocurrentes puntúan más alto; reducido desde 0.1 que dominaba el scoring 24×
RRF_K60Constante de suavizado para Reciprocal Rank FusionMayor → la posición en el rank importa menos; 60 es el valor estándar del paper original de RRF
EXPANSION_FACTOR3Multiplicador de over-retrieval KNNMayor → más candidatos para re-ranking a costa de computación; limit=10 → 30 candidatos
TEMPORAL_FLOOR0.1Valor mínimo para el decaimiento temporalMayor → las entidades viejas retienen más señal; 0.1 significa que el conocimiento se degrada pero nunca se destruye

:::caution Las constantes están ajustadas para funcionar juntas. Cambiar una sin considerar las demás puede producir resultados inesperados. Por ejemplo, establecer GAMMA=0.1 sin reducir BETA_SAL causará que la co-ocurrencia domine sobre la salience, ignorando efectivamente los patrones de acceso. :::

Deboosts por Estado

Después del scoring límbico, los resultados se ajustan según el estado de la entidad y la composición de sus observaciones:

EstadoDeboostEfecto
activo1.0× (ninguno)Default, sin penalización
pausado0.85×Penalización leve
completado0.70×Penalización moderada
archivado0.50×Penalización fuerte

Penalización por Metadata

Si más del 50% de las observaciones de una entidad tienen kind="metadata", su limbic_score se multiplica por 0.7. Esto previene que entidades cargadas de metadata (listados de archivos, dumps de configuración) dominen los resultados de búsqueda.

Registro de Señales

El Sistema Límbico se basa en tres señales registradas durante el uso normal de la API:

Tabla entity_access

CREATE TABLE entity_access (
    entity_id    INTEGER PRIMARY KEY REFERENCES entities(id) ON DELETE CASCADE,
    access_count INTEGER NOT NULL DEFAULT 1,
    last_access  TEXT    NOT NULL DEFAULT (datetime('now'))
);
  • Cuándo se registra: cada llamada a search_semantic (para resultados top-K) y open_nodes (para entidades abiertas).
  • Qué se almacena: access_count (incrementado en cada acceso) y last_access (actualizado al timestamp actual).
  • Comportamiento: best-effort — el registro ocurre después de construir la respuesta y no afecta el resultado actual.

Tabla co_occurrences

CREATE TABLE co_occurrences (
    entity_a_id  INTEGER NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
    entity_b_id  INTEGER NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
    co_count     INTEGER NOT NULL DEFAULT 1,
    last_co      TEXT    NOT NULL DEFAULT (datetime('now')),
    PRIMARY KEY (entity_a_id, entity_b_id)
);
  • Cuándo se registra: después de search_semantic (para todos los pares en el conjunto top-K) y después de open_nodes (cuando se abren 2+ entidades juntas).
  • Qué se almacena: co_count (incrementado por par) y last_co (timestamp actualizado). Los pares se almacenan en orden canónico: entity_a_id < entity_b_id siempre, previniendo pares duplicados como (A, B) y (B, A).
  • Comportamiento: best-effort, post-respuesta, non-blocking.

:::note Las señales se registran para las entidades retornadas en los resultados top-K (el output final después del re-ranking), no para el conjunto expandido de candidatos. Esto significa que solo las entidades que el usuario realmente ve generan datos de tracking. :::

Auto-Tuning: Optimización de GAMMA y BETA_SAL

Las constantes del limbic scoring (GAMMA y BETA_SAL) pueden ser ajustadas automáticamente vía grid search offline usando datos recolectados del A/B testing en shadow mode.

Por Qué Ajustar?

Los valores por defecto (GAMMA=0.01, BETA_SAL=0.5) funcionan bien como punto de partida, pero el balance óptimo depende de tus patrones de uso. El auto-tuning encuentra el punto ideal para tu knowledge graph específico.

Cómo Funciona

  1. Recolectar datos: Shadow mode loguea cada query search_semantic con ambos rankings (baseline y límbico)
  2. Calcular métricas: ab_metrics.py calcula NDCG@K usando feedback implícito (eventos de re-acceso)
  3. Grid search: auto_tuner.py --tune explora combinaciones de GAMMA × BETA_SAL
  4. Aplicar suavemente: Nuevos valores se mezclan vía media móvil exponencial (10% nuevo, 90% viejo)

Uso

# Analizar rendimiento actual
python scripts/auto_tuner.py --analyze

# Encontrar params óptimos y aplicar
python scripts/auto_tuner.py --tune

# Forzar valores específicos con blend suave
python scripts/auto_tuner.py --set-gamma 0.05 --set-beta 0.75

# Rangos personalizados
python scripts/auto_tuner.py --tune --gamma-range "0.001,0.01,0.05,0.1" --beta-sal-range "0.1,0.5,1.0"

Métricas

MétricaDescripción
NDCG@KNormalized Discounted Cumulative Gain at K — qué tan bien el ranking coincide con relevancia implícita
Lift@KProporción de items relevantes en top-K vs total — más alto es mejor
GainMejora de NDCG sobre parámetros actuales

Requisitos

  • Mínimo 50 eventos con treatment=1 (grupo de tratamiento del A/B test)
  • Datos de feedback implícito (eventos de re-acceso vía record_access)
  • Cobertura suficiente del espacio de parámetros

:::caution El auto-tuning requiere datos acumulados del shadow mode. Sin suficientes eventos, el comando --tune se saltará con un mensaje como “Solo 23 eventos, mínimo 50 requeridos”. :::

Flujo Completo del Pipeline

graph TD
    Q["Cadena de consulta"] --> Encode["1. Codificar<br/>engine.encode(query)<br/>→ float[384]"]
    Encode --> KNN["2. KNN 3×<br/>search_embeddings(query, limit × 3)<br/>→ [{entity_id, distance}]"]
    KNN --> Fetch["3. Obtener metadata<br/>access_data · degrees · co_occurrences"]
    Fetch --> Rerank["4. Re-rankear<br/>rank_candidates()<br/>calcular limbic_score por candidato<br/>→ ordenar descendente → top-K"]
    Rerank --> Build["5. Construir output<br/>{name, entityType, observations,<br/>distance, limbic_score, scoring}"]
    Build --> Record["6. Registrar señales<br/>record_access(top-K ids)<br/>record_co_occurrences(top-K ids)<br/>best-effort, post-respuesta"]

Paso a paso:

  1. Codificar consulta — la cadena de consulta se convierte en un vector de 384 dimensiones usando el modelo de embeddings con prefijo task="query".
  2. KNN 3× — el vector se compara contra todos los embeddings de entidades vía sqlite-vec KNN, recuperando limit × EXPANSION_FACTOR candidatos (default: 3× el límite solicitado).
  3. Obtener metadata — para cada candidato, el sistema carga conteos de acceso, últimos tiempos de acceso, grados del grafo y datos de co-ocurrencia desde las tablas de tracking.
  4. Re-rankear — la función rank_candidates() computa el score límbico para cada candidato usando la fórmula anterior, ordena por score descendente y retorna el top-K.
  5. Construir output — los resultados se formatean con todos los campos: datos originales más limbic_score, desglose de scoring y distance.
  6. Registrar señales — los conteos de acceso y co-ocurrencias para las entidades retornadas se actualizan. Esto ocurre después de construir la respuesta, es best-effort y no afecta el resultado actual.

:::tip El EXPANSION_FACTOR de 3× es lo que hace efectivo el re-ranking. Si se piden 10 resultados, el sistema recupera 30 candidatos, re-rankeo los 30 y retorna los mejores 10. Esto le da al Sistema Límbico espacio para surfear entidades que rankean más bajo en similitud pura pero más alto en importancia y recencia. :::

Transparencia de la API

El Sistema Límbico extiende la API de search_semantic de forma retrocompatible.

Input: sin cambios

search_semantic(query, limit)

Sin parámetros nuevos. El scoring ocurre automáticamente.

Output: campos extendidos

Cada resultado incluye nuevos campos junto a los originales:

{
  "results": [
    {
      "name": "SofIA - Sistema Multiagente",
      "entityType": "Proyecto",
      "observations": ["Sistema multiagente con roles especializados"],
      "distance": 0.42,
      "limbic_score": 0.67,
      "scoring": {
        "importance": 0.85,
        "temporal_factor": 0.99,
        "cooc_boost": 1.23
      }
    }
  ]
}
CampoTipoDescripción
distancefloatDistancia coseno original de KNN — no es el score límbico
limbic_scorefloatScore compuesto que determina el orden de los resultados
scoringobjectDesglose de los tres componentes límbicos
scoring.importancefloatScore de salience (frecuencia de acceso + grado del grafo)
scoring.temporal_factorfloatFactor de decaimiento temporal (1.0 = recién accedida, → piso 0.1)
scoring.cooc_boostfloatBoost de co-ocurrencia por aparecer con entidades relacionadas
rrf_scorefloat?Presente solo en modo Búsqueda Híbrida

Ordenamiento

Los resultados se ordenan por limbic_score descendente (mayor primero), no por distancia coseno ascendente. Este es el cambio de comportamiento clave: la entidad más relevante-e-importante aparece primero, incluso si existe una entidad ligeramente más similar pero poco importante.

Alcance del tracking

El tracking de co-ocurrencia se dispara en dos lugares:

  • search_semantic — para todos los pares de entidades en el conjunto top-K retornado
  • open_nodes — cuando se abren 2+ entidades juntas en la misma llamada

Ver la Referencia de Tools para la especificación completa de ambas tools.

Módulo: scoring.py

El motor de scoring está en src/mcp_memory/scoring.py (~351 líneas). Expone las siguientes funciones públicas:

FunciónFirmaPropósito
rank_candidates()(candidates, access_data, degrees, co_occurrences, limit) → list[dict]Re-rankear resultados KNN con scoring límbico — modo semántico puro
rank_hybrid_candidates()(candidates, access_data, degrees, co_occurrences, limit) → list[dict]Re-rankear resultados fusionados con RRF con scoring límbico — modo híbrido
reciprocal_rank_fusion()(semantic_results, fts_results, k) → list[dict]Fusionar rankings KNN y FTS5 usando RRF
compute_importance()(access_count, max_access, degree) → floatCalcular importance(e) desde señales brutas
compute_temporal_factor()(last_access, created_at) → floatCalcular temporal_factor(e) desde timestamps
compute_cooc_boost()(entity_id, co_occurrences, result_ids) → floatCalcular cooc_boost(e, R) desde mapa de co-ocurrencias

Todas las constantes (BETA_SAL, BETA_DEG, D_MAX, LAMBDA_HOURLY, GAMMA, RRF_K, EXPANSION_FACTOR, TEMPORAL_FLOOR) son variables a nivel de módulo y pueden sobrescribirse al importar o patchearse para testing.

Uso en el pipeline

# Modo semántico puro
ranked = rank_candidates(
    candidates=knn_results,        # [{entity_id, distance}]
    access_data=access_data,       # {entity_id: {access_count, last_access}}
    degrees=degrees,               # {entity_id: int}
    co_occurrences=co_occurrences, # {(a_id, b_id): co_count}
    limit=10
)

# Modo híbrido (KNN + FTS5)
merged = reciprocal_rank_fusion(knn_results, fts_results, k=RRF_K)
ranked = rank_hybrid_candidates(
    candidates=merged,
    access_data=access_data,
    degrees=degrees,
    co_occurrences=co_occurrences,
    limit=10
)

:::note La función rank_hybrid_candidates() maneja el caso especial donde entidades solo-FTS5 tienen distance = None. Estima su relevancia base a partir del score RRF normalizado (rango [0.2, 0.8]) en lugar de usar similitud coseno. :::

Ejemplo Resuelto

Recorrido de un cálculo de scoring completo para una entidad concreta.

Entidad: “FastMCP” (una entidad de framework)

  • Conteo de acceso: 10 (máximo en el conjunto de candidatos: 20)
  • Grado del grafo: 8 relaciones
  • Último acceso: hace 30 días
  • Co-ocurrencia con otros 3 resultados: conteos de [5, 2, 1]
  • Distancia coseno desde la consulta: 0.35

Paso 1 — Similitud base:

cosine_sim = max(0, 1 - 0.35) = 0.65

Paso 2 — Importance:

access_factor = log₂(11) / log₂(21) = 3.459 / 4.392 ≈ 0.787
degree_factor = 1 + 0.15 × (8/15) = 1 + 0.08 = 1.08
importance   = 0.787 × 1.08 ≈ 0.850
salience_boost = 1 + 0.5 × 0.850 = 1.425

Paso 3 — Factor temporal:

Δt = 30 días × 24 = 720 horas
temporal_factor = exp(-0.0001 × 720) = exp(-0.072) ≈ 0.931

Paso 4 — Boost de co-ocurrencia:

cooc_boost = log₂(6) + log₂(3) + log₂(2) = 2.585 + 1.585 + 1.000 = 5.170
cooc_factor = 1 + 0.01 × 5.170 = 1.052

Paso 5 — Score límbico compuesto:

limbic_score = 0.65 × 1.425 × 0.931 × 1.052
             = 0.65 × 1.425 × 0.931 × 1.052
             ≈ 0.908

El Sistema Límbico impulsó esta entidad desde una similitud bruta de 0.65 a un score compuesto de 0.908 — un incremento del 40% impulsado por importance (primario), recencia temporal (secundario) y co-ocurrencia (terciario).

Relacionado

  • Búsqueda Híbrida — cómo FTS5 y KNN se fusionan vía RRF antes del re-ranking límbico
  • Búsqueda Semántica — el pipeline KNN que produce los candidatos iniciales
  • Referencia de Tools — especificación completa de la API para search_semantic y open_nodes
  • Arquitectura — visión general del sistema incluyendo el lugar del módulo de scoring en el flujo de datos