0Pricing
AI Prompt Engineering · Lección

Patrón de resumen Map-Reduce

Resuma cada fragmento de forma independiente y después sintetice los resúmenes.

Patrón de resumen Map-Reduce es una lección gratuita de AI Prompt Engineering en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Prompt Engineering, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Prompt Engineering incluye 4 lecciones en total.

El patrón Map-Reduce

Cuando un documento supera la ventana de contexto del LLM, no puede pasarlo todo de una vez. El patrón map-reduce resuelve este problema:

  • Map: resumir cada fragmento de forma independiente
  • Reduce: sintetizar todos los resúmenes de los fragmentos en un único resumen final

Esto refleja el MapReduce clásico de los sistemas distribuidos: la misma lógica de divide y vencerás aplicada a tareas lingüísticas.

Paso 1: la fase map

En la fase map, cada fragmento se envía al LLM con un prompt de resumido. El modelo devuelve un resumen breve únicamente de ese fragmento. Estos resúmenes se recopilan en una lista.

Cada resumen debe ser mucho más breve que el fragmento original: normalmente, entre el 10 y el 20 % de la longitud original. Esta compresión es lo que hace viable el paso reduce.

import openai

client = openai.OpenAI(api_key='sk-...')

def summarize_chunk(chunk, model='gpt-4o'):
    resp = client.chat.completions.create(
        model=model,
        messages=[
            {'role': 'system', 'content': 'Summarize the following text concisely in 3-5 sentences.'},
            {'role': 'user', 'content': chunk}
        ]
    )
    return resp.choices[0].message.content

def map_phase(chunks):
    return [summarize_chunk(c) for c in chunks]

Paso 2: la fase reduce

En la fase reduce, todos los resúmenes de los fragmentos se concatenan y se envían al LLM con un prompt de síntesis. El modelo produce un único resumen final coherente.

Si los resúmenes de los fragmentos siguen siendo demasiado largos para caber en una sola ventana de contexto, aplique reduce de forma recursiva: resuma primero grupos de resúmenes y, después, sintetice esos resultados.

def reduce_phase(chunk_summaries, model='gpt-4o'):
    combined = '\n\n'.join(
        f'Section {i+1}:\n{s}'
        for i, s in enumerate(chunk_summaries)
    )
    resp = client.chat.completions.create(
        model=model,
        messages=[
            {'role': 'system', 'content': 'You are given summaries of consecutive sections of a document. Write a single coherent summary of the entire document.'},
            {'role': 'user', 'content': combined}
        ]
    )
    return resp.choices[0].message.content

Integración: API sin procesar

A continuación se muestra la canalización completa de map-reduce mediante llamadas directas a la API de OpenAI, sin necesidad de ningún framework. Esto le proporciona control total sobre los prompts y los parámetros de cada fase.

def map_reduce_summarize(document, chunk_size=1000):
    chunks = fixed_chunk(document, max_tokens=chunk_size)
    print(f'Chunks: {len(chunks)}')

    chunk_summaries = map_phase(chunks)
    print(f'Map phase complete. Summaries: {len(chunk_summaries)}')

    final_summary = reduce_phase(chunk_summaries)
    return final_summary

with open('long_report.txt') as f:
    doc = f.read()

result = map_reduce_summarize(doc)
print(result)

LangChain MapReduceDocumentsChain

LangChain proporciona una MapReduceDocumentsChain lista para usar que gestiona la segmentación, las llamadas map en paralelo y el paso reduce. Es práctica, pero menos flexible que las llamadas directas a la API.

from langchain_openai import ChatOpenAI
from langchain.chains.summarize import load_summarize_chain
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.docstore.document import Document

llm = ChatOpenAI(model='gpt-4o', openai_api_key='sk-...')
splitter = RecursiveCharacterTextSplitter(chunk_size=3000, chunk_overlap=200)

with open('long_report.txt') as f:
    text = f.read()

docs = splitter.create_documents([text])
chain = load_summarize_chain(llm, chain_type='map_reduce')
result = chain.invoke(docs)
print(result['output_text'])

Paralelización de la fase map

El resumen de cada fragmento es independiente, por lo que la fase map se puede paralelizar. Mediante ThreadPoolExecutor de Python, todas las llamadas a la API para los fragmentos se envían de forma simultánea, lo que reduce drásticamente el tiempo real de ejecución.

from concurrent.futures import ThreadPoolExecutor, as_completed

def map_phase_parallel(chunks, max_workers=10):
    summaries = [None] * len(chunks)
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = {
            executor.submit(summarize_chunk, chunk): i
            for i, chunk in enumerate(chunks)
        }
        for future in as_completed(futures):
            idx = futures[future]
            summaries[idx] = future.result()
    return summaries

Reduce recursivo

Cuando un documento es muy largo, los propios resúmenes de los fragmentos pueden superar la ventana de contexto. Aplique reduce de forma recursiva: agrupe los resúmenes en lotes, aplique reduce a cada lote y, después, aplique reduce a los resúmenes de los lotes.

