Lección 31 · 10 min · Gratis

Resumen de documentos largos con Map-Reduce

Copyright (c) Meta Platforms, Inc. y afiliados. Este software puede ser usado y distribuido según los términos del Acuerdo de Licencia de la Comunidad Llama.

Open In Colab

Este tutorial te muestra cómo construir una sólida canalización de resumen para documentos largos. Crearemos un "Asistente de Resumen Inteligente" que usa Llama 4 para resumir un documento que es demasiado extenso para ser procesado en una sola pasada.

Aunque modelos como Llama 4 tienen ventanas de contexto masivas, resumir textos extremadamente largos a veces puede hacer que los detalles se "pierdan en el medio". Para resolver esto, implementaremos el patrón Map-Reduce: primero, "mapearemos" una tarea de resumen sobre fragmentos más pequeños y coherentes del texto, y luego "reduciremos" esos resúmenes individuales en una visión general final de alta fidelidad.

Componente Elección Por qué
Modelo Llama-4-Maverick-17B-128E-Instruct-FP8 Un modelo potente ideal para resúmenes de alta calidad tanto en la etapa de fragmentos como en la de resumen final.
Patrón Resumen Map-Reduce Un patrón fundamental para procesar documentos largos. "Mapeamos" una función de resumen sobre cada fragmento, luego "reducimos" los resúmenes resultantes en uno final.
Infraestructura Llama API Proporciona acceso a los modelos Llama 4 usando el SDK llama_api_client.

Nota sobre los proveedores de inferencia: Este tutorial usa la Llama API con fines de demostración. Sin embargo, puedes ejecutar modelos Llama 4 con cualquier proveedor de inferencia preferido. Ejemplos comunes incluyen Amazon Bedrock y Together AI. La lógica central de este tutorial puede adaptarse a cualquiera de estos proveedores.

Qué aprenderás

  • Cómo implementar una canalización robusta para resumir documentos de cualquier longitud.
  • El patrón fundamental "Map-Reduce" para el procesamiento de documentos.
  • Técnicas para el "chunking semántico" para dividir un documento lógicamente mientras se preserva el contexto.
  • Cómo elaborar prompts efectivos y específicos para cada etapa para una canalización LLM de varios pasos.
  • Cómo encadenar llamadas a LLM para realizar tareas complejas y de varias etapas.

Instalar dependencias

Necesitarás dos bibliotecas para este proyecto: tiktoken para un conteo preciso de tokens, y la llama-api-client oficial.

!pip install --quiet tiktoken llama-api-client

Importaciones y configuración del cliente de la Llama API

Importa los módulos necesarios e inicializa el LlamaAPIClient. Esto requiere que una clave de la Llama API esté disponible como variable de entorno. Si no tienes una clave de la Llama API, por favor, obtén una en Meta Llama API.

Recuerda, usamos la Llama API para este tutorial, pero puedes adaptar esta sección para usar tu proveedor de inferencia preferido.

import os, sys, re
from typing import List
import tiktoken
from llama_api_client import LlamaAPIClient

# --- Llama client ---
API_KEY = os.getenv("LLAMA_API_KEY")
if not API_KEY:
    sys.exit("❌  Please set the LLAMA_API_KEY environment variable.")

client = LlamaAPIClient(api_key=API_KEY)

Paso 1: Obtener los datos

Este tutorial usa una versión en markdown del artículo de investigación de Meta, ASTRO: Teaching Language Models to Reason by Reflecting and Backtracking In-Context. El archivo, ASTRO-Teaching_Language_Models_to_Reason.md, está incluido en el subdirectorio data del repositorio, lo que facilita seguir el tutorial.

Estamos usando un archivo markdown para este tutorial porque preserva la estructura del documento con encabezados, lo cual es útil para el chunking semántico. Si estás trabajando con otros formatos como PDFs, puedes usar servicios de análisis como LlamaParse para convertirlos a markdown.

file_path = "data/ASTRO-Teaching_Language_Models_to_Reason.md"

try:
    with open(file_path, 'r', encoding='utf-8') as f:
        document_text = f.read()
except FileNotFoundError:
    raise FileNotFoundError(
        f"Error: The file was not found at {file_path}"
    )

