¿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
| Capacidad | Qué hace | Metáfora biológica |
|---|---|---|
| Saliencia | Entidades frecuentemente accedidas y bien conectadas rankean más alto | Valencia emocional — cosas importantes se recuerdan mejor |
| Decay Temporal | Entidades no accedidas recientemente disminuyen gradualmente en rank | Olvido — conocimiento sin usar se desvanece |
| Co-ocurrencia | Entidades que aparecen juntas frecuentemente se refuerzan entre sí | Asociación — cosas que disparan juntas, se cablean juntas |
| Decay Temporal de Co-ocurrencia | Co-ocurrencias recientes cuentan más que las antiguas | Asociaciones 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
| Estrategia | Peso Coseno | Peso Límbico | Mejor Para |
|---|---|---|---|
COSINE_HEAVY | 70% | 30% | Queries factuales: definiciones, “qué es”, términos exactos |
LIMBIC_HEAVY | 30% | 70% | Queries exploratorias: “explícame todo”, contexto amplio |
HYBRID_BALANCED | 50% | 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:
| Componente | Rango | Rol |
|---|---|---|
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_MAXconsolidation = 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íasearch_semanticoopen_nodes). Si la entidad nunca fue accedida, se usacreated_aten su lugar.LAMBDA_HOURLY = 0.0001— la tasa de decaimiento exponencial por horaTEMPORAL_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 hora | 1 | 0.9999 |
| 1 día | 24 | 0.9976 |
| 1 semana | 168 | 0.9833 |
| 30 días | 720 | 0.9305 |
| 90 días | 2160 | 0.8053 |
| 180 días | 4320 | 0.6485 |
| 1 año | 8766 | 0.4172 |
| 2 años | 17532 | 0.1740 |
| 3+ años | 26000+ | → 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_count | log₂(1 + co_count) | Multiplicador |
|---|---|---|
| 1 | 1.00 | 1× |
| 5 | 2.58 | 5× |
| 10 | 3.46 | 10× |
| 50 | 5.67 | 50× |
| 100 | 6.66 | 100× |
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-ocurrencia | Factor de decay |
|---|---|
| 1 hora | 0.9999 |
| 1 día | 0.9976 |
| 1 semana | 0.9833 |
| 30 días | 0.9305 |
| 90 días | 0.8053 |
| 1 año | 0.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.
| Constante | Valor | Propósito | Efecto de aumentar |
|---|---|---|---|
BETA_SAL | 0.5 | Peso del boost de salience en el score compuesto | Mayor → importance importa más; una entidad con importance=1.0 obtiene boost de 1.5× |
BETA_DEG | 0.15 | Peso del grado del grafo dentro de importance | Mayor → las entidades bien conectadas puntúan más alto; bajo por diseño ya que el grado es secundario |
D_MAX | 15 | Límite en el conteo de relaciones para normalización de grado | Mayor → entidades con muchas relaciones siguen recibiendo boost; 15 es un umbral razonable para hubs |
LAMBDA_HOURLY | 0.0001 | Tasa de decaimiento temporal por hora | Mayor → olvido más rápido; vida media actual ≈ 290 días |
GAMMA | 0.01 | Peso del boost de co-ocurrencia en el score compuesto | Mayor → las entidades co-ocurrentes puntúan más alto; reducido desde 0.1 que dominaba el scoring 24× |
RRF_K | 60 | Constante de suavizado para Reciprocal Rank Fusion | Mayor → la posición en el rank importa menos; 60 es el valor estándar del paper original de RRF |
EXPANSION_FACTOR | 3 | Multiplicador de over-retrieval KNN | Mayor → más candidatos para re-ranking a costa de computación; limit=10 → 30 candidatos |
TEMPORAL_FLOOR | 0.1 | Valor mínimo para el decaimiento temporal | Mayor → 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:
| Estado | Deboost | Efecto |
|---|---|---|
activo | 1.0× (ninguno) | Default, sin penalización |
pausado | 0.85× | Penalización leve |
completado | 0.70× | Penalización moderada |
archivado | 0.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) yopen_nodes(para entidades abiertas). - Qué se almacena:
access_count(incrementado en cada acceso) ylast_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 deopen_nodes(cuando se abren 2+ entidades juntas). - Qué se almacena:
co_count(incrementado por par) ylast_co(timestamp actualizado). Los pares se almacenan en orden canónico:entity_a_id < entity_b_idsiempre, 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
- Recolectar datos: Shadow mode loguea cada query
search_semanticcon ambos rankings (baseline y límbico) - Calcular métricas:
ab_metrics.pycalcula NDCG@K usando feedback implícito (eventos de re-acceso) - Grid search:
auto_tuner.py --tuneexplora combinaciones de GAMMA × BETA_SAL - 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étrica | Descripción |
|---|---|
| NDCG@K | Normalized Discounted Cumulative Gain at K — qué tan bien el ranking coincide con relevancia implícita |
| Lift@K | Proporción de items relevantes en top-K vs total — más alto es mejor |
| Gain | Mejora 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:
- Codificar consulta — la cadena de consulta se convierte en un vector de 384 dimensiones usando el modelo de embeddings con prefijo
task="query". - KNN 3× — el vector se compara contra todos los embeddings de entidades vía sqlite-vec KNN, recuperando
limit × EXPANSION_FACTORcandidatos (default: 3× el límite solicitado). - 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.
- 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. - Construir output — los resultados se formatean con todos los campos: datos originales más
limbic_score, desglose descoringydistance. - 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
}
}
]
}
| Campo | Tipo | Descripción |
|---|---|---|
distance | float | Distancia coseno original de KNN — no es el score límbico |
limbic_score | float | Score compuesto que determina el orden de los resultados |
scoring | object | Desglose de los tres componentes límbicos |
scoring.importance | float | Score de salience (frecuencia de acceso + grado del grafo) |
scoring.temporal_factor | float | Factor de decaimiento temporal (1.0 = recién accedida, → piso 0.1) |
scoring.cooc_boost | float | Boost de co-ocurrencia por aparecer con entidades relacionadas |
rrf_score | float? | 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 retornadoopen_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ón | Firma | Propó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) → float | Calcular importance(e) desde señales brutas |
compute_temporal_factor() | (last_access, created_at) → float | Calcular temporal_factor(e) desde timestamps |
compute_cooc_boost() | (entity_id, co_occurrences, result_ids) → float | Calcular 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_semanticyopen_nodes - Arquitectura — visión general del sistema incluyendo el lugar del módulo de scoring en el flujo de datos