Saltearse al contenido

Técnicas de recuperación

Recuperar es encontrar, entre todos tus fragmentos, los que responden a la pregunta. La búsqueda básica por significado ya funciona bien con muchas preguntas, pero falla con otras: códigos exactos, preguntas que necesitan un filtro, fragmentos que no dicen de qué hablan o preguntas de recuento. Cada técnica de esta página arregla uno de esos casos, y casi todas se combinan entre sí conectando componentes.

Qué técnica para qué pregunta

Resultados medidos el 17 de octubre de 2026 con una base de conocimiento de prueba (9 documentos de un servicio técnico de cafeteras, 40 preguntas). Cada celda dice en qué porcentaje de preguntas la respuesta correcta fue el primer resultado / estuvo entre los cinco primeros. Las filas con Local Rerank se volvieron a medir el 18 de octubre con su modelo actual. Son pocas preguntas por tipo (de 6 a 10): muestran cómo se comporta cada técnica, no lo que pasará con tus datos.

Tipo de preguntaEjemploBúsqueda básicaMejor técnica medidaCon ellaCoste añadido por pregunta
Dicha con otras palabras«¿Cada cuánto hay que renovar las gomas que sellan el portafiltros?»80 % / 100 %Multi Query Retrieverdel 90 al 100 % / 100 %1 llamada a un modelo, unos 1,2 s
Código o referencia exacta«¿Qué pieza es la JT-777?»50 % / 88 %Local Rerank75 % / 100 %Sin modelo de lenguaje, unos 1,2 s
Necesita un filtro (marca, mes, tipo)«¿Qué significa el error E07 en la Vellani Aurora?»33 % / 33 %Fragmentos con contexto + híbrida + Local Rerank33 % / 100 %Sin modelo de lenguaje al preguntar, unos 2 s
El fragmento no dice de qué habla«¿Qué recomendó el informe de septiembre sobre los descalcificadores?»67 % / 100 %Fragmentos con contexto (búsqueda básica)67 % / 100 %Ninguno al preguntar
Relaciones o recuentos«¿Cuántas incidencias abiertas tiene Lucía Ortega?»0 de 6 respuestas correctasNeo4j GraphRAG en Text2Cypher con 2 ejemplos5 de 61 llamada a un modelo, unos 1,1 s
No está en tus documentos«¿Cuánto cuesta una Vellani Aurora 3G nueva?»Un umbral de parecido no las distingueLocal Rerank con Minimum Relevance 0,01Rechazó 2 de 4, sin rechazar ninguna de las 36 que sí tenían respuesta, pero por muy poco margen: alguna respuesta buena sacó 0,011Ninguno más que el reordenado

Dos cosas más que salen de la misma medición:

  • Reordenar también ayuda cuando el fragmento no dice de qué habla: la respuesta fue el primer resultado en 5 de 6 de esas preguntas, frente a 4 de 6 sin reordenar. Aun así, la mejor combinación sigue empezando por preparar los fragmentos con Contextual Text Splitter.
  • Las preguntas de recuento no se resuelven con fragmentos. La mejor combinación de fragmentos respondió bien 2 de 6. Si tus usuarios preguntan «cuántos», «quién tiene más» o «cuáles están abiertas», esos datos tienen que estar en una base que se consulta. Ver GraphRAG con Neo4j.

Las técnicas, una a una

Búsqueda por similitud

Lo que hace cualquier base vectorial con Search Type en Similarity: devuelve los Number of Results fragmentos más parecidos a la pregunta. Es rápida (decenas de milisegundos) y encontró la respuesta entre los cinco primeros en el 83 % de las preguntas sobre documentos. Es la base de todo lo demás.

Umbral de puntuación

Con Search Type en Similarity with score threshold, la base descarta los resultados por debajo de Search Score Threshold. Sirve para quitar ruido evidente, pero no para detectar preguntas sin respuesta: en nuestra medición, la pregunta por el precio de una máquina nueva (que no estaba en los documentos) se parecía más a los documentos que la mayoría de las preguntas que sí tenían respuesta, porque compartía el nombre del modelo. Para eso usa la relevancia de Local Rerank (ver más abajo).

