Blog
Análisis técnicos

Construyendo un pipeline RAG híbrido con Reciprocal Rank Fusion

Cómo la similitud vectorial y la búsqueda full-text de PostgreSQL corren en paralelo y se fusionan mediante Reciprocal Rank Fusion en respuestas con citas y puntuaciones de relevancia.

Simmetric Team7 min de lectura12/06/2026

Por qué una sola estrategia de recuperación nunca basta

El retrieval-augmented generation se sostiene o se cae con lo que el retriever entrega al modelo. Pregunta a una base de conocimiento, y la respuesta es tan buena como los chunks que la preceden - y las preguntas enterprise llegan en dos formas que ninguna estrategia de búsqueda única maneja bien.

Las preguntas semánticas - "¿cómo maneja la facturación la prorata?", "¿qué decidimos sobre el vendor lock-in?" - tratan sobre el significado. La búsqueda vectorial brilla aquí: incorpora la consulta y los chunks de documentos al mismo espacio y recupera los vecinos más cercanos, así un chunk escrito con palabras completamente diferentes puede salir a la superficie. Pero la búsqueda puramente vectorial no es fiable para la otra forma de pregunta: los identificadores exactos. Códigos de producto, cadenas de error, números de reglamento, nombres de personas - los embeddings los difuminan, y el vecino más cercano a un código de error oscuro suele ser otro código, no relacionado.

Las preguntas por palabras clave son la imagen espejo. La búsqueda full-text de PostgreSQL acierta tokens exactos y términos raros, pero pierde las paráfrasis por completo: pregunta por "ampliación de personal" y no encontrará el documento que dice "contratación de proveedores".

Los documentos corporativos reales atraen ambos tipos de preguntas, a menudo en la misma sesión. Simmetric Chat por tanto se niega a elegir. Cada recuperación ejecuta dos piernas en paralelo - similitud vectorial y búsqueda full-text de PostgreSQL - y fusiona los resultados con Reciprocal Rank Fusion (RRF) antes de que nada llegue al modelo. Este artículo recorre ese pipeline: las dos piernas, las matemáticas de la fusión, la ruta de ingesta que las alimenta y la capa de citas que hace auditable las respuestas.

Dos piernas, una consulta

Cuando un chat necesita conocimiento, el agente ReAct invoca su skill rag_search, y la búsqueda híbrida inicia dos recuperaciones independientes a la vez:

  • La pierna vectorial sale del servidor y llama al collector, el servicio que posee el almacén vectorial. El collector incorpora la consulta con el mismo modelo de embedding usado en la ingesta y devuelve los chunks más cercanos de la colección del workspace. El almacén vectorial en sí es conectable - LanceDB por defecto (basado en archivos, local, amigable con air-gap), o Qdrant, pgvector o Chroma para despliegues que prefieran un índice del lado del servidor.
  • La pierna full-text nunca sale del servidor. Consulta PostgreSQL directamente, comparando la consulta contra una columna vectorial full-text concatenada en la tabla de chunks, respaldada por un índice GIN y clasificada por relevancia léxica. La tokenización es consciente del idioma en siete lenguas, así que los documentos italianos y alemanes se pueden buscar con sus propias reglas de palabras en lugar de aproximaciones inglesas.

Las colecciones son por workspace, que es lo que mantiene el conocimiento aislado: un chat en el workspace A recupera de los chunks del workspace A y nada más. Ejecutar ambas piernas en cada consulta cuesta un viaje de ida y vuelta extra y compra una cobertura que ninguna pierna tiene sola.

El modo de fallo también es deliberadamente redundante. Un guard compara el modelo de embedding configurado hoy con el que se usó para incorporar los documentos del workspace. Ante un desajuste - tras un cambio de modelo, por ejemplo - la pierna vectorial se omite por completo y la recuperación degrada a solo full-text, en lugar de servir puntuaciones de similitud de espacios de embedding incomparables. El chat sigue funcionando, y el operador obtiene una ruta de reindexación explícita en el panel de administración en lugar de una regresión de calidad silenciosa.

Reciprocal Rank Fusion, concretamente

Las dos piernas devuelven listas clasificadas medidas en escalas inconmensurables: similitud coseno por un lado, relevancia léxica por el otro. Promediar las puntuaciones brutas significaría calibrar esas escalas entre sí - frágil, y diferente para cada modelo de embedding y cada corpus. Simmetric Chat fusiona rangos en lugar de puntuaciones, usando Reciprocal Rank Fusion:

text
fused(chunk) = sum over legs of 1 / (k + rank),  with k = 60

Cada chunk acumula una contribución por pierna en la que aparece, así un chunk clasificado primero en ambas piernas puntúa aproximadamente el doble que un chunk clasificado primero solo en una. La constante k amortigua la influencia de los rangos superiores - con k = 60, la diferencia entre el rango uno y el cinco en una sola pierna es un delta pequeño, y el consenso entre piernas es lo que realmente sube a un chunk en la lista fusionada.