def recursive_reduce(summaries, batch_size=10):
    while len(summaries) > 1:
        batches = [
            summaries[i:i + batch_size]
            for i in range(0, len(summaries), batch_size)
        ]
        summaries = [reduce_phase(batch) for batch in batches]
        print(f'Reduced to {len(summaries)} summaries')
    return summaries[0]

Conservación de los detalles importantes

Un fallo común del map-reduce ingenuo es que se pierdan detalles importantes durante la compresión. Mitigaciones:

  • Indique en el prompt del paso map que conserve nombres, números y fechas
  • Pida al paso reduce que compruebe si hay contradicciones entre las secciones
  • Utilice un tamaño de fragmento mayor para que el contexto del paso map sea más completo
  • Ejecute un paso de verificación: pregunte al modelo si las entidades clave del original aparecen en el resumen final
MAP_PROMPT = '''Summarize the following section in 5 sentences.
Preserve all key names, numbers, dates, and conclusions.

Section:
{chunk}'''

Cadena refine: un patrón alternativo

La cadena refine es una alternativa a map-reduce. Procesa los fragmentos de forma secuencial: el resumen del fragmento N se pasa junto con el fragmento N+1 y el modelo actualiza el resumen acumulado. Esto produce resultados más coherentes, pero no se puede paralelizar y es más lento.

Utilice refine cuando la coherencia narrativa sea importante (por ejemplo, en contratos legales). Utilice map-reduce cuando la velocidad sea prioritaria (por ejemplo, en lotes de artículos de noticias).

def refine_summarize(chunks):
    current_summary = summarize_chunk(chunks[0])
    for chunk in chunks[1:]:
        prompt = (
            f'Existing summary:\n{current_summary}\n\n'
            f'New section:\n{chunk}\n\n'
            'Update the summary to incorporate the new section.'
        )
        resp = client.chat.completions.create(
            model='gpt-4o',
            messages=[{'role': 'user', 'content': prompt}]
        )
        current_summary = resp.choices[0].message.content
    return current_summary

Gestión de costes y tokens

Map-reduce realiza muchas llamadas a la API. Para un documento de 100 fragmentos con gpt-4o a 5 $ por cada millón de tokens de entrada:

  • Map: 100 fragmentos × 1000 tokens = 100.000 tokens de entrada ≈ 0,50 $
  • Reduce: aproximadamente 10.000 tokens (resúmenes) ≈ 0,05 $
  • Total: aproximadamente 0,55 $ por documento

Para reducir el coste, utilice gpt-4o-mini en la fase map (0,15 $ por cada millón) y gpt-4o únicamente para reduce. Este enfoque híbrido reduce los costes en un 70 % con una pérdida mínima de calidad.

def map_phase_cheap(chunks):
    # Use mini model for map — cheaper, sufficient for chunk summaries
    return [
        summarize_chunk(c, model='gpt-4o-mini')
        for c in chunks
    ]

def reduce_phase_quality(summaries):
    # Use full model for final synthesis
    return reduce_phase(summaries, model='gpt-4o')

Cuándo utilizar map-reduce

El resumido map-reduce es más adecuado para:

  • Documentos más largos que la ventana de contexto del modelo
  • El resumido por lotes de muchos documentos (también puede paralelizarlo por documento)
  • Situaciones en las que necesita controlar el prompt de cada paso

Es menos adecuado para extraer un dato específico (utilice recuperación en su lugar) o cuando el documento sea lo bastante corto como para caber en el contexto (resúmalo directamente).

Comprobación de conocimientos

En el patrón de resumido map-reduce, ¿qué ocurre durante la fase reduce?

Recapitulación: resumido map-reduce

El patrón map-reduce permite gestionar documentos demasiado largos para una única llamada al LLM:

  • Map: resumir cada fragmento de forma independiente; se puede paralelizar
  • Reduce: sintetizar los resúmenes de los fragmentos en un único resumen final
  • Reduce recursivo: aplicarlo cuando los propios resúmenes son demasiado largos
  • Consejo para reducir costes: utilizar un modelo económico para map y un modelo de mayor calidad para reduce

El MapReduceDocumentsChain de LangChain proporciona una implementación lista para usar. En la próxima lección se aborda el resumido jerárquico de libros y artículos de investigación.

Preguntas frecuentes

¿La lección «Patrón de resumen Map-Reduce» es gratis?

Sí — el texto completo de «Patrón de resumen Map-Reduce» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Prompt Engineering, actualiza a CoddyKit PRO. El curso de AI Prompt Engineering incluye 4 lecciones en total.

¿Qué aprenderé en «Patrón de resumen Map-Reduce»?

Resuma cada fragmento de forma independiente y después sintetice los resúmenes. Practicas AI Prompt Engineering con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Prompt Engineering?

No se requiere experiencia previa. AI Prompt Engineering en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Patrón de resumen Map-Reduce»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Prompt Engineering?

Sí. Cada lección de AI Prompt Engineering incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Estrategias de división para textos largos
  2. Patrón de resumen Map-Reduce
  3. Resumen jerárquico
  4. Mantener el contexto entre fragmentos
← Volver a AI Prompt Engineering