Resultados variados (MMR)

Qdrant ofrece MMR (Max Marginal Relevance) en Search Type: en lugar de los cinco fragmentos más parecidos, que a veces dicen lo mismo, devuelve fragmentos parecidos a la pregunta pero distintos entre sí. Útil cuando tienes muchos documentos casi iguales (versiones, informes mensuales). En nuestra medición no cambió el resultado de forma clara.

Búsqueda por palabras (BM25)

BM25 Retriever busca los fragmentos que contienen las palabras de la pregunta y da más peso a las palabras poco frecuentes, como un código. No distingue mayúsculas, tildes ni signos, y compara los códigos con guiones enteros: «jt-777?» encuentra «JT-777:». Lee los fragmentos de la base que conectas a Parent document vectorstore (la salida Vector Store de la base).

¿Hace falta preparar algo para BM25? No. Usa los mismos fragmentos que ya guardaste en la base vectorial, tal cual, sin una segunda ingesta ni otro formato: en cada ejecución los lee de la base (todos en FAISS, Chroma y Qdrant; hasta 10.000 en las demás) y construye en ese momento su índice de palabras. Si troceaste con Contextual Text Splitter, también busca en la frase de contexto de cada fragmento. Lo único a tener en cuenta es el volumen: con colecciones muy grandes, leerlas en cada pregunta tarda más.

Sola, encontró los códigos exactos tan bien como la búsqueda por significado (88 % entre los cinco primeros) y fue peor con las preguntas dichas con otras palabras. Su sitio es la búsqueda híbrida.

Búsqueda híbrida (palabras + significado)

Ensemble Retriever consulta a la vez varios buscadores y mezcla sus listas. Para una búsqueda híbrida conecta a Retrievers la salida Retriever de BM25 Retriever y la salida Retriever de tu base vectorial. En Weights decides cuánto cuenta cada uno, en el orden en que los conectaste: 0.5, 0.5 es un buen punto de partida.

Con pesos iguales, la respuesta estuvo entre los cinco primeros en el 83 % de las preguntas, igual que la búsqueda básica, y en el 100 % de las preguntas por código exacto (88 % sin ella). No cuesta llamadas a modelos y añade unos milisegundos.

El vídeo de Reordenación con Local Rerank monta esta búsqueda híbrida y la reordena.

Multi Query

Multi Query Retriever pide a un modelo que reescriba la pregunta de varias formas (Number of Questions, 3 por defecto), busca con todas y junta los resultados. Con las preguntas dichas con otras palabras puso la respuesta primera en el 90 % al 100 % de los casos según la ejecución, porque el modelo no siempre escribe las mismas versiones (80 % sin él). Cuesta una llamada a un modelo por pregunta, unos 1,2 segundos. El registro de cada ejecución muestra las preguntas con las que buscó.

Este vídeo muestra cómo Multi Query Retriever encuentra una respuesta que la búsqueda normal no ve cuando la pregunta usa otras palabras, y cómo la compresión deja solo los resultados útiles.

Lo que ves en el vídeo:

  1. Una pregunta dicha con otras palabras, del tipo «si una reparación se vuelve a estropear a los pocos meses, ¿me lo cobráis otra vez?». La búsqueda normal no trae el apartado de la garantía de las reparaciones.
  2. Multi Query Retriever escribe 3 versiones de la pregunta y busca también con la original: ahora sí encuentra ese apartado.
  3. El registro de la ejecución muestra las preguntas con las que buscó.
  4. Contextual Compression Retriever, con un modelo que revisa 10 resultados y descarta los que no responden, se queda solo con unos pocos: el registro dice cuántos encontró y cuántos conservó.

Self Query: filtros que escribe un modelo