Dos detalles de ingeniería hacen que la fusión sea de grado producción en lugar de libro de texto:

  • Un conjunto de fuentes por chunk registra si fue encontrado por la pierna vectorial, la full-text o ambas. Un chunk recuperado por ambas piernas es la corroboración más fuerte que el pipeline puede producir, y el formateo aguas abajo preserva esa señal en lugar de aplanarla.
  • Un desempate determinista - puntuación fusionada descendente, luego identificador de documento, luego posición del chunk - garantiza que la misma consulta devuelva el mismo orden en cada réplica. Cuando alguien pregunta "¿por qué citó este párrafo?", la respuesta tiene que ser reproducible; la fusión no determinista haría la pregunta incontestable.

De documentos a chunks buscables

La fusión es solo la mitad del pipeline; la otra mitad ocurre en la ingesta, cuando un documento subido se convierte en chunks que ambas piernas pueden buscar. El collector analiza archivos PDF, Word, Excel, PowerPoint, Markdown, CSV y transcripciones de YouTube, divide el texto con un divisor recursivo por caracteres (1.000 caracteres por chunk, 200 caracteres de solapamiento para que las frases que cruzan un límite no se pierdan), incorpora cada chunk y escribe los vectores en la colección del workspace.

Crucialmente, el texto del chunk también aterriza en PostgreSQL, donde el servidor mantiene el vector de búsqueda full-text que consulta la pierna FTS. El collector nunca toca la base de datos relacional - una frontera de servicio dura que mantiene intercambiable el pipeline de análisis-e-incorporación y deja el índice de búsqueda en propiedad del servidor que lo consulta.

La versión 0.22 hizo la recuperación precisa en una segunda dimensión: el filtrado por metadatos. El agente ahora puede acotar una llamada rag_search a tipos de documento (PDF, Markdown, TXT, CSV, DOCX, XLSX) y a ventanas de fecha de ingesta, lo que corrige el clásico fallo de "documentos de 2023 respondiendo preguntas de 2025". Los filtros atraviesan ambas piernas - como prefiltros sobre metadatos de ingesta sellados en los almacenes vectoriales, y como predicados SQL parametrizados en el lado full-text. Un respaldo de metadatos del lado del servidor vuelve a comprobar cada resultado fusionado contra la tabla de documentos autoritativa, así la corrección del filtro no depende de que cada proveedor vectorial implemente los predicados perfectamente. Los vectores heredados ingeridos antes del sellado de metadatos simplemente se caen mientras un filtro está activo, y recuperan la filtrabilidad mediante un re-embed activado por el admin.

Respuestas que muestran su trabajo

La calidad de la recuperación es solo la mitad de la historia; la otra mitad es la honestidad sobre en qué se fundamenta la respuesta. Las citas fluyen por el mismo canal de streaming que los tokens: las insignias de cita se muestran en línea en la respuesta, cada una con el documento fuente, el chunk y una puntuación de relevancia, y cada una enlazando a la fuente para que el lector pueda verificar la afirmación con un clic.

La disciplina de frescura también vive aquí. Tras deduplicar los resultados fusionados, un filtro de anclaje limita las citas por documento a las dos mejores por puntuación de relevancia y descarta las citas de chunks cuyo texto no comparte solapamiento léxico significativo con la respuesta final. La puerta es deliberadamente conservadora - las páginas wiki, los resultados de archivo y las respuestas muy cortas siempre se conservan - pero elimina el modo de fallo donde una respuesta dice "no hay más información" mientras muestra "Fuentes (5)" extraídas de un único documento marginalmente relacionado. El aviso de "sin evidencia de apoyo" se juzga contra el mismo conjunto filtrado, así el aviso y la lista de fuentes siempre describen la misma realidad.

Elegir y ajustar la pila

El pipeline es deliberadamente dirigido por configuración, y los valores por defecto son los que priorizan la privacidad:

  • Almacén vectorial: LanceDB por defecto - basado en archivos, almacenado localmente, sin servicio externo requerido, totalmente compatible con air-gap. Qdrant, pgvector y Chroma están a un cambio de entorno cuando un despliegue lo supera; el proveedor se selecciona en el arranque.
  • Embeddings: transformadores locales (384 dimensiones, completamente sin conexión) por defecto, o embeddings de OpenAI cuando un despliegue acepta la llamada saliente. Cambiar el modelo de embedding requiere un re-índice, que el panel de administración dirige; el guard de desajuste mantiene el sistema a salvo en el ínterin.
  • Re-ranking: opcional. Un reranker puede sobre-recuperar y reordenar los resultados fusionados cuando la calidad de la respuesta importa más que la latencia.
  • Constante de fusión: k = 60 se entrega por defecto; es una constante única en el servicio de búsqueda híbrida si sus distribuciones de clasificación requieren un amortiguamiento diferente.

El recorrido completo del flujo de datos - la frontera servidor-collector, la disposición de almacenamiento detrás de cada proveedor vectorial y los eventos de cita en streaming - está documentado en la guía de arquitectura.

Leer la guía completa en la documentación →

Artículos relacionados