las ecuaciones de esta slide
f(t) = e−λt(vigencia del conocimiento congelado)
fracción de las preguntas del negocio cuya respuesta sigue siendo la que el modelo memorizó en el entrenamiento. t = meses desde la fecha de corte; λ = fracción de la base documental que cambia cada mes. A λ = 5 %/mes, a los 14 meses la mitad de lo que "sabe" el modelo ya está desactualizado.
Psin(t) = f(t)·a + (1−f(t))·g(sin retrieval)
sin RAG el modelo acierta con probabilidad a = 0.92 cuando la respuesta sigue en sus pesos, y con probabilidad g = 0.15 cuando no: entonces responde igual de seguro, pero inventando — eso es la alucinación.
Pcon(t) = R·F + (1−R)·Psin(t)(con RAG)
con RAG, con probabilidad R (el recall del retrieval) el chunk correcto y vigente llega al contexto y el modelo responde fiel a él con probabilidad F = 0.95; si el retrieval falla (1−R), caemos al caso sin RAG. La ventaja de RAG es exactamente R·(F−Psin): crece con cada mes que pasa.
guion paso a paso
  1. Pon t = 0 meses. Las dos barras casi empatan: recién entrenado, el modelo todavía "sabe" tu negocio y el retrieval aporta poco.
  2. Sube t a 24 con λ = 5 %/mes. Psin se desploma hacia el suelo g = 0.15; la curva dorada apenas se inmuta: los documentos del índice no envejecen, se reindexan.
  3. Baja R a 0.5. La ventaja de RAG se reduce a la mitad: un RAG es exactamente tan bueno como su retrieval, de ahí el resto del día.
  4. Sube λ a 15 %/mes (normativa bancaria, precios, catálogo Inditex). A los 12 meses la brecha ya supera los 40 puntos: cuanto más vivo el dominio, antes se paga el conocimiento congelado.
Comprueba que entiendes: ¿por qué la curva dorada casi no depende de t?
Porque la respuesta no sale de los pesos congelados sino del documento vigente que el retrieval mete en el contexto: indexar un documento nuevo cuesta segundos, reentrenar el modelo cuesta semanas. El único canal por el que el tiempo entra en Pcon es el término de fallo (1−R)·Psin(t): cuando el retrieval no encuentra el chunk, el modelo vuelve a depender de su memoria, que sí envejece. Por eso la curva dorada cae un poquito, y cae más cuanto peor es R.

Setup. Un LLM se entrena con datos hasta una fecha de corte: no conoce tu CRM, tus circulares ni el calendario de la oficina de Burgos, y lo que conocía caduca. Modelizo eso con tres números: la vigencia f(t) decae exponencialmente a ritmo λ, el modelo acierta a = 0.92 sobre conocimiento vigente y g = 0.15 cuando alucina, y el RAG acierta F = 0.95 cuando su retrieval (recall R) encuentra el documento. Arriba: P(respuesta correcta) frente a los meses desde el corte, sin RAG (tinta) y con RAG (dorado). Abajo: a la t elegida, de cada 1000 consultas, cuántas salen bien y cuántas mal en cada sistema.

Juega. Los tres sliders son las tres palancas del problema: el tiempo (que no controlas), el ritmo de cambio de tu sector (que tampoco) y el recall del retrieval (la única que sí). Observa que la alternativa real a RAG no es "el modelo a pelo", es reentrenar o hacer fine-tuning cada pocos meses: pagar decenas de miles de euros por subir f(t) de golpe a 1… y verla decaer otra vez.

Lee así. La distancia vertical entre las dos curvas es el valor económico del retrieval: a 5000 consultas/día, cada punto porcentual de brecha son 50 respuestas inventadas menos al día que un empleado o un cliente recibiría con total confianza aparente.

Mensaje. Para conocimiento corporativo cambiante, RAG gana a fine-tuning el 90 % de las veces: las actualizaciones son incrementales (indexar el documento nuevo) y el modelo nunca tiene que "aprender" tus datos, solo leerlos. El examen pasa de libro cerrado a libro abierto.

Términos. Fecha de corte: último día cubierto por los datos de entrenamiento. Alucinación: respuesta inventada emitida con la misma confianza que una correcta. Recall R: probabilidad de que el chunk que contiene la respuesta esté entre los recuperados. Faithfulness F: probabilidad de que la respuesta sea fiel al contexto recuperado.