Self Query Retriever lee la pregunta y escribe la búsqueda con sus filtros. «El error E07 en la Vellani» se convierte en «error E07» con el filtro marca = Vellani. Describes en Metadata Schema los datos por los que se puede filtrar (el mismo formato que Metadata Tagger).

  • Con los datos de cada documento (tipo, marca, mes), acertó entre los cinco primeros el 83 % de las preguntas que necesitaban filtro, frente al 33 % sin filtros.
  • El registro de cada ejecución muestra la búsqueda y el filtro que escribió el modelo, por ejemplo marca = "Vellani".
  • Nunca falla por el filtro: si la respuesta del modelo no se puede leer, si la base no puede aplicar el filtro (un rango sobre un campo de texto) o si nada lo cumple, busca sin filtro y el registro lo dice.
  • Funciona con FAISS, Chroma DB, Qdrant, PGVector y otras bases de la paleta. Con FAISS acertó el mismo 83 % que con Qdrant.
  • Enumera los valores que toma un campo (enum en el esquema) para que el modelo los escriba como están guardados.
  • Cuesta una llamada a un modelo por pregunta, alrededor de 1 segundo.

Este vídeo muestra cómo Self Query Retriever convierte una pregunta por marca y mes en un filtro, y encuentra lo que la búsqueda normal se deja.

Lo que ves en el vídeo:

  1. En el flujo de ingesta, el esquema de Metadata Tagger con los datos de cada fragmento: marca, tipo de documento, mes y códigos.
  2. Self Query Retriever sobre Qdrant, con el mismo esquema en Metadata Schema y los valores permitidos de cada campo.
  3. A «¿Qué incidencias tuvieron las Vellani en julio?», el modelo escribe el filtro and(eq("marca", "Vellani"), eq("mes", "2026-07")).
  4. Con ese filtro vuelven los dos fragmentos de julio de Vellani, con las tres incidencias: Cafetería Triana, Cervecería Macarena y Cafetería San Bernardo.
  5. La búsqueda sin filtro se deja alguna de ellas.

Si prefieres filtros fijos o que los rellene el agente, usa los filtros de la propia base, en la sección siguiente.

Filtros por metadatos en la base vectorial

FAISS, Chroma DB, Qdrant, PGVector, Neo4j y Elasticsearch tienen el mismo filtro, Filter by Metadata: filas de campo, operador y valor (Manual) o un JSON como {"marca": "Vellani"} (Dynamic). Se aplica a la búsqueda, al Retriever y al modo herramienta, y el agente puede rellenar el valor él mismo. Cómo se configura, en Filtrar por metadatos.

Medido en las seis bases con las 6 preguntas que necesitan filtro (primer resultado / entre los cinco primeros):

Cómo se filtraResultadoCoste añadido
Sin filtro33 % / 33 %—
Filtro fijo (marca, mes o tipo igual al de la pregunta)33 % / 100 %Ninguno: misma latencia que sin filtro
El agente escribe el filtro (modo herramienta, DeepSeek)33-50 % / 83 %La llamada al modelo que el agente ya hace
  • El filtro deja la respuesta entre los cinco primeros en todas las preguntas, pero no la sube al primer puesto: dentro del documento correcto sigue mandando el parecido. Combínalo con Local Rerank si necesitas la respuesta arriba.
  • El agente escribió un filtro correcto en las 6 preguntas; la diferencia con el filtro fijo viene de cómo reescribió la búsqueda.
  • Con datos en forma de lista, como las etiquetas de Metadata Tagger, Contains dio el mismo 100 % en FAISS, Qdrant, PGVector y Elasticsearch. Chroma DB y Neo4j no miran dentro de listas.

Este vídeo muestra cómo un filtro por marca deja fuera los fragmentos de otras marcas, primero con una condición fija y después con un agente que rellena el valor.

Lo que ves en el vídeo:

  1. Sin filtro, «¿Qué significa el error E07?» devuelve fragmentos de marcas distintas: el mismo código significa cosas diferentes en cada una.
  2. Con una fila en modo Manual (Field marca, Operator Equal, Value Vellani), todos los resultados son de Vellani.
  3. La lista de operadores, con In y Contains para las etiquetas de códigos, y cómo se combinan varias condiciones.
  4. Un Agent con la base como herramienta, donde Condition 1: Value lo rellena la IA: en la llamada a la herramienta se ve filter_1_value: "Vellani" y la respuesta es el E07 de Vellani (caudalímetro bloqueado, pieza VL-1180).
  5. El filtro funciona igual en FAISS, Chroma DB, PGVector, Neo4j y Elasticsearch.

