saltar al contenido
volver al mapa
técnica
etapa: retrieve
3 min de lectura

Retrieval

El retrieval es donde la búsqueda se vuelve respuesta: dense, sparse, híbrido y reranking deciden si el contexto que llega al LLM es útil o basura disfrazada de evidencia.

Cohere RerankBM25ColBERTTavily

Qué es

El retrieval es el paso que decide qué pasajes de la base se convierten en contexto para el LLM. En RAG, es la etapa donde se gana o se pierde la mayor parte de la calidad: un buen contexto se vuelve una buena respuesta, un contexto equivocado se vuelve una respuesta equivocada, incluso con un prompt perfecto y un modelo excelente. Un mal retrieval no tiene arreglo después.

Un sistema de retrieval tiene tres decisiones: qué algoritmo usar (denso, disperso, híbrido), cómo hacer rerank del resultado bruto y cómo fusionar listas provenientes de algoritmos distintos. Las tres decisiones dependen del tipo de pregunta y del tipo de corpus.

Dense, sparse e híbrido

La búsqueda densa usa embeddings: la pregunta se vuelve vector, el corpus se vuelve vector, la similitud es geométrica. Es buena para paráfrasis, preguntas conceptuales y términos no técnicos. Es débil para siglas raras, identificadores y términos literales que existen en el documento pero no en el vocabulario del modelo.

La búsqueda dispersa usa frecuencia de términos ( es el estándar de la práctica). Es buena para palabras exactas, nombres propios y siglas. Es débil para paráfrasis y consultas que mezclan términos. BM25 puntúa cada término por el TF (cuántas veces aparece en el documento) y por el IDF (qué tan raro es en el corpus), y normaliza por el tamaño del documento. El resultado es una lista ordenada por relevancia léxica.

La búsqueda híbrida corre las dos en paralelo y fusiona las listas. El método de fusión más común es RRF (Reciprocal Rank Fusion): cada lista asigna 1/(k + rank) a cada candidato, y los candidatos se reordenan por la suma. El resultado hereda lo mejor de las dos búsquedas.

Reranking

Después del top fusionado, todavía queda ruido. El reranker entra para reordenar el top-N con un modelo que mira la pregunta y el candidato juntos. Cohere Rerank, BGE Reranker y ColBERT hacen esto con un modelo de lenguaje más pequeño que puntúa cada par (pregunta, documento) con mejor calidad que la .

El costo es proporcional al número de candidatos reordenados, así que la lista de entrada suele ser de 50 a 200 ítems. El costo en latencia queda dentro del presupuesto porque el reranker es más pequeño y barato que el LLM final.

En la práctica

El ejemplo junta dense retrieval (Qdrant), BM25 (Pyserini) y un reranker Cross-Encoder en un único pipeline. La fusión es RRF, y el reranker recorta los 50 mejores a los 5 finales.

retrieval/pipeline.pypython
from typing import Iterable
from qdrant_client import QdrantClient
from pyserini.search.lucene import LuceneSearcher
from sentence_transformers import CrossEncoder

qdrant = QdrantClient(url="http://localhost:6333")
searcher = LuceneSearcher.from_prebuilt_index("manual_pt")
reranker = CrossEncoder("cross-encoder/mmarco-mMiniLMv2-L12-H384-v1")

def rrf(ranks: Iterable[list[str]], k: int = 60) -> list[tuple[str, float]]:
    scores: dict[str, float] = {}
    for r in ranks:
        for i, doc_id in enumerate(r):
            scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + i + 1)
    return sorted(scores.items(), key=lambda x: x[1], reverse=True)

def retrieve(query: str, embedding: list[float], top_k: int = 5):
    # 1. dense (Qdrant, top 50)
    dense_hits = qdrant.search(
        collection_name="chunks",
        query_vector=embedding,
        limit=50,
        with_payload=False,
    )
    dense_ids = [str(h.id) for h in dense_hits]

    # 2. sparse (BM25, top 50)
    bm25_hits = searcher.search(query, k=50)
    bm25_ids = [h.docid for h in bm25_hits]

    # 3. fusión RRF
    fused = rrf([dense_ids, bm25_ids])

    # 4. rerank de los 50 candidatos
    candidates = [(doc_id, lookup_text(doc_id)) for doc_id, _ in fused[:50]]
    pairs = [(query, text) for _, text in candidates]
    scores = reranker.predict(pairs)
    ranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)

    return [doc_id for (doc_id, _), _ in ranked[:top_k]]

Puntos fuertes

  • cobertura doble: el híbrido cubre tanto la paráfrasis (densa) como el término exacto (BM25), así que los dos puntos ciegos se mitigan
  • el rerank del top-N entrega un impulso: el reranker pequeño filtra lo que pasó, así que el LLM solo ve lo que realmente importa
  • costo amortizado: hacer rerank del top-50 sale barato, y el resto de la lista bruta ni siquiera se procesa

Limitaciones

  • complejidad operativa: tres subsistemas (vector, BM25, reranker) deben estar sanos a la vez; si uno falla, el clúster cae
  • la fusión es heurística: RRF no aprende una fusión óptima, y el k=60 por defecto no es universal; el ajuste es trabajo de producción
  • el reranker se vuelve un tema aparte: el reranker se actualiza por modelo, así que verificar si un modelo nuevo supera al anterior es una regresión obligatoria
BM25Función de ranking clásica de la búsqueda textual: puntúa cada documento con TF-IDF con saturación (los términos importantes pesan más hasta cierto tope) y normaliza por longitud. Es la búsqueda dispersa del retrieval híbrido y captura coincidencias exactas de términos (código de error, nombre de API) donde el embedding solo falla feo.ver en el glosario →Similitud de cosenoMedida de qué tan alineados están dos vectores en el espacio de embeddings: coseno del ángulo entre ellos, independiente de la magnitud. Para embeddings normalizados basta el producto interno y sigue siendo rápido, por eso se volvió la distancia estándar en casi toda base vectorial.ver en el glosario →

conexiones en el mapa

actualizado el 14/10/2026 · fuentes para profundizar · reportar un error

Estudia antes

Desbloquea

pon a prueba lo que entendiste

Cargando preguntas…