Desmitificando la digestión de documentos: una inmersión profunda en la síntesis de documentos masivos, parte 1 | por Vinayak Sengupta | Sep, 2024

RAG es una solución ampliamente implementada y ampliamente debatida para abordar la optimización de resúmenes de documentos mediante tecnologías GenAI. Sin embargo, como cualquier tecnología o solución nueva, es propensa a desafíos extremos, especialmente en el entorno empresarial actual. Dos preocupaciones principales son la extensión contextual junto con el costo por mensaje y el problema del contexto “perdido en el medio” mencionado anteriormente. Profundicemos un poco más para comprender estos desafíos.

Nota: Realizaré los ejercicios en Python utilizando las bibliotecas LangChain, Scikit-Learn, Numpy y Matplotlib para iteraciones rápidas.

Hoy en día, con los flujos de trabajo automatizados que permite GenAI, analizar documentos grandes se ha convertido en una expectativa/requisito de la industria. Las personas quieren encontrar rápidamente información relevante de informes médicos o auditorías financieras con solo solicitar el LLM. Pero hay una salvedad: los documentos empresariales no son como los documentos o conjuntos de datos con los que trabajamos en el ámbito académico, los tamaños son considerablemente más grandes y la información pertinente puede estar presente prácticamente en cualquier parte de los documentos. Por lo tanto, los métodos como la limpieza/filtrado de datos a menudo no son una opción viable, ya que no siempre se proporciona el conocimiento del dominio sobre estos documentos.

Además de esto, incluso los últimos modelos de lenguaje grande (LLM) como GPT-4o de OpenAI con ventanas de contexto de 128K tokens no pueden consumir estos documentos de una sola vez o incluso si lo hicieran, la calidad de la respuesta no cumpliría con los estándares, especialmente por el costo que implicaría. Para demostrar esto, tomemos un ejemplo del mundo real en el que se intenta resumir el Manual del empleado de GitLab que se puede descargar aquíEste documento está disponible de forma gratuita bajo la licencia MIT disponible en su GitHub repositorio.

1 Comenzamos cargando el documento y también inicializamos nuestro LLM, para mantener relevante este ejercicio haré uso de GPT-4o.

from langchain_community.document_loaders import PyPDFLoader

# Load PDFs
pdf_paths = ["/content/gitlab_handbook.pdf"]
documents = []

for path in pdf_paths:
loader = PyPDFLoader(path)
documents.extend(loader.load())

from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o")

2 Luego podemos dividir el documento en fragmentos más pequeños (esto es para incrustaciónExplicaré por qué en los pasos posteriores).

from langchain.text_splitter import RecursiveCharacterTextSplitter

# Initialize the text splitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)

# Split documents into chunks
splits = text_splitter.split_documents(documents)

3 Ahora, calculemos cuántos tokens componen este documento, para esto iteraremos a través de cada fragmento del documento y calcularemos el total de tokens que componen el documento.

total_tokens = 0

for chunk in splits:
text = chunk.page_content # Assuming `page_content` is where the text is stored
num_tokens = llm.get_num_tokens(text) # Get the token count for each chunk
total_tokens += num_tokens

print(f"Total number of tokens in the book: {total_tokens}")

# Total number of tokens in the book: 254006

Como podemos ver, la cantidad de tokens es 254 006, mientras que el límite de la ventana de contexto para GPT-4o es 128 000. Este documento no se puede enviar de una sola vez a través de la API de LLM. Además de esto, considerando que el precio de este modelo es de $0,00500 / 1000 tokens de entrada, ¡una sola solicitud enviada a OpenAI para este documento costaría $1,27! Esto no suena horrible hasta que lo presentas en un paradigma empresarial con múltiples usuarios e interacciones diarias en muchos documentos tan grandes, especialmente en un escenario de startup donde están naciendo muchas soluciones GenAI.

Otro desafío al que se enfrentan los LLM es el Perdido en el medio, Problema de contexto como se analiza en detalle en este papelLa investigación y mis experiencias con sistemas RAG que manejan múltiples documentos describen que los LLM no son muy robustos cuando se trata de extrapolar información de entradas de contexto largas. El rendimiento del modelo se degrada considerablemente cuando la información relevante está en algún lugar en el medio del contexto. Sin embargo, el rendimiento mejora cuando la información requerida está al principio o al final del contexto proporcionado. La reclasificación de documentos es una solución que se ha convertido en un tema de creciente debate e investigación para abordar este problema específico. Exploraré algunos de estos métodos en otra publicación. Por ahora, volvamos a la solución que estamos explorando, que utiliza la agrupación en clústeres de K-medias.

Vale, admito que he introducido un concepto técnico en la última sección, permítanme explicarlo (para aquellos que no conozcan el método, los entiendo).

Primero lo básico

Para entender la agrupación en clústeres de K-means, primero debemos saber qué es la agrupación en clústeres. Consideremos lo siguiente: tenemos un escritorio desordenado con bolígrafos, lápices y notas todos dispersos. Para ordenar, uno agruparía los elementos similares, como todos los bolígrafos en un grupo, los lápices en otro y las notas en otro, creando esencialmente tres grupos separados (sin promover la segregación). La agrupación en clústeres es el mismo proceso en el que, entre una colección de datos (en nuestro caso, los diferentes fragmentos de texto del documento), se agrupan datos o información similares creando una clara separación de preocupaciones para el modelo, lo que facilita que nuestro sistema RAG seleccione y seleccione la información de manera efectiva y eficiente en lugar de tener que revisarla toda como un método codicioso.

K, ¿significa?

K-means es un método específico para realizar clustering (existen otros métodos pero no nos adentremos en la información). Permítanme explicarles cómo funciona en 5 sencillos pasos:

  1. Selección del número de grupos (K):¿En cuántos grupos queremos que se dividan los datos?
  2. Selección de centros de grupo:Inicialmente, se selecciona aleatoriamente un valor central para cada uno de los grupos K
  3. Trabajo en grupo:A continuación, cada punto de datos se asigna a cada grupo en función de su proximidad a los centros elegidos previamente. Ejemplo: los elementos más cercanos al centro 1 se asignan al grupo 1, los elementos más cercanos al centro 2 se asignarán al grupo 2… y así sucesivamente hasta el grupo K.
  4. Ajuste de los centros:Una vez clasificados todos los puntos de datos, calculamos el promedio de las posiciones de los elementos en cada grupo y estos promedios se convierten en los nuevos centros para mejorar la precisión (porque inicialmente los habíamos seleccionado al azar).
  5. Enjuagar y repetir: Con los nuevos centros, las asignaciones de puntos de datos se actualizan nuevamente para los grupos K. Esto se hace hasta que la diferencia (matemáticamente la Euclidiano distancia) es mínimo para los elementos dentro de un grupo y máximo para otros puntos de datos de otros grupos, es decir, segregación óptima.

Si bien esta puede ser una explicación bastante simplificada, se puede encontrar una explicación más detallada y técnica (para mis compañeros nerds) de este algoritmo. aquí.