las ecuaciones de esta slide
topk(q) = arg máx(k)j∈[J] cos(φ(q), φ(dj))(Ec. de retrieval del día)
de los J chunks del corpus, quédate con los k que maximizan el coseno entre el embedding de la query φ(q) y el del chunk φ(dj). El superíndice (k) significa "los k mejores", no "elevado a k". φ es el modelo de embeddings del Día 08: texto → vector de D números.
ŷ ∼ pθ(y | q, dj1,…,djk)(generación condicionada)
el LLM (parámetros θ, congelados) genera la respuesta ŷ condicionando en la query y en los k chunks recuperados, que van pegados en el prompt. Después devuelve los dji como citas verificables: esa es la etapa de atribución.
Mem = J·D·b bytes,    opsfuerza bruta = 2·J·D por consulta
el índice guarda J vectores de D dimensiones a b bytes por número (4 en float32, 1 cuantizado a int8). Buscar por fuerza bruta es un producto escalar contra cada chunk: 2·J·D operaciones. Las bases vectoriales (FAISS, Qdrant, Pinecone, pgvector) existen para no pagar eso: con un índice ANN tipo HNSW se visitan ≈ ef·log2J candidatos.
guion paso a paso
  1. Recorre la etapa de 1 a 7 leyendo el texto del lector. Las etapas 1–4 (ingesta) se pagan una vez; las 5–7 (consulta) se pagan en cada query. Esa asimetría organiza todo el día.
  2. Sube J a 1 000 000 con D = 1024 en float32. El índice pesa ~4 GB y la fuerza bruta tarda cientos de milisegundos por consulta: ya no cabe en "tiempo de chat".
  3. Activa int8. La memoria se divide por 4 con pérdida de recall mínima: es la cuantización que BBVA usa en pgvector en el caso final.
  4. Compara las distancias de fuerza bruta con las del índice ANN en el lector. Factor de aceleración de cientos a miles: por eso existen las bases vectoriales como producto.
Comprueba que entiendes: ¿por qué no pegar el corpus entero en el prompt y ahorrarse el índice?
Por presupuesto y por ventana: J chunks de 400 tokens son J·400 tokens por consulta. Con J = 300 000 eso son 120 millones de tokens: no caben en ninguna ventana de contexto y, aunque cupieran, a 3 €/millón costarían 360 € por pregunta. El índice existe para seleccionar k·400 ≈ 4000 tokens: el retrieval es, ante todo, un mecanismo de compresión del coste.

Setup. El pipeline canónico tiene dos carriles. Ingesta (offline, una vez): los documentos se trocean en J chunks, cada chunk pasa por el modelo de embeddings φ y el vector resultante se guarda en la base vectorial. Consulta (online, cada vez): la query se embebe con el mismo φ, el índice devuelve los top-k chunks por coseno y el LLM genera la respuesta condicionada a ellos, con citas. Arriba: el diagrama con la etapa elegida iluminada y las dimensiones de cada pieza. Abajo: la memoria del índice en función de J, en float32 y en int8.

Juega. El slider de J recorre de mil a tres millones de chunks (escala log): mira cómo la memoria y el tiempo de búsqueda crecen lineales en J mientras que el coste por consulta del LLM no depende de J en absoluto: solo de k. Esa separación es el diseño entero de RAG.

Lee así. El lector da la memoria exacta J·D·b, el número de productos escalares de la fuerza bruta y la estimación ANN (ef = 64 candidatos por nivel, log2J niveles). Son los números que pides a un proveedor de vector DB antes de firmar.

Mensaje. Indexa una vez, recupera en cada query. Para empezar basta Chroma en local; cuando el corpus crece, Qdrant o Pinecone; si ya tienes Postgres, pgvector. La elección de base vectorial es logística, no ciencia: la ciencia está en el chunking y el retrieval, que vienen ahora.

Términos. Chunk dj: trozo de documento de 200–800 tokens, la unidad que se indexa. φ: modelo de embeddings. Vector DB: almacén que busca por similitud de vectores. ANN: búsqueda de vecinos aproximada (HNSW, IVF), sublineal en J.

las ecuaciones de esta slide
nchunks = L−ss−o + 1(troceado con solape)
un documento de L palabras troceado en ventanas de s palabras que avanzan de s−o en s−o (cada chunk comparte o palabras con el anterior). Más solape = más chunks = más almacenamiento, a cambio de que ningún corte parta una cláusula por la mitad.
sim(c) = gc√|c|(retrieval de juguete)
proxy del coseno para esta demo: gc = palabras de la respuesta anotada que caen dentro del chunk, normalizado por √|c| igual que el coseno normaliza por la longitud del vector. Un chunk largo diluye su señal: esa división es la madre del trade-off.
precision = |G∩C||C|,    recall = |G∩C||G|(contra la respuesta anotada)
G = palabras de la respuesta correcta (anotadas en dorado), C = palabras enviadas al LLM (los chunks recuperados). Precision = qué parte de lo enviado es respuesta; recall = qué parte de la respuesta llega al contexto.
guion paso a paso
  1. Pon s = 25, o = 0, kret = 1. Precision = 1.00 pero recall = 0.43: el chunk recuperado es pura respuesta, pero la respuesta completa (58 palabras) no cabe en 25 y la excepción del 85 % queda fuera.
  2. Sube kret a 2 y luego a 3. Recall sube a 0.86 y luego a 1.00 con precision todavía 0.77: los chunks pequeños se compensan recuperando más chunks, no agrandándolos.
  3. Vuelve a kret = 1 y pon s = 160 con o = 0. Doble castigo: precision 0.25 (el LLM recibe scoring, tasaciones y tipos que nadie preguntó) y recall 0.69, porque el corte de la palabra 160 parte la respuesta (palabras 142–199) entre dos chunks.
  4. Con s = 160, sube o a 30. Recall salta a 1.00: el solape cura el corte desafortunado. El precio está en el lector: 5 chunks en vez de 4, más almacenamiento por el texto duplicado.
