Inicio / Artículos

PageIndex: RAG sin vectores, basado en razonamiento, con índice de árbol

PageIndex abandona la base de datos vectorial en favor de un índice de árbol gestionado por un LLM. Cómo funciona este RAG basado en razonamiento, con código en Python, una conexión MCP y números de referencia.

Editor: REACTAPP.TOP14 min de lectura3118 palabras

Fuentes: PageIndex: The RAG Framework That Threw Out Vector Databases and Still Hit 98.7% Accuracy

Imagínese un framework RAG que descarta por completo las bases de datos vectoriales y, aun así, presenta un resultado de prueba que ningún sistema basado en embeddings puede igualar. Ese es PageIndex, un proyecto de código abierto de VectifyAI. En FinanceBench, la prueba estándar para responder preguntas sobre documentos financieros, los sistemas RAG convencionales basados en vectores obtienen resultados entre el 30 y el 50 por ciento. PageIndex, en cambio, alcanza el 98,7 por ciento. No lo logró gracias a un modelo de embeddings mejor, sino al eliminarlos por completo.

Ese resultado merece una segunda mirada, ya que la respuesta a preguntas financieras a partir de documentos presentados ante la SEC es una de las pruebas más exigentes de recuperación de información en la inteligencia artificial en producción. Requiere razonamiento en múltiples pasos, saltos entre secciones y números exactos. El mejor sistema existente no utilizó vectores, ni procesamiento en bloques, ni bases de datos vectoriales.

Aquí se explica qué hace PageIndex, cómo está construido, el código Python que lo hace funcionar, dónde brilla y dónde no.

El muro al que chocan los documentos extensos

Cualquiera que haya desarrollado RAG para contenido más largo que un artículo de blog conoce este problema. Un usuario le pregunta a un sistema basado en un informe anual de 200 páginas cuál es la comparación entre los ingresos netos totales en el ejercicio fiscal 2024 y en el ejercicio fiscal 2023. El flujo estándar funciona de la siguiente manera:

  1. Dividir el documento en fragmentos de tamaño fijo, generalmente de 300 a 500 tokens.
  2. Incorporar cada fragmento con un modelo como text-embedding-3-large.
  3. Almacenar los vectores en Pinecone, Weaviate, Milvus, Chroma, pgvector o sistemas similares.
  4. Al realizar la consulta, incorporar la pregunta y obtener los k vectores más cercanos mediante similitud de coseno.
  5. Passar esos fragmentos al LLM para que escriba la respuesta.

Para material breve y no estructurado como artículos de blog, tickets de soporte y documentación de productos, eso funciona bien. Pero un informe 10-K lo divide de maneras predecibles.

La consulta no parece ser la respuesta. La recuperación de vectores asume que el texto más similar a la consulta es el más relevante. Pero una consulta expresa una intención, no un contenido. Una pregunta sobre las tendencias de ingresos no muestra la única fila de la tabla en la página 47, sino todos los párrafos que hablan sobre ingresos.

Un término, sesenta lugares. En un largo informe anual, “ingreso operativo” aparece docenas de veces en diferentes contextos. La similitud los clasifica más o menos por igual, y el pasaje que realmente responde a la pregunta puede nunca llegar a los tres primeros puestos.

El fragmentado daña las tablas. Un encabezado de tabla queda en el fragmento 14 y la fila que se necesita está en el fragmento 15. Ninguno de los dos tiene sentido por sí solo. Las ventanas superpuestas, el fragmentado semántico y los analizadores conscientes de tablas ayudan, pero ninguno elimina el problema subyacente.

No hay memoria entre turnos. Si el mensaje anterior preguntaba por activos y el siguiente pregunta “¿y qué hay de pasivos?”, el sistema de recuperación considera que se trata de una consulta completamente nueva. Nada le indica que lo más probable es que el usuario se refiera a la misma sección del mismo informe.

