Saltar al contenido
Volver a la lista de artículos
AI/AGI14分

Mejorando la calidad de recuperación en RAG 2026: búsqueda híbrida, rerankers, HyDE y late chunking

Raising RAG Retrieval Quality in 2026: Hybrid, Rerankers, HyDE, and Late Chunking

石川 大地AI Solutions Architect
2026-04-2314分
RAGRetrievalRerankerHyDEChunkingEvaluation

El retrieval define el techo de calidad de RAG

En 2026, es raro el caso de un proyecto RAG donde "cambiar el modelo generativo de GPT-4 a Claude Opus 4.7 lo hizo de repente más inteligente". La mayoría de los problemas se dan porque el retrieval no está recuperando la información necesaria o porque está recuperando ruido que confunde al LLM. Al revisar los proyectos RAG que KGA ha acompañado durante los últimos 18 meses, el puntaje de experiencia de usuario mejoró entre 30 y 60% solo con mejorar el retrieval, mientras que el cambio de modelo de LLM promedio solo un 8%.

Este artículo organiza las mejores prácticas de retrieval para RAG en 2026 en cinco capas: (1) búsqueda híbrida, (2) reranker, (3) reescritura de consultas, (4) estrategia de chunking y (5) métricas de evaluación.

Capa 1: Hybrid Search (BM25 + Dense)

La búsqueda dense pura falla frecuentemente con números de modelo ("ZX-450B"), siglas ("TLS1.3"), nombres propios y condiciones numéricas específicas. BM25, por el contrario, tiene dificultades con las reformulaciones semánticas. Fusionarlos con Reciprocal Rank Fusion (RRF) se convirtió en el estándar del sector.

RRF es muy simple: transforma el ranking de cada resultado de búsqueda a `1 / (k + rank)` y los suma (k=60 por defecto). Dado que no se preocupa por las diferencias de escala de puntuación, funciona de forma universal para combinar distintos modelos.

```python from collections import defaultdict

def rrf_fusion(ranked_lists: list[list[str]], k: int = 60) -> list[tuple[str, float]]: scores = defaultdict(float) for results in ranked_lists: for rank, doc_id in enumerate(results, start=1): scores[doc_id] += 1.0 / (k + rank) return sorted(scores.items(), key=lambda x: -x[1])

bm25_top = bm25_index.search(query, k=50) dense_top = vector_db.search(query_embed, k=50) fused = rrf_fusion([bm25_top, dense_top])[:20] ```

En el proyecto de búsqueda jurídica de KGA, el nDCG@10 subió de 0,52 con BM25 solo y 0,61 con dense solo, a 0,73 con el híbrido RRF. Es sencillo pero poderoso.

Capa 2: Reranker (Cohere Rerank-3, Voyage Rerank-2)

Después de obtener los top 50-200 con búsqueda híbrida, el diseño en dos etapas que puntúa con precisión mediante un reranker de tipo cross-encoder es el estándar de 2026. La búsqueda dense es una arquitectura bi-encoder que vectoriza la consulta y el documento de forma independiente, perdiendo la interacción entre consulta y documento. El reranker pasa ambos simultáneamente por un Transformer y produce la relevancia real.

  • Cohere Rerank-3 (lanzado en 09/2025): soporte para 100 idiomas, 128k de contexto, $2/1k queries
  • Voyage Rerank-2: 32k de contexto, líder en MTEB Reranking, $0,5/1k queries
  • Jina Reranker v2: opción más cercana al OSS; el rendimiento en japonés cede un paso frente a Cohere
  • BGE-Reranker-v2-m3: OSS con licencia MIT, primera opción para operación self-hosted

```python import cohere

co = cohere.Client() results = co.rerank( model="rerank-3", query="requisitos de transferencia transfronteriza en la ley de protección de datos", documents=[d.text for d in top50], top_n=10, ) reranked = [top50[r.index] for r in results.results] ```

El efecto del reranker es dramático; el promedio en KGA muestra que el nDCG@10 salta de 0,65 a alrededor de 0,82. Sin embargo, el reranker añade +200-400ms de latencia en top 50, por lo que en la UX de búsqueda hace falta diseñar para asincronía o para respuesta rápida solo con la primera etapa.

Capa 3: reescritura de consultas (HyDE, Query2Doc, Multi-Query)

Las consultas del usuario suelen ser cortas y ambiguas ("rescisión de contrato", "uso de memoria"). La técnica de expandirlas con un LLM antes de buscar se incorporó al diseño de retrieval de 2026.

  • HyDE (Hypothetical Document Embeddings): se le pide al LLM que escriba un documento de respuesta hipotético y se usa su embedding como clave de búsqueda
  • Query2Doc: se combina la consulta con el pseudodocumento para obtener el embedding (variante de HyDE, más estable en muchos casos)
  • Multi-Query: se le pide al LLM que genere 3-5 expresiones alternativas con la misma intención, se buscan en paralelo y se fusionan con RRF

```python def hyde_search(query: str, vector_db, llm): hypothetical = llm.generate( f"Escribe una respuesta ficticia de 3 oraciones para la siguiente pregunta: {query}" ) combined = query + " " + hypothetical # Se convierte en Query2Doc embed = embedding_model.encode(combined) return vector_db.search(embed, k=50) ```