Comprueba que entiendes: ¿por qué la nota del día dice que la ventana óptima es "la unidad coherente más pequeña"?
Porque precision y recall se maximizan a la vez cuando el chunk coincide exactamente con la unidad que responde preguntas: la cláusula en un contrato, la sección en un manual, el turno en una conversación. Más pequeño que la unidad, partes respuestas (recall cae); más grande, arrastras vecinos irrelevantes (precision cae). El solape es el seguro contra no saber dónde empieza la unidad.

Setup. El documento de arriba es una política de riesgo de crédito hipotecario de un banco ficticio (~600 palabras, troceada en vivo). La pregunta de juguete es: "¿qué LTV máximo permite la política en vivienda habitual y qué excepción existe?". Las palabras doradas son la respuesta anotada (dos frases: el límite del 80 % y la excepción del 85 %). Cada banda gris alterna es un chunk; las zonas color arena pertenecen a dos chunks (solape); el recuadro grueso marca los chunks que el retrieval de juguete selecciona. Abajo: precision, recall y F1 en función del tamaño de chunk, con tu s actual marcada.

Juega. Trocear mal es la causa número uno de RAG mediocre, y este es el porqué en una figura: chunks pequeños dan precisión sin contexto (la respuesta se fragmenta), chunks grandes dan contexto con ruido (la respuesta se diluye entre párrafos irrelevantes que además pagas a precio de token).

Lee así. El lector da el número de chunks (⌈(L−s)/(s−o)⌉+1), la precision y el recall contra la respuesta anotada y los tokens enviados al LLM (≈ palabras × 1.4).

Mensaje. Reglas defensivas del día: chunks de 300–600 tokens, solape de 50–100, conservar metadatos (título, sección, fecha) junto al texto, y no partir tablas ni listas en mitad de fila. La curva de abajo es la razón de cada una.

Términos. Chunk: ventana de texto indexada como una unidad. Solape o: palabras compartidas entre chunks consecutivos. Respuesta anotada (gold): el span que un humano marcó como respuesta correcta, para poder medir. F1: media armónica de precision y recall.

las ecuaciones de esta slide
cos(φ(q),φ(d)) = φ(q)·φ(d)‖φ(q)‖ ‖φ(d)‖ = Σm qmdm√(Σqm²) √(Σdm²)(similitud coseno)
producto escalar de los dos embeddings dividido por sus normas: mide el ángulo, no la longitud. Vale 1 si apuntan igual, 0 si son perpendiculares (nada que ver), −1 si opuestos. Con vectores normalizados a norma 1, el coseno es directamente el producto escalar — por eso las vector DB normalizan al indexar.
topk(q) = arg máx(k)j∈[J] cos(φ(q),φ(dj))(la misma Ec. del pipeline, ahora en vivo)
aquí J = 15 y los embeddings son 2D para poder dibujarlos (los reales tienen D = 1024; la geometría es la misma). El sector dorado del dibujo es el "cono de recuperación": todos los chunks cuyo ángulo con la query es menor que el del k-ésimo clasificado.
#chunkcos
guion paso a paso
  1. Con la query de hipotecas y k = 3, mira el plano. El cono dorado es estrecho y cubre exactamente el cluster de hipotecas: retrieval = geometría.
  2. Sube k a 8. El cono se abre y empiezan a entrar chunks de mora y provisiones: similitud baja = contexto ruidoso. k controla la apertura.
  3. Cambia a la query de tarjetas. El ranking entero se reordena: el coseno no es una propiedad del chunk sino de la pareja query–chunk.
  4. Lee la columna cos de la tabla. Los tres primeros se apiñan en 0.98–1.00 y luego hay un salto: la separación útil ocurre entre clusters temáticos, no dentro de ellos.
Comprueba que entiendes: ¿por qué coseno y no distancia euclídea?
Con embeddings normalizados a norma 1 son equivalentes: ‖u−v‖² = 2−2 cos(u,v), así que ordenar por coseno descendente y por distancia ascendente da el mismo ranking. La ventaja del coseno es conceptual: ignora la longitud del vector, que en muchos modelos de embeddings refleja longitud o frecuencia del texto y no su tema. Lo que importa es hacia dónde apunta el significado.

Setup. Quince chunks reales de documentación bancaria (hipotecas, riesgo y mora, tarjetas, normativa) viven en un plano de embeddings 2D: cada punto es φ(dj), proyección didáctica de los 1024 números reales. La flecha dorada es φ(q) para la query elegida. El JS calcula los 15 cosenos de verdad, ordena, y rellena la tabla con el top-k; el sector sombreado cubre el ángulo hasta el k-ésimo clasificado.