Las referencias cruzadas permanecen ocultas. Supongamos que la página 12 dirige a los lectores al Apéndice G, y que ese apéndice se encuentra en la página 87. El texto del apéndice no tiene superposición semántica con la pregunta original, por lo que el sistema vectorial RAG nunca seguirá esa referencia. Inyectar metadatos de referencias cruzadas en los fragmentos de texto es una solución temporal, pero es frágil y no es escalable.

Estos no son casos marginales raros. Provienen de la propia arquitectura. Como expresó Mingtian Zhang, cofundador de VectifyAI, en el anuncio del proyecto, lo que realmente necesita la recuperación de información es la relevancia, y la relevancia requiere razonamiento.

Qué es PageIndex

PageIndex es un marco RAG sin vectores y basado en el razonamiento, lanzado por VectifyAI en septiembre de 2025, creado por Zhang y Yu Tang. Está licenciado bajo MIT, y su repositorio creció rápidamente, superando las 23,000 estrellas y casi 2,000 forks a finales de marzo de 2026.

Su idea central proviene de AlphaGo. En lugar de escanear exhaustivamente un espacio, comparando cada fragmento mediante similitud vectorial, se utiliza una estrategia aprendida para navegarlo de manera inteligente. PageIndex aplica este enfoque a los documentos, con tres propiedades destacables:

  • Sin base de datos vectoriales. La estructura de los documentos y el razonamiento del LLM reemplazan la búsqueda por similitud, por lo que no hay Pinecone, ni Chroma, ni embeddings.
  • Sin fragmentación. Los documentos permanecen organizados como secciones naturales, capítulos, párrafos y tablas, y no como ventanas arbitrarias de 500 tokens.
  • Navegación al estilo humano. Se comporta como una persona que busca un documento a mano: mira el índice, encuentra la sección que probablemente contenga la respuesta y la lee.

El método consta de dos pasos.

Paso 1: un índice en forma de árbol jerárquico

Al procesar un documento no se crean embeddings. PageIndex analiza la estructura del documento y genera un árbol jerárquico, esencialmente un índice adecuado para LLMs. Cada nodo contiene un título, un breve resumen de la sección, un rango de páginas y nodos hijos para las subsecciones, anidados según sea necesario.

Un documento SEC de 50 páginas podría generar un árbol con de 30 a 50 nodos, almacenado como un único objeto JSON. Nada se almacena en una base de datos vectorial, solo JSON. Todo el objeto cabe en una ventana de contexto de un LLM, y se puede abrir cualquier nodo para leerlo. Un nodo se ve así:

{
  "node_id": "0006",
  "title": "Financial Stability",
  "start_index": 21,
  "end_index": 22,
  "summary": "Covers the Federal Reserve's financial stability oversight...",
  "sub_nodes": [
    {
      "node_id": "0007",
      "title": "Monitoring Financial Vulnerabilities",
      "start_index": 22,
      "end_index": 28,
      "summary": "Describes the Fed's vulnerability monitoring framework..."
    },
    {
      "node_id": "0008",
      "title": "Domestic and International Cooperation",
      "start_index": 28,
      "end_index": 31,
      "summary": "Federal Reserve collaboration with international bodies..."
    }
  ]
}

Cada node_id apunta al contenido en bruto de esa sección: texto, tablas e imágenes. El LLM puede solicitar el contenido de cualquier nodo cuando lo necesite.

La clave arquitectónica radica en dónde se encuentra este índice. Una base de datos vectorial mantiene un índice estático y separado de los embeddings fuera del modelo. Aquí, el árbol JSON se encuentra dentro del contexto activo del LLM durante la inferencia. VectifyAI lo denomina índice in-context, y el modelo no solo lo consulta, sino que también razona sobre él en tiempo real.

Paso 2: búsqueda en árbol impulsada por el razonamiento