if document_text:
    print(f"✅  Successfully loaded document: {len(document_text):,} characters.")
✅  Successfully loaded document: 142,921 characters.

Paso 2: La lógica del chunking

¿Por qué chunking?

Para documentos largos, incluso con una ventana de contexto grande, resumir en una sola pasada puede llevar a la degradación del contexto, donde el modelo puede subestimar los detalles del medio del texto.

Para asegurar que todas las partes del documento se procesen con igual enfoque, usamos un enfoque de map-reduce. Dividir el documento en fragmentos más pequeños y coherentes para un resumen individual garantiza un resultado final más detallado y de alta calidad.

¿Cómo hacer chunking?

Una estrategia de chunking efectiva es fundamental. Simplemente dividir el texto por un recuento fijo de tokens puede romper oraciones o separar ideas relacionadas. Un enfoque mejor es el chunking semántico. Nuestra estrategia tiene dos niveles:

  1. División basada en encabezados: Primero, el documento se divide en secciones grandes basándose en sus encabezados markdown (#, ##, ###). Esto preserva la estructura lógica del documento.
  2. Chunking basado en párrafos: Cada sección grande se divide luego en los fragmentos finales más pequeños. Este proceso respeta los límites de los párrafos y un límite de tokens especificado, asegurando que los fragmentos sean semánticamente coherentes y de tamaño apropiado para el LLM.

Nota sobre la generalización: La división basada en encabezados de este tutorial está optimizada para documentos markdown. Para otros formatos (como texto plano o PDFs), puedes generalizar este enfoque de división basada en encabezados identificando elementos estructurales similares. Por ejemplo, podrías dividir por títulos de capítulos, secciones numeradas o usar expresiones regulares para encontrar patrones personalizados que definan saltos lógicos en tu documento. El principio del chunking semántico multinivel sigue siendo el mismo.

Elegir el tamaño de chunk adecuado

Aunque nuestra estrategia de chunking prioriza los límites semánticos (encabezados y párrafos) sobre los recuentos fijos de tokens, aún necesitamos establecer un tamaño máximo para nuestros chunks. Esto asegura que incluso el chunk semántico más grande quepa cómodamente dentro de la ventana de contexto del modelo.

La constante CHUNK_SIZE_TOKENS sirve como este límite superior. Encontrar el valor correcto es una compensación:

  • Demasiado alto: El límite podría ser aún mayor que la ventana de contexto del modelo (una vez que se incluye el prompt), lo que provocaría que las llamadas a la API fallen.
  • Demasiado bajo: Esto podría forzar la lógica de chunking a dividir párrafos u otras unidades lógicas de forma demasiado agresiva, reduciendo la calidad de los resúmenes. También aumenta el número de llamadas a la API, lo que conlleva un mayor costo y latencia.

El límite de tokens 16000 en este tutorial es un tamaño conservador para modelos con grandes ventanas de contexto (normalmente 128k para modelos disponibles en la Llama API). Deja un amplio espacio para el prompt mientras asegura que cada chunk sea lo suficientemente grande como para proporcionar un contexto significativo para el resumen.

Nota sobre el procesamiento local: Todo el procesamiento hasta este punto, incluida la carga de datos y el chunking del texto, ocurre localmente. Todavía no hemos realizado ninguna llamada a la Llama API. El conteo de tokens se realiza con una biblioteca local para asegurar que nuestros chunks tengan el tamaño correcto para las llamadas a la API en los siguientes pasos.

# --- Constants & Configuration ---
ENCODING_MODEL = "o200k_base"
CHUNK_SIZE_TOKENS = 16000 # A practical chunk size

def count_tokens(text: str, encoding: tiktoken.Encoding) -> int:
    """Helper function to count tokens in a string."""
    return len(encoding.encode(text))

def chunk_document(
    markdown_text: str,
    chunk_size: int = CHUNK_SIZE_TOKENS,
    headers_to_split_on: List[str] = ["#", "##", "###"]
) -> List[str]:
    """
    Chunks a markdown document, preserving header context for each chunk.
    """
    # 1. Split the document by headers to get sections
    header_pattern = "|".join(f"^{h}\\s" for h in headers_to_split_on)
    sections = re.split(f"({header_pattern})", markdown_text, flags=re.MULTILINE)
    if sections and not sections[0].strip():
        sections.pop(0)

    if len(sections) > 1:
        sections = list(zip(sections[0::2], sections[1::2]))
    else:
        sections = []

    encoding = tiktoken.get_encoding(ENCODING_MODEL)
    final_chunks = []

    # 2. Process each section
    for header, content in sections:
        header_token_count = count_tokens(header, encoding)
        
        if header_token_count + count_tokens(content, encoding) <= chunk_size:
            final_chunks.append(header + content)
            continue

        # Split the content by paragraphs
        paragraphs = content.split('\n\n')
        current_chunk_paragraphs = []
        current_chunk_tokens = header_token_count

        for para in paragraphs:
            para_tokens = count_tokens(para, encoding)

            # If a paragraph is too large to fit with the header, it must be truncated.
            if header_token_count + para_tokens > chunk_size:
                available_tokens = chunk_size - header_token_count
                para_token_ids = encoding.encode(para)
                truncated_ids = para_token_ids[:available_tokens]
                para = encoding.decode(truncated_ids, errors='ignore')
                para_tokens = len(truncated_ids)
                print(f"Warning: Truncating a paragraph to {para_tokens} "
                      f"tokens to fit the chunk size.")

            # If the current chunk is not empty and the new paragraph doesn't fit,
            # finalize the current chunk before starting a new one.
            if (current_chunk_paragraphs and 
                (current_chunk_tokens + para_tokens > chunk_size)):
                final_chunks.append(header + "\n\n".join(current_chunk_paragraphs))
                current_chunk_paragraphs = []
                current_chunk_tokens = header_token_count

            current_chunk_paragraphs.append(para)
            current_chunk_tokens += para_tokens

        # Add the last remaining chunk
        if current_chunk_paragraphs:
            final_chunks.append(header + "\n\n".join(current_chunk_paragraphs))
            
    return final_chunks

# Now, let's chunk our document
chunks = chunk_document(document_text)

# --- Print Statistics and a Sample Chunk ---
if chunks:
    print(f"Total chunks created: {len(chunks)}")
    encoding = tiktoken.get_encoding(ENCODING_MODEL)
    token_counts = [count_tokens(chunk, encoding) for chunk in chunks]
    avg_tokens = sum(token_counts) / len(token_counts)
    print(f"Average token count per chunk: {avg_tokens:.2f}")
    print(f"Max token count in a chunk: {max(token_counts)}")
    print(f"Min token count in a chunk: {min(token_counts)}")
    print("-" * 50)
    print("Top 5 Chunks:")
    for i, chunk in enumerate(chunks[:5]):
        print(f"Chunk {i}:")
        print(chunk)
        print("-" * 50)
Total chunks created: 54
Average token count per chunk: 661.94
Max token count in a chunk: 6357
Min token count in a chunk: 3
--------------------------------------------------
Top 5 Chunks:
Chunk 0:
# ASTRO: Teaching Language Models to Reason by Reflecting and Backtracking In-Context

Joongwon Kim<sup>1,2</sup>, Anirudh Goyal<sup>1</sup>, Liang Tan<sup>1</sup>, Hannaneh Hajishirzi<sup>2</sup>, Srini Iyer<sup>1</sup>, Tianlu Wang<sup>1</sup>

<sup>1</sup>AI at Meta, <sup>2</sup>University of Washington

We introduce Astro, the "Autoregressive Search-Taught Reasoner", a framework for training language models to reason like search algorithms, explicitly leveraging self-reflection, backtracking, and exploration in their outputs. Recently, training large language models (LLMs) via reinforcement learning (RL) has led to the advent of reasoning models with greatly enhanced reasoning capabilities. Open-source replications of reasoning models, while successful, build upon models that already exhibit strong reasoning capabilities along with search behavior observed even before RL. As a result, it is yet unclear how to boost the reasoning capabilities of other non-reasoner models including Llama 3. Astro teaches such models to internalize structured search behavior through a synthetic dataset derived from Monte Carlo Tree Search (MCTS) over mathematical problem-solving trajectories. By converting search traces into natural language chain-of-thoughts that capture both successes and recoveries from failure, Astro bootstraps models with a rich prior for exploration during RL. We finetune our models on these search-derived traces and further improve performance via RL with verifiable rewards. We apply Astro to the Llama 3 family of models and achieve absolute performance gains of 16.0% on MATH-500, 26.9% on AMC 2023, and 20.0% on AIME 2024, especially improving upon challenging problems that require iterative correction. Our results demonstrate that search-inspired training offers a principled way to instill robust reasoning capabilities into open LLMs.

Date: June 23, 2025
Correspondence: Joongwon Kim at [email protected]

| **stepwise solutions** ## Step 1: Define the problem and identify what we need to find. We need to find the time it takes for Aya to complete her walk and stop at the coffee shop when walking at a speed of $s + \frac{1}{2}$ kilometers per hour, including the time $t$ spent in the coffee shop. ## Step 2: Set up the equations based on the information given. Let's denote the total time for the walk and coffee shop at speed $s$ as 4 hours or 240 minutes, and at speed $s+2$ as 2 hours and 24 minutes, or 144 minutes ... The final answer is \boxed{398}. Llama-3.1-70B-Instruct | **long CoT solutions** Procedure Cloning SFT RL ASTRO Let's begin by finding the time that it takes for Aya to complete her walk and stop at the coffee shop ... 
… (salida recortada)

Paso 3: La etapa "map" - resumiendo cada chunk

Con el documento dividido en chunks manejables y semánticamente coherentes, podemos comenzar la etapa "Map". Esto significa que aplicamos la misma operación —en este caso, el resumen— a cada chunk de forma independiente.

Ingeniería de prompts

La calidad de los resúmenes depende en gran medida de la calidad de los prompts. Para esta etapa, el prompt debe instruir al modelo para que cree un resumen de una pequeña parte de un documento más grande. Es crucial decirle al modelo que se enfoque solo en el texto proporcionado y que no añada información externa.

LLM_MODEL = "Llama-4-Maverick-17B-128E-Instruct-FP8"
DOC_TITLE = ("ASTRO: Teaching Language Models to Reason by Reflecting and "
             "Backtracking In-Context")

MAP_PROMPT = """
Your role is to create a concise, factual summary of a text chunk from the 
research paper titled "{document_title}".
- Extract only key facts, figures, and statements from the chunk text itself.
- Omit any conversational introductions or conclusions. Do not explain what you 
  are doing.
- If a chunk contains no substantive information (e.g., only headers, formatting, 
  or boilerplate), output the exact phrase: "No substantive information."

**Text Chunk:**
{chunk_text}
"""

def map_summarize_chunk(chunk_text: str, document_title: str) -> str:
    """
    Summarizes a single chunk of text using the 'map' prompt.
    """
    try:
        resp = client.chat.completions.create(
            model=LLM_MODEL,
            messages=[
                {"role": "user", "content": MAP_PROMPT.format(
                    document_title=document_title, chunk_text=chunk_text)},
            ],
            temperature=0.1, # Low temperature for deterministic summaries
        )
        return resp.completion_message.content.text
    except Exception as e:
        print(f"    Error summarizing chunk: {e}")
        return "" # Return empty string on failure

# Let's test the map function on the first few chunks
if chunks:
    for i, chunk in enumerate(chunks[:5]):
        summary = map_summarize_chunk(chunk, DOC_TITLE)
        print(f"Summary of chunk {i}:")
        print(summary)
        print("-" * 50)
Summary of chunk 0:
- ASTRO is a framework for training language models to reason like search algorithms.
- ASTRO leverages self-reflection, backtracking, and exploration in language model outputs.
- ASTRO uses a synthetic dataset derived from Monte Carlo Tree Search (MCTS) over mathematical problem-solving trajectories.
- The framework finetunes models on search-derived traces and improves performance via reinforcement learning (RL) with verifiable rewards.
- ASTRO is applied to the Llama 3 family of models.
- Absolute performance gains achieved: 16.0% on MATH-500, 26.9% on AMC 2023, and 20.0% on AIME 2024.
- Llama-3.1-70B-ASTRO-RL achieves 81.8% on MATH-500, 64.4% on AMC 2023, and 30.0% on AIME 2024 (pass@1).
--------------------------------------------------
Summary of chunk 1:
- ASTRO is a framework that infuses search-like behavior into language models to improve their reasoning capabilities.
- ASTRO operates in three stages: search trajectory generation, supervised fine-tuning, and reinforcement learning.
- Search trajectory generation uses Monte Carlo Tree Search (MCTS) to explore the solution space of math problems and builds search trees with diverse reasoning traces.
- About 36K high-quality chain-of-thought (CoT) solutions are sampled across three open-source math datasets.
- Supervised fine-tuning (SFT) is performed on the search-integrated solutions to infuse autoregressive search behavior into the models.
- The SFT checkpoint based on llama-3.1-70b-instruct achieves 69.6% on MATH-500, 55.0% on AMC 2023, and 13.3% on AIME 2024 after fine-tuning for one epoch.
- Reinforcement learning (RL) is performed using a modified form of Group Relative Policy Optimization (GRPO) to further improve the models' reasoning capabilities.
- After RL, the policy based on llama-3.1-70b-instruct achieves 81.8% in MATH-500, 64.4% in AMC 2023, and 30.0% in AIME 2024 (pass@1).
--------------------------------------------------
Summary of chunk 2:
* Astro generates a dataset of search traces via procedure cloning.
* Search trees are obtained using Monte Carlo Tree Search (MCTS) with verifier-based rewards.
* Search trees are linearized into sequences of nodes exploring various states.
* Node sequences are translated into chains-of-thought integrating self-reflection and backtracking in natural language.
* The resulting dataset encodes self-reflection and backtracking priors for training language models.
* The dataset is used for supervised fine-tuning and reinforcement learning to solve math problems.
--------------------------------------------------
Summary of chunk 3:
* The data generation setup is a Markov Decision Process (MDP).
* The language model functions as the policy ΠLM and explores the solution space to the input x.
* Each state St represents a combination of the input prompt and the sequence of steps generated by the policy.
* The goal is to teach a language model to predict a sequence of states (S0 · · · Send) in response to x.
* Training data for Astro is generated in three main stages: 
  1. Generating a search tree T using Monte Carlo Tree Search (MCTS).
  2. Linearizing T into a sequence of nodes L.
  3. Translating L into a chain-of-thought solution y that integrates self-reflection and backtracking in natural language.
--------------------------------------------------
Summary of chunk 4:
- Monte Carlo Tree Search (MCTS) is used with language model policy ΠLM to obtain a search tree with diverse solution traces.
- MCTS involves three stages: selection, expansion, and backpropagation.
- Selection uses Predictor+Upper Confidence bounds applied to Trees (PUCT) to balance exploration and exploitation.
- The selection formula is: $$S^*_{t+1} = \underset{(S_{t+1}=S_t \rightarrow a_i)}{\text{argmax}} \left[Q(S_t, a_i) + c_{\text{puct}} \cdot \Pi_{\text{LM}}(a_i|S_t)\sqrt{\frac{N(S_t)}{1 + N(S_t, a_i)}}\right]$$
- Expansion involves sampling k actions, scoring full solutions using verifier V, and averaging scores across M rollouts.
- The reward score formula is: $$R(S_{t+1}) = \frac{1}{M} \sum_{j\in[1...M]} V(\Pi_{\text{LM},j}(S_{t+1}))$$
- Backpropagation updates Q-values and visit counts using equations: 
  $$N(s_t) = N(s_t) + 1$$
  $$Q(S_t, a) = \frac{\sum_{i=1}^K Q(S_{t+1}, a_i) \cdot N(S_{t+1}, a_i) + R(S_{t+1})}{\sum_{i=1}^K N(S_{t+1}, a_i) + 1}$$
- The policy ΠLM used is llama-3.3-70b-instruct.
- Parameters used are: k = 8, M = 16, cpuct = 1.0, 32 iterations, and maximum tree depth of 50.
--------------------------------------------------

Paso 4: La etapa "reduce": creando el resumen final

Con la etapa "map" completa, ahora tenemos una lista de resúmenes individuales para cada fragmento. La etapa "reduce" combina estos en un único resumen ejecutivo coherente.

Ingeniería de prompts para la síntesis

El prompt para esta etapa es diferente. Ya no solo estamos resumiendo; estamos sintetizando. El prompt instruye al modelo para que entrelace los puntos individuales de los resúmenes de los fragmentos en una narrativa fluida y bien escrita.

REDUCE_PROMPT = """
You are a research assistant tasked with creating an executive summary.
You have been given a series of concise summaries from different sections of a 
research paper.
Your goal is to synthesize these individual summaries into a single, well-written, 
and coherent executive summary.
The final summary should read like a standalone document, flowing logically from 
one topic to the next.

**Summaries of Report Sections:**
{chunk_summaries}
"""

MAX_CONTEXT_WINDOW = 100000

def reduce_create_final_summary(chunk_summaries: List[str]) -> str:
    """
    Combines chunk summaries into a final executive summary using the 'reduce' prompt.
    """
    summaries_text = "\\n\\n---\\n\\n".join(chunk_summaries)
    
    encoding = tiktoken.get_encoding(ENCODING_MODEL)
    if count_tokens(summaries_text, encoding) > MAX_CONTEXT_WINDOW:
        # For this tutorial, we'll truncate to fit. A more advanced implementation
        # might run another map-reduce pass (recursive reduction).
        print("Warning: Combined summaries are too large; will be truncated for "
              "final summary.")
        tokens = encoding.encode(summaries_text)
        truncated_tokens = tokens[:MAX_CONTEXT_WINDOW]
        summaries_text = encoding.decode(truncated_tokens, errors='ignore')

    try:
        resp = client.chat.completions.create(
            model=LLM_MODEL,
            messages=[
                {"role": "user", "content": REDUCE_PROMPT.format(
                    chunk_summaries=summaries_text)},
            ],
            temperature=0.3, # Slightly higher for more fluid, natural writing
        )
        return resp.completion_message.content.text
    except Exception as e:
        print(f"    Error creating final summary: {e}")
        return ""

Paso 5: Uniéndolo todo

El siguiente código ejecuta la canalización completa:

  1. Map: Itera a través de un subconjunto de nuestros fragmentos y genera un resumen para cada uno.
  2. Reduce: Toma todos los resúmenes de fragmentos generados y los sintetiza en nuestro resumen ejecutivo final.

Para mantener este tutorial rápido e interactivo, solo procesaremos los primeros 25 fragmentos. En un escenario de producción, procesarías todos los fragmentos.

# For this demonstration, we'll process a subset of chunks.
# In a real application, you would process all of them.
CHUNKS_TO_PROCESS = 25
chunks_to_summarize = chunks[:CHUNKS_TO_PROCESS]

print(f"--- MAP: Summarizing {len(chunks_to_summarize)} individual chunks ---")
chunk_summaries = [map_summarize_chunk(chunk, DOC_TITLE) 
                   for chunk in chunks_to_summarize]
chunk_summaries = [summary for summary in chunk_summaries 
                   if summary.strip()]  # Filter out errors
print(f"\\nSuccessfully summarized {len(chunk_summaries)} chunks.")

# --- Calculate compression rate ---
encoding = tiktoken.get_encoding(ENCODING_MODEL)
original_tokens = sum(count_tokens(chunk, encoding) 
                      for chunk in chunks_to_summarize)
summarized_tokens = sum(count_tokens(summary, encoding) 
                        for summary in chunk_summaries)
if original_tokens > 0:
    compression_rate = (1 - (summarized_tokens / original_tokens)) * 100
    print(f"\\nOriginal token count: {original_tokens:,}")
    print(f"Summarized token count: {summarized_tokens:,}")
    print(f"Compression rate: {compression_rate:.2f}%")

print("\\n--- REDUCE: Creating final summary ---")
final_summary = reduce_create_final_summary(chunk_summaries)

# --- Display Final Result ---
print("\\n" + "=" * 50)
print("           FINAL EXECUTIVE SUMMARY")
print("=" * 50)
print(final_summary)
--- MAP: Summarizing 25 individual chunks ---
\nSuccessfully summarized 25 chunks.
\nOriginal token count: 19,127
Summarized token count: 4,163
Compression rate: 78.23%
\n--- REDUCE: Creating final summary ---
\n==================================================
           FINAL EXECUTIVE SUMMARY
==================================================
Here is a synthesized executive summary based on the provided summaries:

**Executive Summary**

This report introduces ASTRO, a novel framework designed to enhance the reasoning capabilities of language models by infusing search-like behavior into their outputs. ASTRO operates in three stages: data generation using Monte Carlo Tree Search (MCTS), supervised fine-tuning (SFT), and reinforcement learning (RL). The framework leverages self-reflection, backtracking, and exploration in language model outputs to improve their performance on mathematical problem-solving tasks.

The data generation stage utilizes MCTS to build search trees, which are then linearized into node sequences and translated into long Chain-of-Thoughts (CoTs) that integrate self-reflection and backtracking in natural language. The resulting dataset is used for SFT and RL to fine-tune the Llama 3 family of models.

The ASTRO-trained models demonstrate significant performance gains on various mathematical benchmarks, including MATH-500, AMC 2023, and AIME 2024. Specifically, Llama-3.1-70B-ASTRO-RL achieves 81.8% on MATH-500, 64.4% on AMC 2023, and 30.0% on AIME 2024 (pass@1). The models also exhibit improved self-reflection and backtracking capabilities, generating longer CoTs and achieving better training efficacy and upper bound during RL.

The report highlights the importance of search priors in improving the model's reasoning capabilities and demonstrates that ASTRO-trained models outperform those trained without explicit search priors across all benchmarks. The results suggest that ASTRO is a promising framework for enhancing the mathematical reasoning abilities of language models.

Overall, this research contributes to the development of more advanced language models that can reason like search algorithms, with potential applications in various domains that require complex problem-solving capabilities.

Mejora futura: Manejo de documentos extremadamente largos con reducción recursiva

Si estás resumiendo un libro entero, el texto combinado de tus resúmenes de fragmentos podría ser aún demasiado largo para la ventana de contexto del modelo. La solución es la reducción recursiva.

Ejecutas el mismo proceso de map-reduce de nuevo sobre los propios resúmenes de fragmentos:

  1. Genera 500 resúmenes de fragmentos del documento original.
  2. Agrupa estos 500 resúmenes en lotes de 50.
  3. Ejecuta tu función reduce_create_final_summary en cada lote, produciendo 10 "súper resúmenes".
  4. Finalmente, ejecuta la función de reducción una última vez en los 10 "súper resúmenes" para obtener tu resumen ejecutivo final.

Este enfoque te permite escalar esta técnica de resumen a documentos de prácticamente cualquier longitud.

Próximos pasos y rutas de actualización

Este tutorial proporciona una base sólida para una potente canalización de resumen. Puedes extenderla de varias maneras para una aplicación de nivel de producción.

Necesidad Dónde buscar
Chunking más avanzado Para una división de documentos más robusta, explora bibliotecas como LangChain o LlamaIndex, que ofrecen "Recursive Character Text Splitters" que pueden manejar documentos y código complejos. Estos pueden dividir basándose en la sintaxis del código, la estructura de markdown y más.
Patrones alternativos El patrón "Map-Reduce" no es la única opción. Aprende sobre el patrón "Refine", donde el modelo construye y refina iterativamente un resumen procesando un fragmento a la vez. Esto puede ser mejor para crear una narrativa única y altamente coherente.
Preguntas y respuestas Si tu objetivo es hacer preguntas a un documento largo en lugar de resumirlo, el mejor enfoque es la Generación Aumentada por Recuperación (RAG). Esto implica almacenar fragmentos en una base de datos vectorial y recuperar solo los más relevantes para responder a la pregunta de un usuario. Consulta nuestra receta de RAG con chunking contextual.
Lección del curso «Llama Cookbook (use cases)» de Meta, publicado con licencia MIT. Traducción y adaptación al español de IA con Clase. IA con Clase no está afiliado a Meta. Ver el original · Licencia
Esta lección es gratuita. El resto del curso se abre con la Membresía de IA con Clase, que incluye todos los cursos del catálogo. Ver precios