Juega. Las queries no comparten palabras con los chunks (pregunta "porcentaje del valor de la vivienda", el chunk dice "80 % del valor de tasación, LTV"): el embedding los acerca por significado, que es justo lo que las keywords no saben hacer. Guarda esa idea para la slide de búsqueda híbrida, donde verás el caso contrario.

Lee así. El lector da el coseno del mejor y del k-ésimo chunk y la apertura del cono en grados: es la imagen mental correcta de qué significa "subir k" en producción.

Mensaje. Recuperar es medir ángulos en un espacio donde el significado es dirección. Todo lo que viene después (recall@k, híbrido, re-ranking) son parches sobre esta geometría cuando la dirección no basta.

Términos. Embedding φ(x): vector que representa el significado de un texto. Cluster: grupo de chunks del mismo tema, próximos en ángulo. Cono de recuperación: región angular que el top-k cubre alrededor de la query.

las ecuaciones de esta slide
Recall@k = |Rel ∩ topk||Rel|,    Precision@k = |Rel ∩ topk|k(calidad del retrieval)
Rel = chunks anotados como relevantes para la query. Recall@k: de todo lo relevante, qué fracción entra en los k recuperados (¿está el chunk gold?). Precision@k: de los k recuperados, qué fracción es relevante (¿cuánto ruido pago?). Al subir k, recall solo puede subir y precision tiende a bajar.
MRR = 1|Q|Σq∈Q 1rankq(Mean Reciprocal Rank)
media, sobre las queries de evaluación, del inverso de la posición del primer chunk relevante: 1 si siempre sale primero, 0.5 si suele salir segundo. Mide lo que el usuario siente: cuánto hay que bajar para encontrar algo útil.
coste = Tsys + k·c + Tq106·pin(el precio de subir k)
cada chunk extra mete c ≈ 400 tokens en el prompt a precio pin = 3 €/millón (modelo medio). Subir k no es gratis: es la conexión entre la métrica de retrieval y la factura.
guion paso a paso
  1. Con la query de hipotecas, sube k de 1 a 4. Recall trepa rápido hasta 0.8: cuatro de los cinco chunks relevantes están en el cluster que el coseno ve bien.
  2. Sigue subiendo hasta k = 13. Recall se queda clavado en 0.8 durante muchísimas k: el quinto chunk relevante (la norma FEIN, que vive en el cluster de normativa) está lejos en ángulo y no entra casi hasta el final. Subir k no arregla un embedding que no lo ve.
  3. Mira el panel de abajo al pasar de k = 4 a k = 14. El coste por consulta se multiplica por ~2.7 para ganar 0.2 de recall al final: cada barra de ganancia marginal es cero mientras pagas tokens.
  4. Selecciona "media de las 4 queries". La curva agregada suaviza los escalones pero el codo sigue en k ≈ 4–6: el k razonable de producción para este corpus.
Comprueba que entiendes: tu evaluador interno dice Recall@5 = 0.88; ¿inviertes en mejor retrieval o en mejor LLM?
En el LLM (o en el prompt): la regla del día es que con Recall@5 ≥ 0.85 el cuello de botella ya es la generación, no el retrieval — el chunk correcto casi siempre está en el contexto, así que los fallos vienen de no usarlo bien. Con Recall@5 < 0.7 sería al revés: mejora embedding y chunking antes de tocar el modelo. Medir retrieval por separado existe exactamente para decidir esta inversión.

Setup. Mismo corpus de 15 chunks y mismas 4 queries de la slide anterior, ahora con las relevancias anotadas a mano (3–5 chunks relevantes por query). El ranking sale del coseno real; las curvas de arriba son Recall@k (dorado) y Precision@k (tinta) calculadas contra esas anotaciones para cada k de 1 a 15. Abajo: la ganancia marginal de recall de cada chunk añadido (barras) y el coste acumulado del contexto en céntimos (línea).

Juega. La forma de las curvas es universal: recall es monótono creciente con escalones, precision decae en cuanto los relevantes se acaban. Lo que cambia entre sistemas es dónde están los escalones: un buen embedding los adelanta, uno malo los retrasa, y la query de hipotecas enseña el caso típico de empresa: un relevante "huérfano" en otro cluster que ninguna k razonable rescata.

Lee así. El lector da Recall@k, Precision@k, el MRR del sistema sobre las 4 queries y los tokens y céntimos del contexto a la k elegida. Coherencia: con k = 15 el recall es 1 en todas las queries (está todo el corpus dentro) y la precision es exactamente |Rel|/15.

Mensaje. k grande compra recall con dos monedas: euros (cada chunk son ~400 tokens facturados) y ruido (precision baja = contexto lleno de distractores, que en la slide del presupuesto verás que degrada la propia generación). Las dos slides siguientes son las dos formas profesionales de no pagar ese precio: híbrido y re-ranking.