Cuando llega una pregunta, PageIndex proporciona al LLM el árbol, con solo títulos y resúmenes y sin texto en bruto, y en esencia le pregunta dónde buscar teniendo en cuenta esta estructura y la pregunta. El modelo lee los títulos y resúmenes de los nodos, determina qué secciones probablemente contengan la respuesta y devuelve una lista de IDs de nodos. El sistema luego obtiene el contenido real de esos nodos.

La recuperación de información es un bucle:

  1. Examinar el índice para comprender la estructura y identificar las secciones candidatas.
  2. Elegir una sección que tenga la mayor probabilidad de contener lo necesario.
  3. Leerla, extrayendo el texto en bruto de ese nodo.
  4. Verificar si es suficiente. Si lo es, escribir la respuesta. Si no, volver al primer paso e intentar otra sección.

Este es un paradigma diferente al de la búsqueda vectorial. Una base de datos vectorial calcula la similitud coseno en paralelo sobre cada fragmento, lo cual es rápido pero superficial. PageIndex, en cambio, utiliza un modelo LLM para determinar dónde es probable que se encuentre la respuesta. Durante el proceso, el modelo puede seguir referencias cruzadas, reconocer que una pregunta sobre datos del apéndice pertenece al nodo correspondiente al apéndice, y darse cuenta de que una pregunta con varias partes necesita contenido de dos secciones. Cada paso también deja un rastro del razonamiento, por lo que se puede ver qué nodos se visitaron y por qué. La recuperación de información deja de ser una caja negra.

El ejemplo del Apéndice G

Una demostración basada en la integración MCP de VectifyAI muestra por qué esto es importante. Alguien pregunta por el total de activos diferidos en un informe anual de la Reserva Federal. El cuerpo principal, en las páginas 75 a 82, analiza el cambio en los activos diferidos pero nunca indica el total. Sin embargo, la página 77 contiene una oración que dice que la Tabla 5.3 resume ingresos, gastos y distribuciones, y que el Apéndice G ofrece información más detallada.

Vector RAG se queda atascado aquí. El Apéndice G es una tabla de números que no tiene similitud semántica con una pregunta sobre activos diferidos, por lo que la base de datos lo ignora. PageIndex funciona de manera diferente. El LLM lee el árbol, va a la sección financiera, detecta la referencia al Apéndice G, la sigue a través del árbol, obtiene la tabla correcta y devuelve la cifra exacta, con un rastro de razonamiento que muestra cada paso.

Python, de principio a fin

El código a continuación está adaptado del libro oficial PageIndex, con comentarios que muestran el flujo. Comience con la instalación:

pip install pageindex openai

Importaciones:

import os
import json
import asyncio
from pageindex import PageIndexClient
from openai import AsyncOpenAI

Luego están las credenciales y los clientes. Una clave API proviene del panel de control PageIndex:

# Grab an API key from https://dash.pageindex.ai/api-keys
PAGEINDEX_API_KEY = os.environ["PAGEINDEX_API_KEY"]
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]pi_client = PageIndexClient(api_key=PAGEINDEX_API_KEY)
openai_client = AsyncOpenAI(api_key=OPENAI_API_KEY)

Construir el árbol

Introducir las herramientas necesarias:

import pageindex.utils as utils

Suba un PDF y deje que PageIndex genere el árbol. El indexado lleva algo de tiempo, por lo que el script hace consultas hasta que esté listo y muestra el resultado:

# Upload a PDF; PageIndex handles the tree generation
doc = pi_client.upload("annual_report_2024.pdf")
doc_id = doc["doc_id"]# Tree generation takes a bit, so we poll
while not pi_client.is_retrieval_ready(doc_id):
    print("Still indexing...")
    import time; time.sleep(5)# Grab the tree and take a look
tree = pi_client.get_tree(doc_id, node_summary=True)["result"]
print("Document Tree:")
utils.print_tree(tree)