Reordenación con Local Rerank

Local Rerank recibe los candidatos de un buscador y los vuelve a ordenar con un modelo que lee a la vez la pregunta y cada fragmento. Es más preciso que comparar vectores y funciona dentro de la plataforma: gratuito, multilingüe (español, inglés y muchos más) y sin clave de API.

CampoQué poner
RetrieverLa salida Retriever de tu base o de un Ensemble Retriever. Pídele más resultados de los que quieres conservar, por ejemplo 12 o 20.
Results to KeepCuántos de los mejores se devuelven. 4 o 5 es lo habitual.
Minimum Relevance (avanzado)Descarta los resultados con una relevancia (de 0 a 1) por debajo de este valor. Con 0 (por defecto) no descarta nada. Las respuestas buenas pueden sacar notas de solo 0,01, así que solo valores muy bajos son seguros; valores como 0,15 ya descartan respuestas buenas.
Model (avanzado)El de por defecto es multilingüe. Los demás son más pequeños y solo para inglés.

Con la búsqueda básica más Local Rerank, la respuesta fue el primer resultado en el 77 % de las preguntas sobre documentos, frente al 60 % sin reordenar, y las preguntas por código exacto pasaron de tenerla primera en el 50 % de los casos al 75 %. Tiempo: unos 1,2 segundos por pregunta con 20 candidatos, y crece con el número de candidatos.

Este vídeo compara la búsqueda normal con la búsqueda híbrida más la reordenación, en una pregunta por una referencia de pieza.

Lo que ves en el vídeo:

  1. Qdrant sola, con sus 5 primeros resultados, no trae la pieza MO-305.
  2. BM25 Retriever y Qdrant unidos en Ensemble Retriever con Weights 0.5, 0.5, y Local Rerank detrás: pide 20 candidatos y se queda con los 5 mejores.
  3. El primer resultado es la lista de recambios del manual del molino, donde está «MO-305: condensador de arranque de 20 µF», con una relevancia de 0,55.
  4. La misma combinación, conectada como herramienta de un Agent, responde bien a la pregunta.

Reordenación con Cohere Rerank

Cohere Rerank hace lo mismo con el servicio de Cohere: necesita su credencial y cuesta por uso. Si tus textos están en español, elige un modelo multilingüe en Model (rerank-multilingual-v3.0 o rerank-v3.5), porque el de por defecto es para inglés. No lo hemos incluido en la medición.

Compresión con un modelo

Contextual Compression Retriever depura los resultados de otro buscador con un modelo. Con Compressor en LLMChainFilter, el modelo lee cada resultado y descarta los que no responden. En nuestra medición se quedó con 2 o 3 de 10 resultados de media, nunca descartó la respuesta correcta y la puso primera en el 88 % de las preguntas (75 % sin él). Cuesta una llamada a un modelo por resultado (10 llamadas para 10 resultados), en paralelo: alrededor de 1 segundo. Es el compresor por defecto. LLMChainExtractor, que deja solo las frases que responden, puso la respuesta primera en el 94 % pero tardó 8,8 segundos; EmbeddingsFilter no hace llamadas a un modelo, pero su umbral hay que ajustarlo a tu modelo de embeddings: con 0,4 una pregunta se quedó sin resultados.

El vídeo de Multi Query termina con Contextual Compression Retriever filtrando 10 resultados.

Fragmento pequeño, documento completo

Multi Vector Retriever busca en fragmentos pequeños, que se encuentran con más precisión, y devuelve el trozo más grande del documento al que pertenecen, una sección o el documento entero. Un nodo en Prepare Chunks corta tus documentos para la base vectorial (Piece Size 2000 y Chunk Size 400 por defecto); otro en Search los busca. Útil cuando el fragmento que se encuentra se queda corto para responder, por ejemplo una ficha de producto o un procedimiento.

Con fragmentos de 400 caracteres y trozos de 2000, la respuesta estuvo entre los cinco primeros resultados en el 93 % de las preguntas sobre documentos (83 % con la búsqueda normal), pero cada búsqueda devolvió 8.400 caracteres en vez de 3.100: la búsqueda normal con el mismo texto (13 resultados) encontró el 97 %. Su valor es que el agente lee secciones enteras en vez de fragmentos sueltos, no que encuentre más.