Términos. Rel: conjunto anotado de chunks relevantes (el "gold standard" del evaluador). Ganancia marginal: recall@k menos recall@k−1. MRR: posición media (recíproca) del primer acierto.

las ecuaciones de esta slide
scoreα(q,d) = α·côs(q,d) + (1−α)·BM25(q,d)(búsqueda híbrida, Ec. del deck)
mezcla lineal del canal semántico (coseno de embeddings) y el canal léxico (BM25 por keywords), ambos re-escalados a [0,1] sobre el corpus (mín–máx) para que la mezcla tenga sentido. α = 1 es dense puro; α = 0 es BM25 puro; en producción α ≈ 0.7.
BM25(q,d) = Σt∈q IDF(t)·tft,d·(k1+1)tft,d + k1(1−b+b·|d|/L̄)(k1=1.5, b=0.75)
para cada término t de la query: cuántas veces aparece en el chunk (tf), saturado por k1 (la décima aparición ya no suma) y penalizado si el chunk es más largo que la media .
IDF(t) = ln(1 + N−dft+0.5dft+0.5)(rareza del término)
dft = en cuántos de los N = 15 chunks aparece t. Un término que está en todas partes ("banco") vale casi 0; un código que aparece en un único chunk ("7832") vale ln(1+14.5/1.5) ≈ 2.4: BM25 es un detector de términos raros, y los códigos son lo más raro que hay.
chunkcôsBM25score
guion paso a paso
  1. Query A con α = 1 (dense puro). El contrato gold cae al puesto 5: para el embedding, "contrato 2024-BBVA-7832" es solo "un contrato hipotecario más" y los chunks genéricos de hipotecas le ganan en ángulo.
  2. Baja α a 0.3. El gold salta al puesto 1: los tokens 2024, bbva y 7832 aparecen en un único chunk, su IDF es enorme y BM25 los premia sin dudar.
  3. Query B con α = 0 (BM25 puro). Ningún chunk comparte keywords con "dinero para comprar una casa a plazos": BM25 da 0 a todo y el ranking es ruido — el gold cae al fondo.
  4. Busca un α que deje el gold de ambas queries en el top-3. La zona α ≈ 0.5–0.8 funciona para las dos: por eso 0.7 es el default de producción que cita el deck.
Comprueba que entiendes: ¿por qué hay que normalizar BM25 antes de mezclarlo con el coseno?
Porque viven en escalas incomparables: el coseno está acotado en [−1,1] mientras que BM25 es una suma de IDFs sin tope (aquí llega a ~7 con tres términos raros). Sin re-escalar, α no significaría nada: con α = 0.5 el canal BM25 dominaría siempre. El mín–máx por query pone a los dos canales en [0,1] y convierte α en lo que promete ser: la fracción de la decisión que confías al significado frente a las keywords. (Alternativa estándar sin normalizar: fusionar rankings con RRF.)

Setup. Mismo corpus de 15 chunks bancarios, ahora con su texto completo: el JS tokeniza (minúsculas, sin tildes, sin stopwords), calcula df, IDF y BM25 de verdad, re-escala ambos canales a [0,1] y mezcla con α. Arriba: la posición del chunk gold en el ranking según α, para las dos queries (1 = arriba del todo). Abajo: el top-6 actual como barras apiladas, parte dorada = contribución α·côs, parte gris = (1−α)·BM25.

Juega. Las dos queries son los dos extremos del mundo real. La A es el caso "siglas y códigos exactos": contratos, referencias de producto, NIFs, tickets — el embedding los aplana (significan poco) y BM25 los clava (son rarísimos). La B es el caso "paráfrasis": el cliente dice "dinero para comprar una casa a plazos" y el documento dice "hipoteca sobre vivienda habitual" — cero keywords compartidas, BM25 ciego, embedding perfecto.

Lee así. En el panel superior, una curva que baja al bajar α (la A mejora con keywords) y otra que sube (la B se rompe sin semántica): el α bueno es el tramo donde ambas están abajo. En la tabla, mira qué canal aporta cada barra del top: el gold de A vive del gris, el de B vive del dorado.

Mensaje. En producción, híbrido es el default: dense solo no basta. Query "contrato 2024-BBVA-7832": dense lo pierde, BM25 lo encuentra. Es uno de los tres patrones que suben Recall@5 de 0.65 a 0.90 sin cambiar de modelo; el siguiente es el re-ranking.

Términos. BM25: ranking léxico clásico (tf–IDF saturado y normalizado por longitud). IDF: log-rareza de un término en el corpus. Stopword: palabra vacía que se descarta ("de", "la", "que"). RRF: reciprocal rank fusion, alternativa para fusionar rankings sin normalizar scores.