La impresión muestra cada sección, subsección y rango de páginas, lo que permite saber de inmediato si el árbol capturó el diseño correctamente.

Deje que el LLM busque en el árbol

Este es el paso fundamental. La función recibe el árbol y una consulta:

async def find_relevant_nodes(tree: dict, query: str) -> list:
    """LLM reasons over tree structure to identify relevant nodes."""

Dentro, el texto en bruto se elimina para ahorrar tokens, ya que el modelo solo necesita títulos y resúmenes. La instrucción presenta al modelo como un experto en recuperación de documentos, le pide que siga las referencias cruzadas y solicita un JSON que contenga su razonamiento además de una lista de IDs de nodos:

    # Strip raw text to save tokens; the LLM only needs titles and summaries
    tree_without_text = utils.remove_fields(
        tree.copy(), fields=["text"]
    )    search_prompt = f"""
    You are a document retrieval expert. Given a question and
    a hierarchical tree structure of a document, identify all
    nodes likely to contain the answer.    Each node has a node_id, title, and summary.
    Follow cross-references if a section mentions another.    Question: {query}    Document tree structure:
    {json.dumps(tree_without_text, indent=2)}    Reply in this JSON format only:
    {{
        "thinking": "<reasoning about which nodes are relevant>",
        "node_list": ["node_id_1", "node_id_2"]
    }}
    """    response = await openai_client.chat.completions.create(
        model="gpt-4.1",
        messages=[{"role": "user", "content": search_prompt}],
        temperature=0,
        response_format={"type": "json_object"},
    )    result = json.loads(response.choices[0].message.content)
    print(f"LLM reasoning: {result['thinking']}")
    return result["node_list"]

Obtener contenido y responder

La siguiente función recopila el texto sin procesar de los nodos seleccionados:

def collect_node_content(tree: dict, node_ids: list) -> str:
    """Pull raw text from the nodes the LLM selected."""
    all_nodes = utils.flatten_tree(tree)
    context_parts = []

Luego, el cuerpo del bucle reúne el contexto, con cada sección etiquetada por título y rango de página, y todo el proceso lo envuelve: selecciona nodos, obtiene el contenido, genera una respuesta con citas y devuelve la respuesta junto con los nodos utilizados.

    for node in all_nodes:
        if node["node_id"] in node_ids:
            title = node.get("title", "Untitled")
            pages = f"pages {node.get('start_index', '?')}-{node.get('end_index', '?')}"
            text = node.get("text", "")
            context_parts.append(
                f"[{title} | {pages}]\n{text}"
            )
    return "\n\n---\n\n".join(context_parts)
async def answer_query(tree: dict, query: str) -> dict:
    """Full vectorless RAG pipeline: tree search + answer generation."""    # Step 1: LLM picks the nodes
    node_ids = await find_relevant_nodes(tree, query)    # Step 2: Fetch content from those nodes
    context = collect_node_content(tree, node_ids)    # Step 3: Generate answer with citations
    answer_prompt = f"""
    Answer the question using only the provided context.
    Cite specific pages and sections in your answer.    Context:
    {context}    Question: {query}
    """    response = await openai_client.chat.completions.create(
        model="gpt-4.1",
        messages=[{"role": "user", "content": answer_prompt}],
        temperature=0,
    )    return {
        "answer": response.choices[0].message.content,
        "retrieved_nodes": node_ids,
        "context_length": len(context),
    }
# Run it
query = "What was the total value of deferred assets in 2023?"
result = asyncio.run(answer_query(tree, query))
print(result["answer"])
print(f"Nodes used: {result['retrieved_nodes']}")

Conexión con MCP

Para Claude, Cursor o cualquier agente compatible con MCP, PageIndex se conecta directamente a través de un servidor alojado:

{
  "mcpServers": {
    "pageindex": {
      "type": "http",
      "url": "https://api.pageindex.ai/mcp",
      "headers": {
        "Authorization": "Bearer your_api_key"
      }
    }
  }
}