Este vídeo compara los fragmentos sueltos con la sección completa que devuelve Multi Vector Retriever, en una pregunta por un procedimiento.

Lo que ves en el vídeo:

  1. Un nodo Multi Vector Retriever en Prepare Chunks corta los documentos en fragmentos de 400 caracteres que recuerdan su sección de 2.000, y los guarda en Qdrant.
  2. Otro nodo en Search busca en esos fragmentos y devuelve la sección entera.
  3. A «¿Cómo se cambia la sonda NTC de una Jaltec Brío 2G, paso a paso?», la búsqueda normal devuelve trozos sueltos a los que les faltan pasos.
  4. La búsqueda con secciones devuelve el procedimiento completo, hasta la comprobación final.

Búsqueda en un grafo

Neo4j GraphRAG busca por significado o por significado y palabras en los nodos de un grafo, recorre las relaciones de cada resultado o escribe la consulta que responde a la pregunta. Es la única técnica que respondió bien las preguntas de recuento. Consulta GraphRAG con Neo4j.

La configuración recomendada

Para manuales, políticas y preguntas frecuentes, esta es la combinación que mejor funcionó:

  1. Ingesta. Contextual Text Splitter (Chunk Size entre 700 y 800, Chunk Overlap entre 100 y 150, un modelo rápido y barato) → Metadata Tagger solo si vas a filtrar → base vectorial (Qdrant, o Chroma DB o FAISS si no tienes servidor) con FastEmbed Embeddings (Local). Conserva en cada fragmento el tipo de documento, la marca y el periodo.
  2. Búsqueda. Base en Retriever con Number of Results 20 → Local Rerank con Results to Keep 5. Si tus usuarios preguntan mucho por códigos, pon delante un Ensemble Retriever con BM25 Retriever y la base, con Weights 0.5, 0.5.
  3. Respuesta. Conecta la salida Tool de Local Rerank a un Agent, con instrucciones que le pidan responder solo con lo que encuentra.
  4. Registros. Si además tienes incidencias, pedidos o tickets, añade al mismo agente una herramienta que los consulte: Neo4j GraphRAG en Text2Cypher o una consulta SQL.

Con fragmentos con contexto, búsqueda híbrida y Local Rerank, la respuesta fue el primer resultado en el 80 % de las preguntas sobre documentos y estuvo entre los cinco primeros en todas, frente al 60 % y el 83 % de la búsqueda básica. El coste: una llamada a un modelo por fragmento al preparar los documentos y unos 2 segundos de reordenado por pregunta.

Tienes este flujo montado paso a paso en Ejemplos paso a paso.

Cómo conseguir que el agente diga «no lo sé»

Un agente con una herramienta de búsqueda siempre recibe algo, aunque no tenga que ver con la pregunta. Para que no invente, combina dos cosas:

  1. Filtra lo que no tiene que ver, con cuidado. Con Minimum Relevance de Local Rerank en 0,01 se rechazaron 2 de las 4 preguntas sin respuesta y ninguna de las que sí la tenían, pero por muy poco: alguna respuesta buena sacó 0,011 y una pregunta sin respuesta, 0,12. Un valor más alto ya descarta respuestas buenas, así que pruébalo con tus propias preguntas. Un umbral de parecido entre vectores no lo consigue.
  2. Díselo en las instrucciones. Algunas preguntas sin respuesta se parecen mucho a tus documentos (un código de error que no existe en un modelo que sí existe) y solo las detecta el agente al leer los resultados. Añade al System Prompt del agente algo como:
Responde solo con la información que te devuelven tus herramientas.
Si no está, di que no tienes ese dato y no lo inventes.

Así responde el asistente del vídeo cuando le preguntan el precio de una máquina nueva: dice que no tiene ese dato en lugar de inventarlo.

Si quieres que esa comprobación la haga el propio componente, usa el RAG Agent: puntúa cada documento y, si ninguno sirve, responde en el idioma de la pregunta que no ha encontrado la información.