las ecuaciones de esta slide
fase 1: C = topk0 por sbi(q,d)  →   fase 2: top5 de C por sce(q,d)(retrieve & re-rank)
el bi-encoder (embeddings precalculados, coseno: barato) poda el corpus a k0 candidatos; el cross-encoder (lee query y chunk juntos, un forward por par: caro) reordena solo esos k0 y los 5 mejores van al LLM. Toda la arquitectura es una sola idea: gastar el modelo caro únicamente donde el barato ya no distingue.
s = rel + ε,   ε ∼ N(0,σ²),   σce = 0.25 << σbi(modelo de juguete de los scores)
cada documento tiene relevancia verdadera rel ∈ {0,1} y cada encoder la observa con ruido gaussiano: el cross-encoder ve casi la verdad (σ = 0.25), el bi-encoder la ve borrosa (σ ajustable). La calidad P@5 de abajo es un Monte Carlo real sobre 120 réplicas de este modelo.
lat(k0) = 80 + 9·k0 ms(latencia de la cascada)
80 ms de retrieval ANN y formación del batch más 9 ms por cada par (query, candidato) que pasa por el cross-encoder: la factura del re-ranking es lineal en k0, la calidad no.
guion paso a paso
  1. Pon k0 = 5. Equivale a no re-rankear: el conjunto de 5 ya quedó fijado por el bi-encoder y el cross-encoder solo puede reordenarlo, no mejorarlo. Es la línea base discontinua.
  2. Sube k0 a 40. P@5 sube con fuerza y se acerca a la meseta: casi todos los relevantes que el bi-encoder dejó entre el puesto 6 y el 40 son rescatados por el cross-encoder.
  3. Sigue hasta 100. La curva ya es plana pero la latencia sigue subiendo 9 ms por candidato: a partir de la meseta pagas por nada. El codo (k0 ≈ 20–50) es el punto de diseño del deck.
  4. Sube σbi a 1.4 y repite. La curva gana pendiente y la meseta se aleja: cuanto peor es tu retrieval barato, más relevantes se esconden en puestos tardíos y más paga el re-ranking.
Comprueba que entiendes: ¿por qué no pasar los 200 documentos por el cross-encoder y olvidarse del bi-encoder?
Por coste y latencia: el cross-encoder hace un forward completo por cada par (query, documento) — 200 pares son 80 + 9·200 = 1880 ms por consulta, y en un corpus real serían 350 000 forwards: días de GPU por pregunta. El bi-encoder existe porque sus embeddings se precalculan una vez en la ingesta y la consulta es solo un producto escalar: es la única pieza que escala con J. La cascada es la respuesta general: filtro barato sobre todo, modelo caro sobre poco.

Setup. 200 documentos candidatos, de los que 12 son relevantes de verdad. El bi-encoder y el cross-encoder puntúan cada uno con el modelo de ruido del panel de ecuaciones (simulado con semillas reproducibles). Arriba: la calidad final P@5 (fracción de los 5 chunks enviados al LLM que son relevantes), promediada sobre 120 réplicas Monte Carlo, en función de k0; en gris, la latencia. Abajo: el embudo de una réplica concreta: 200 → k0 → 5, con el número de relevantes que sobrevive en cada etapa.

Juega. El slider de k0 es el único hiperparámetro del patrón: cuántos candidatos baratos le confías al juez caro. El botón de réplica enseña la variabilidad: en una réplica concreta el embudo puede tener suerte o no, pero la curva (el promedio) es estable: así se decide en ingeniería, sobre la curva, no sobre la anécdota.

Lee así. P@5 en la línea base (k0 = 5, sin re-ranking) contra P@5 en tu k0: esa diferencia es lo que el cross-encoder compra; la latencia de al lado es lo que cuesta. El deck lo resume: recuperar 20 barato, re-rankear con bge-reranker-large, mandar 5 al LLM.

Mensaje. El re-ranking desacopla dos problemas que el coseno mezcla: encontrar candidatos (recall, barato, escala con J) y ordenarlos bien (precision, caro, escala con k0). Junto con híbrido y query rewriting, es el tercer patrón que sube Recall@5 de 0.65 a 0.90 sin tocar el modelo generador.

Términos. Bi-encoder: embebe query y documento por separado; similitud = coseno; precalculable. Cross-encoder: procesa el par junto y devuelve un score; no precalculable. P@5: precision sobre los 5 chunks finales. Meseta: zona donde subir k0 ya no mejora la calidad.