También existe un servidor MCP local para cargar archivos desde el disco, y requiere Node.js 18 o una versión más reciente:

{
  "mcpServers": {
    "pageindex": {
      "command": "npx",
      "args": ["-y", "@pageindex/mcp"]
    }
  }
}

Las cifras, en contexto

La cifra principal proviene de FinanceBench, que se basa en documentos reales presentados ante la SEC, incluidos los 10-K, 10-Q y 8-K, y solo acepta respuestas exactas. Mafin 2.5, el agente de análisis financiero de VectifyAI desarrollado sobre PageIndex, se probó con el conjunto de datos completo. Precisión reportada:

Sistema Precisión Cobertura del benchmark
Mafin 2.5 (PageIndex) 98.7% 100%
Vector RAG tradicional aproximadamente 50% varía
GPT-4o sin RAG aproximadamente 31% 100%
Perplexity aproximadamente 45% varía

Una diferencia de aproximadamente 49 puntos porcentuales con respecto al Vector RAG convencional no es una mejora pequeña; representa una categoría distinta de resultados. Tres factores siguen apareciendo repetidamente:

  • Referencias cruzadas. Los enlaces dentro del documento, como “ver Apéndice G”, se navegan a través del árbol. La búsqueda por similitud no tiene en cuenta estos enlaces.
  • Mantenimiento de la estructura. Las tablas cuentan con encabezados, notas al pie y relaciones entre celdas. PageIndex las conserva como nodos del árbol, mientras que el procesamiento en bloques las destruye.
  • Razonamiento multietapa. Una pregunta que compara el ejercicio fiscal 2023 con el ejercicio fiscal 2024, presentada en diferentes partes del documento, se resuelve de forma natural mediante el bucle iterativo.

Debilidades

