Scaling Retrieval-Based Language Models: El Paper que Redefine la Eficiencia en LLMs
BLOG POST 3 min lectura 25 de enero, 2025

Scaling Retrieval-Based Language Models: El Paper que Redefine la Eficiencia en LLMs

El paper «Scaling Retrieval-Based Language Models» presenta un paradigma revolucionario para escalar LLMs mediante retrieval, logrando performance de modelos 10x más grandes con fraction del costo computacional.

Contribuciones Técnicas Principales

Los autores demuestran que los modelos retrieval-based siguen leyes de escalado diferentes:


# Ley de escalado tradicional
loss_traditional = alpha * (N ** -beta)  # N = parámetros del modelo

# Nueva ley de escalado con retrieval
loss_retrieval = alpha * (N ** -beta) * (R ** -gamma)  # R = tamaño del datastore

# Donde gamma > beta, indicando mayor eficiencia del retrieval

Arquitectura ReLM (Retrieval-Enhanced Language Model)


class ReLM(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.language_model = TransformerLM(
            hidden_size=config.hidden_size,
            num_layers=config.num_layers,
            num_heads=config.num_heads
        )
        
        self.retriever = DenseRetriever(
            encoder=config.retrieval_encoder,
            index_type="HNSW",  # Hierarchical Navigable Small World
            dimension=768,
            similarity="inner_product"
        )
        
        self.fusion_layer = CrossAttentionFusion(
            lm_dim=config.hidden_size,
            retrieval_dim=768,
            num_heads=8
        )
        
    def forward(self, input_ids, attention_mask):
        # Retrieve relevant documents
        query_emb = self.get_query_embedding(input_ids)
        retrieved_docs = self.retriever.search(
            query_emb, 
            k=32,  # número de documentos
            threshold=0.7
        )
        
        # Fuse retrieved information
        lm_hidden = self.language_model(input_ids, attention_mask)
        enhanced_hidden = self.fusion_layer(
            lm_hidden, 
            retrieved_docs.embeddings,
            retrieved_docs.attention_mask
        )
        
        return self.lm_head(enhanced_hidden)

Innovaciones en Retrieval

1. Hierarchical Retrieval

  • Coarse retrieval: BM25 para filtrado inicial rápido
  • Fine retrieval: Dense embeddings para ranking preciso
  • Adaptive k-selection: Número dinámico de documentos según perplejidad

2. Datastore Construction


# Construcción eficiente del datastore
datastore = {
    "embeddings": np.memmap(
        "datastore.npy",
        dtype=np.float16,  # Reducción de memoria
        mode="r+",
        shape=(num_docs, embedding_dim)
    ),
    "metadata": {
        "doc_boundaries": doc_boundaries,
        "source_ids": source_ids,
        "timestamps": timestamps
    },
    "index": faiss.index_factory(
        embedding_dim,
        "IVF65536_HNSW32,PQ64",  # Inverted File + Product Quantization
        faiss.METRIC_INNER_PRODUCT
    )
}

Resultados Experimentales

Performance vs. Tamaño del Modelo

Modelo Parámetros Datastore Perplexity FLOPS
GPT-3 175B 175B 20.5 3.14e23
ReLM-7B 7B 2T tokens 19.8 8.2e21
ReLM-1.5B 1.5B 10T tokens 20.1 3.1e21

Scaling Laws Descubiertas

  • Compute-optimal retrieval: Ratio óptimo de 1:100 entre parámetros y datastore
  • Diminishing returns: Beneficio marginal decrece logarítmicamente con datastore size
  • Cross-domain transfer: Retrieval mejora generalización out-of-domain en 34%

Optimizaciones de Sistema

1. Streaming Retrieval


# Pipeline asíncrono para minimizar latencia
async def streaming_generation(prompt, max_tokens=100):
    async with retrieval_pipeline() as pipeline:
        # Prefetch inicial
        initial_docs = await pipeline.prefetch(prompt, k=64)
        
        tokens = []
        for i in range(max_tokens):
            # Generación y retrieval en paralelo
            next_token, next_query = await asyncio.gather(
                model.generate_next(tokens, initial_docs),
                pipeline.prepare_next_retrieval(tokens)
            )
            
            tokens.append(next_token)
            
            # Update retrieval cada 10 tokens
            if i % 10 == 0:
                initial_docs = await pipeline.retrieve(next_query)
                
    return tokens

2. Distributed Datastore

  • Sharding: Particionado por similarity hashing
  • Caching: LRU cache de 10GB para queries frecuentes
  • Compression: Product quantization reduce storage 32x

Implicaciones para la Industria

Este approach permite:

  • Modelos pequeños con performance de grandes: 7B params ≈ 175B tradicional
  • Actualización sin reentrenamiento: Solo actualizar datastore
  • Especialización por dominio: Datastores específicos por vertical
  • Reducción de costos 90%: Menor compute y memory requirements

Código y Reproducibilidad

Los autores proporcionan:

  • Implementación completa en JAX/Flax
  • Checkpoints pre-entrenados (1.5B, 7B, 13B)
  • Scripts de evaluación para 15 benchmarks
  • Datastore pre-construido de CommonCrawl (2T tokens)

El paper completo está disponible en arXiv:2507.07955, estableciendo un nuevo paradigma para el desarrollo eficiente de LLMs.