las ecuaciones de esta slide
Tin = Tsys + k·c + Tq(presupuesto de contexto)
el prompt de un RAG son tres sumandos: el system prompt (Tsys = 400 tokens de instrucciones y formato de cita), los k chunks de c tokens cada uno, y la pregunta del usuario (Tq = 60). Si Tin + Tout supera la ventana del modelo, la llamada se rechaza: la ventana es un límite duro, no una preferencia.
cobertura(k) = 1 − i=1..k(1−pi),   pi = p1·γi−1(p₁=0.55, γ=0.75)
probabilidad de que la respuesta esté en el contexto: el chunk del puesto i la contiene con probabilidad pi, decreciente en el ranking (γ), y basta con que uno acierte. Crece rápido y satura: el chunk 10 ya casi no añade nada.
calidad = cobertura(k)·e−(Tin/Tatt·F,    coste = Tin·pin + Tout·pout106(Tatt=9000, F=0.95)
el factor gaussiano modela el lost in the middle: a más tokens de contexto, menos atención efectiva sobre el chunk correcto. El producto cobertura×atención es la curva en U invertida: poco contexto = no sabe, demasiado = se pierde. Y cada token entra en la factura a pin.
guion paso a paso
  1. Pon k = 1. Cobertura 0.55: casi la mitad de las veces el chunk correcto no está y el modelo "no sabe" (o peor: alucina con confianza).
  2. Sube a k = 6. Máximo de la curva: cobertura ≈ 0.90 con la atención todavía ≈ 0.92. Este es el punto dulce que explica el "k = 3–10 típico" de la nota del día.
  3. Pon k = 30 y c = 800 con el modelo compacto. Salta el badge de desbordamiento: 24 760 tokens no caben en 8k. La ventana corta la curva antes de que la atención la hunda.
  4. Cambia al modelo frontera (128k). El badge desaparece pero la calidad sigue cayendo: la ventana grande quita el error duro, no el blando. Más contexto no es monótonamente mejor ni aunque quepa.
Comprueba que entiendes: ¿por qué la calidad tiene forma de U invertida en vez de saturar y quedarse plana?
Porque hay dos fuerzas con signos opuestos: la cobertura crece con k (más chunks = más probable que la respuesta esté dentro) pero satura geométricamente, mientras que la atención efectiva decae con los tokens totales (el modelo diluye su atención entre más distractores: el efecto "lost in the middle" medido en la literatura). El producto de una curva que satura por una que decae siempre tiene un máximo interior. En cuanto la cobertura deja de ganar más de lo que la atención pierde, cada chunk extra resta calidad además de costar dinero.

Setup. Arriba: el prompt como barra apilada (system + k chunks + pregunta + respuesta reservada) contra la ventana del modelo elegido; si la suma se pasa, la barra se desborda y el badge avisa. Abajo: la calidad estimada del modelo de juguete frente a k, con la zona prohibida por la ventana sombreada y tu k marcada. Todos los números (tokens, euros, cobertura, atención) salen de las fórmulas del panel, calculadas en vivo.

Juega. k y c son los dos diales que ya tocaste en chunking y recall@k; aquí ves su consecuencia final en la generación. Observa la interacción con el precio: en el modelo frontera, pasar de k = 5 a k = 25 con c = 400 sube el coste por consulta de ~0.06 € a ~0.18 €: multiplicado por 5000 consultas/día son 600 € diarios por contexto que además resta calidad.

Lee así. El lector da Tin y su desglose, el coste por consulta, la cobertura, la atención y su producto. El badge verde/ámbar es el contrato duro con el proveedor: cabe o no cabe.

Mensaje. El contexto es un presupuesto, no un saco: cada token compite por atención y por euros. RAG bien hecho es mandar pocos chunks muy buenos (de ahí híbrido y re-ranking), no muchos chunks por si acaso.

Términos. Ventana de contexto: máximo de tokens (entrada + salida) que el modelo acepta. Lost in the middle: degradación empírica del uso de información enterrada en contextos largos. pin/pout: precio por millón de tokens de entrada/salida.

las ecuaciones de esta slide
Cemb = Tokcorpus106·pemb  (una sola vez),    J = Tokcorpus400
indexar el corpus entero: todos sus tokens pasan una vez por el modelo de embeddings a pemb = 0.10 €/millón. Con los 12 GB de normativa del caso (≈ 144 millones de tokens útiles, ≈ 360 000 chunks de 400) son ~14 €. Una vez.
cq = Tin·pin + Tout·pout106 + crr,    Cmes = Qdía·30·cq + Cinfra(el coste que sí duele)
cada consulta paga su contexto y su respuesta al modelo generador (más crr ≈ 0.0005 € de re-ranker si lo usas), y el mes multiplica por Qdía·30. Cinfra = 150 €/mes del servidor pgvector. La asimetría una-vez frente a cada-día es la lección entera de la slide.
Almacén = J·(D·1 + 1800)·1.4 bytes(vectores int8 + texto + índice)
cada chunk guarda su vector (D = 1024 dimensiones a 1 byte, cuantizado a 8 bits) y su texto con metadatos (≈ 1800 bytes); el factor 1.4 es el overhead del índice HNSW. Para el caso BBVA salen ~1.4 GB: coincide con el 1.5 GB en pgvector de la nota técnica.
conceptocantidadcoste
guion paso a paso
  1. Deja los valores del caso (12 GB, 5000 q/día, k = 10, re-rank, modelo medio). Embedding inicial ~14 € una vez; generación ~1500 €/mes: lo caro no es indexar el banco, es atender el día a día.
  2. Sube el corpus a 100 GB. El embedding inicial sigue por debajo de 150 € y el coste mensual casi ni se mueve: el tamaño del corpus no entra en cq. Indexa sin miedo.
  3. Cambia a modelo frontera. El mensual se multiplica por ~5: la elección del generador es la palanca de coste número uno de un RAG.
  4. Desactiva el re-ranking. Van 10 chunks al LLM en vez de 3: Tin casi se triplica y el mensual sube más de lo que costaba el re-ranker. El cross-encoder se paga solo.
Comprueba que entiendes: ¿por qué el coste mensual escala con Qdía y no con J?
Porque J solo aparece en los costes de capital: el embedding inicial (proporcional a los tokens del corpus, una vez) y el almacenamiento (gigabytes, céntimos al mes). En cambio, cada consulta toca exactamente k chunks, da igual que el índice tenga 360 000 o 36 millones: Tin = 400 + k·400 + 60 no contiene J. Esa independencia es el contrato económico de RAG: el conocimiento crece sin que crezca el coste marginal de usarlo.

Setup. Las dimensiones reales del caso del deck: 12 GB de normativa interna, contratos y FAQ; ~350 000 chunks de ~400 tokens; embedding multilingüe e5-large de D = 1024; almacenamiento ~1.5 GB en pgvector con cuantización a 8 bits; consulta top-10 + re-rank a top-3 + generación; ~1.8 s y ~0.02 $ por consulta. Los sliders reconstruyen ese presupuesto entero con las fórmulas del panel: arriba, el coste mensual frente a las consultas/día para los tres modelos generadores; abajo, la asimetría entre lo que se paga una vez y lo que se paga cada mes.

Juega. Este es el simulador que llevarías a la reunión de presupuesto: mueve consultas/día para ver el punto donde conviene bajar de modelo, y el corpus para comprobar que crecer en conocimiento es casi gratis. La tabla en vivo desglosa cada partida con su fórmula detrás.

Lee así. Con los valores por defecto el coste por consulta ronda 0.01–0.02 €, como en la nota técnica; un agente humano que tarda 10 minutos en buscar la misma respuesta cuesta tres órdenes de magnitud más. Ese cociente, no la demo, es lo que aprueba el proyecto.

Mensaje. El RAG corporativo es económicamente asimétrico: indexar el banco entero cuesta decenas de euros; servirlo cuesta miles al mes y escala con el uso. Optimiza en este orden: modelo generador, k efectivo (re-ranking), tamaño de chunk — y deja el corpus crecer.

Términos. e5-large: modelo de embeddings multilingüe abierto (D = 1024). pgvector: extensión de Postgres para búsqueda vectorial. Cuantización 8-bit: guardar cada dimensión en 1 byte en vez de 4. Coste de capital vs operativo: una vez (indexar) frente a recurrente (servir).

Por qué RAG
Slide: Por qué RAG
"El conocimiento del modelo se congela en la fecha de corte y decae como f(t) = e−λt; los documentos viven. Pcon = R·F + (1−R)·Psin: la ventaja de RAG crece con cada mes, y vale exactamente lo que valga su retrieval."
Pipeline canónico
Slide: Pipeline
"Ingesta una vez (chunking → φ → índice de J×D), consulta cada vez (topk por coseno → LLM con citas). La memoria y la búsqueda escalan con J; el coste por consulta solo con k: esa separación es el diseño entero."
Chunking
Slide: Chunking
"La ventana óptima es la unidad coherente más pequeña: chunks pequeños fragmentan la respuesta (recall cae), grandes la diluyen entre ruido (precision cae). 300–600 tokens, solape de 50–100, metadatos siempre."
Retrieval y sus patrones
Slides: Coseno · Recall@k · Híbrido · Re-ranking
"El coseno ordena por ángulo; recall@k y precision@k miden contra relevancias anotadas; el híbrido α·cos + (1−α)·BM25 rescata códigos y siglas que el embedding aplana; el re-ranking gasta el cross-encoder caro solo sobre los k0 candidatos que el bi-encoder barato ya filtró."
Presupuesto de contexto
Slide: Contexto
"Tin = Tsys + k·c + Tq contra una ventana que es límite duro; la calidad es cobertura × atención, una U invertida con máximo en k ≈ 4–8. Pocos chunks muy buenos, no muchos por si acaso."
Caso BBVA dimensionado
Slide: Caso BBVA
"12 GB → 360 000 chunks → ~14 € de embedding una vez y ~1.4 GB en pgvector; servir 5000 consultas/día → miles de €/mes que escalan con el uso y con el modelo elegido, nunca con J. Indexa sin miedo; optimiza el generador y el k."

En una frase. RAG convierte el conocimiento corporativo en un sistema auditable con citas: cada pieza del pipeline tiene un dial (s, o, k, α, k0, modelo), cada dial tiene una métrica (recall@k, precision@k, faithfulness) y cada métrica tiene un precio en euros — y el Día 16 veremos cuándo, pese a todo, hay que ajustar el modelo.

Garrido-Merchán — ecgarrido@comillas.edu — Deep Learning para Business Analytics — Día 15 · RAG corporativo