Multi-Query tiene la mejor relación costo-beneficio; en el RAG de preguntas frecuentes internas de KGA, el Recall@20 mejoró un 12% frente a la búsqueda con consulta única. El costo es una llamada adicional al LLM por consulta, pero con Claude Haiku o GPT-4.1-mini es menos de 0,1 yenes.

Capa 4: estrategia de chunking

Las implementaciones RAG que operan solo con "dividir en N caracteres" son anticuadas en 2026. La estrategia de chunking determina directamente la calidad del retrieval.

  • Fixed-size: la división clásica por N caracteres. Solapamiento del 10-20%
  • Recursive Character Splitting: divide recursivamente en el orden párrafo → oración → palabra. El comportamiento por defecto del `RecursiveCharacterTextSplitter` de LangChain
  • Semantic Chunking: hace embedding de oraciones consecutivas y divide en los puntos donde la similitud coseno cae bruscamente. Crea chunks semánticamente coherentes
  • Late Chunking (Jina 2024/2025): pasa primero el texto completo por el modelo de embedding, obtiene embeddings por token y luego los promedia para construir el chunk. Como el chunk retiene el contexto circundante, no se pierde la información de pronombres y correferencias
  • Hierarchical / Parent-Child: busca con chunks pequeños y pasa el chunk padre a la generación. Equilibra precisión y cantidad de contexto

Ejemplo de implementación de Late Chunking:

```python from transformers import AutoModel, AutoTokenizer import torch

model = AutoModel.from_pretrained("jinaai/jina-embeddings-v3", trust_remote_code=True) tokenizer = AutoTokenizer.from_pretrained("jinaai/jina-embeddings-v3")

def late_chunking(long_text: str, chunk_boundaries: list[tuple[int, int]]): inputs = tokenizer(long_text, return_tensors="pt", truncation=True, max_length=8192) with torch.no_grad(): token_embeds = model(**inputs).last_hidden_state[0] chunk_embeds = [] for start, end in chunk_boundaries: chunk_embeds.append(token_embeds[start:end].mean(dim=0)) return torch.stack(chunk_embeds) ```

Tras implementar Late Chunking en el RAG de contratos de KGA, el Recall@10 mejoró de 71% a 88% en documentos con muchas referencias cruzadas como "lo establecido en el artículo 3".

Capa 5: métricas de evaluación y evaluación offline

El retrieval no se puede evaluar con "funcionó". Las métricas cuantitativas y los tests de regresión son imprescindibles.

  • Recall@k: proporción de documentos correctos que aparecen entre los primeros k resultados. El indicador más importante porque define el techo del RAG
  • nDCG@10 (Normalized Discounted Cumulative Gain): tiene en cuenta también la calidad del ranking. El estándar de facto en búsqueda comercial
  • MRR (Mean Reciprocal Rank): promedio del recíproco del ranking hasta el primer resultado correcto. Se acerca a la experiencia del usuario
  • Hit Rate@k: binario simple de si el resultado correcto aparece entre los primeros k

El conjunto de evaluación debe tener un mínimo de 100 consultas, idealmente 500. Se mantiene en CSV como pares de consulta e ID de documento correcto, y se ejecutan tests de regresión en CI.

```python import numpy as np

def ndcg_at_k(ranked_ids: list[str], relevance: dict[str, int], k: int = 10) -> float: gains = [relevance.get(doc_id, 0) for doc_id in ranked_ids[:k]] dcg = sum((2 g - 1) / np.log2(idx + 2) for idx, g in enumerate(gains)) ideal_gains = sorted(relevance.values(), reverse=True)[:k] idcg = sum((2 g - 1) / np.log2(idx + 2) for idx, g in enumerate(ideal_gains)) return dcg / idcg if idcg > 0 else 0.0 ```

Frameworks como el `RetrieverEvaluator` de LlamaIndex, RAGAS y Trulens estandarizan estos cálculos, así que en lugar de implementarlos desde cero, la práctica estándar de 2026 es incorporar primero RAGAS.

Configuración de referencia para producción

La configuración estándar de RAG en producción que KGA propone en 2026 es la siguiente:

  • Ingest: documento → Late Chunking (Jina v3) → almacenamiento parent/child
  • Index: almacenamiento de dense y sparse en pgvector o Qdrant
  • Query: Multi-Query (el LLM genera 3 variaciones)
  • Primera etapa: híbrido BM25 + Dense → fusión RRF para top 100
  • Segunda etapa: Cohere Rerank-3 comprime a top 10
  • Generación: se pasan los top 10 a Claude Opus 4.7 para la respuesta final
  • Evaluación: se ejecuta semanalmente en CI un test de regresión con 500 consultas; caídas por debajo de umbrales de nDCG@10, MRR y Recall@20 bloquean el build

Implementar esta configuración con rigor produce la experiencia real de que "el RAG se vuelve más inteligente sin cambiar el LLM". El retrieval es el corazón de RAG, y en 2026 es la capa que merece la prioridad de inversión en los proyectos.

Resolvamos juntos sus desafíos técnicos.

KGA IT Solutions reúne equipos especializados en IA, nube y DevOps para entregar la solución ideal a sus retos.

Contáctanos