PageIndex es impresionante para su ámbito específico, pero no reemplaza al RAG vectorial en todos los casos.

  • Es más lento. Cada recuperación implica varias llamadas al LLM: leer el índice, razonar sobre los nodos, obtener el contenido, verificar la suficiencia, y posiblemente repetir el proceso. Vector RAG responde en milisegundos, mientras que PageIndex lo hace en segundos. El cofundador ha señalado que, dado que la recuperación ocurre en tiempo real durante la generación, el tiempo hasta obtener el primer token puede ser comparable al de una llamada normal al LLM, pero la latencia total sigue siendo mayor.
  • Cuesta más. Se realizan múltiples llamadas de inferencia por consulta, en lugar de una sola búsqueda de embeddings. A gran escala, las cifras resultantes son bastante elevadas.
  • Está diseñado para la profundidad, no para la amplitud. Destaca en la extracción detallada de información de un único documento largo. Buscar 10,000 documentos cortos al mismo tiempo es donde las bases de datos vectoriales demuestran su utilidad, ya que construir y razonar sobre un árbol para cada uno no es práctico.
  • La estructura es importante. Un archivo SEC con encabezados bien formateados genera un índice excelente. Una digitalización mal formateada sin secciones lógicas produce un índice de contenidos deficiente, lo que afecta negativamente todo lo demás. Existe un modo basado en visión para estos casos, pero los documentos estructurados siguen siendo la opción óptima.
  • El razonamiento de los LLM también es imperfecto. Vector RAG falla porque los embeddings solo aproximan el significado. PageIndex también comete errores cuando el razonamiento es aproximado: el modelo puede dirigirse a la sección incorrecta, interpretar mal un resumen o omitir un subnodo relevante. Estos fallos son más fáciles de interpretar y, posiblemente, de depurar, pero aún ocurren.
  • Un único punto de referencia. FinanceBench mide la calidad de los controles en documentos presentados ante la SEC y bien estructurados. Los resultados obtenidos con consultas complejas, que abarcan múltiples dominios y son ambiguas, en tipos de documentos muy diferentes, no han sido validados de forma independiente con el mismo grado de precisión. El 98,7 por ciento es real, pero es importante saber qué es lo que se mide.
  • Cuándo usarlo

    Utilice PageIndex cuando:

    • los documentos son largos, bien estructurados y profesionales: informes anuales, contratos, documentos regulatorios, manuales técnicos
    • la precisión es más importante que la velocidad, como cuando una respuesta incorrecta genera costos económicos o riesgos de cumplimiento
    • las consultas requieren razonamiento en múltiples pasos o la navegación entre secciones
    • necesita registros de auditoría, ya que cada respuesta incluye un rastro de razonamiento y referencias a nodos, algo que valoran las industrias reguladas

    Permanezca con el RAG vectorial cuando:

    • necesita respuestas en menos de un segundo con un alto volumen de consultas
    • está buscando en un gran corpus de documentos cortos
    • los documentos son no estructurados o de tipo conversacional
    • un 90 por ciento de precisión es suficiente
    • el costo por consulta es la principal limitación

    Un enfoque híbrido probablemente no se ha explorado lo suficiente. Utilice la búsqueda vectorial para determinar qué documento de un gran corpus es relevante y luego páselo a PageIndex para una extracción más profunda.

    ¿Qué hay de nuevo desde el lanzamiento?

    El proyecto ha avanzado rápidamente desde septiembre de 2025.

    RAG vectorless basado en agentes. La última adición conecta un PageIndex autohospedado al SDK de OpenAI Agents. Al agente se le proporcionan tres herramientas (get_document(), get_document_structure() y get_page_content()), y este analiza el árbol por sí mismo, utilizando las herramientas adecuadas y recuperando el contenido sin necesidad de seleccionar manualmente los nodos. Es el ejemplo a partir del cual comenzar con flujos de trabajo basados en agentes:

    pip install openai-agents
    python3 examples/agentic_vectorless_rag_demo.py
    

    Modo basado en visión, sin OCR. Un flujo de trabajo diseñado específicamente para el procesamiento visual omite ahora el OCR. Las imágenes de las páginas van directamente a un modelo especializado en visión, y el árbol se genera a partir de lo que ese modelo percibe en la página. Esto es importante en documentos financieros donde el diseño de un estado de cuentas tiene tanta importancia como el texto. Los gráficos, las tablas con celdas combinadas y las notas al pie permanecen intactos, ya que nada se convierte primero en texto.

    Un SDK de TypeScript, pageindex-js-sdk, llegó a principios de 2026 para integraciones con Node.js y herramientas de documentos basadas en la web. Una extensión de escritorio .mcpb de un solo clic instala PageIndex en Claude Desktop, con el manejo automático de OAuth. ChatIndex, un repositorio separado desde enero de 2026, aplica la misma idea de indexación por árbol a historiales de conversaciones extensos.

    El cambio más amplio

    PageIndex representa un cambio más amplio desde la recuperación pasiva, que obtiene todo lo que parece similar, hacia una recuperación activa y basada en razonamiento que decide dónde buscar. Esto ya se puede observar en las herramientas de programación: Claude Code y Cursor han dejado de utilizar el RAG basado en vectores para el código en favor de explorar activamente la base de código, y el equipo de PageIndex espera que los documentos sigan ese mismo enfoque. Para documentos estructurados, esa predicción parece plausible.

    Las bases de datos vectoriales no van a desaparecer. Son rápidas, económicas y suficientemente buenas para una gran variedad de problemas. Pero en aquellos casos donde la corrección, la transparencia y una comprensión profunda de los documentos son indispensables, como en auditorías financieras, búsquedas legales, registros médicos y cumplimiento normativo, la recuperación basada en razonamiento es una opción fundamentalmente mejor.

    El código y los documentos se encuentran en https://github.com/VectifyAI/PageIndex, con documentación en https://docs.pageindex.ai/.

    Leer más