Intermedio 11 minStack

LlamaIndex en pratique

Respuesta directa

LlamaIndex es un marco en Python que gestiona toda la cadena de un RAG: carga de documentos, fragmentación, embeddings, indexación, consultas con fuentes. Localmente, se conecta a Ollama y a embeddings como BGE-M3, pero su configuración predeterminada llama a OpenAI: define Settings.llm y Settings.embed_model antes de indexar, y ajusta context_window y request_timeout.

LlamaIndex reduce un RAG a unas pocas líneas, pero sus valores por defecto (OpenAI, ventana de contexto, tiempo límite de 30 segundos) pueden causar problemas en las instalaciones locales, y los antiguos tutoriales de agentes ya no funcionan. Sabrás montar un pipeline completamente local, elegir un modo de consulta, añadir un reranker y escribir un agente con la API actual.

Por Mohamed Meguedmi·Actualización 2026-09-30·Probado en Windows, macOS y Linux

#LlamaIndex en la práctica: para qué sirve y cuándo adoptarlo

LlamaIndex es un framework de Python que se encarga de toda la cadena de un RAG: cargar documentos, dividirlos en fragmentos (nodes), convertirlos en vectores, indexarlos y luego consultar el índice con un LLM que cita sus fuentes. La versión 0.14.25, publicada en PyPI el 21 de septiembre de 2026, requiere Python 3.10 o superior. Un RAG mínimo cabe en unas diez líneas; el framework resulta útil cuando hay que variar las fuentes, cambiar el modo de respuesta, añadir un reranker o conectar un agente. En local, funciona con Ollama para el LLM y un modelo de embeddings de tu elección, siempre que desactives sus ajustes predeterminados, que llaman a OpenAI. Esta guía explica cómo montar un RAG completamente local, muestra los ajustes que importan y corrige varios ejemplos obsoletos que aún se encuentran en línea.

Abstracciones claras
Document, Node, VectorStoreIndex, retriever, query engine: cada etapa del RAG tiene un objeto específico que se puede sustituir.
Conectores de datos
SimpleDirectoryReader lee PDF, Word, PowerPoint, Markdown, imágenes o audio; otros lectores cubren Notion, Google Docs, Slack o Discord.
Modos de consulta
Varias estrategias de síntesis y motores más elaborados (subpreguntas, enrutamiento entre índices) para ir más allá de la simple búsqueda vectorial.
Ejecución local posible
Ollama y los embeddings de Hugging Face o de Ollama se conectan a través de paquetes de integración específicos.

#Las etapas de un RAG LlamaIndex y sus ajustes por defecto

El kit RAG Local

Tus documentos, tu IA: un RAG local fiable sobre tus PDF, notas y correos — sin enviar nada a la nube.

  • Espacio en línea de por vida
  • PDF + archivos
  • Reembolsado 30 j

Antes de escribir código, ten presentes el pipeline y, sobre todo, sus valores por defecto: ahí se esconden la mayoría de las sorpresas al trabajar en local.

Pipeline de LlamaIndex: objetos y valores por defecto
PasoObjeto o ajusteValor por defecto que conviene conocer
SegmentaciónSentenceSplitter, Settings.chunk_size1.024 tokens de tamaño, 20 de solapamiento
EmbeddingsSettings.embed_modeltext-embedding-ada-002 de OpenAI, según la documentación
LLMSettings.llmgpt-3.5-turbo de OpenAI, según el tutorial de inicio
AlmacenamientoVectorStoreIndex, StorageContextEn memoria; se debe persistir explícitamente en disco
Síntesisresponse_modecompact: concatena tantos chunks como permita la ventana
LLM Ollamarequest_timeout30 segundos por defecto, a menudo demasiado cortos en local
!
Sin configuración, LlamaIndex llama a OpenAI
La documentación indica que LlamaIndex utiliza por defecto la API de OpenAI para el LLM y los embeddings. Con una clave OPENAI_API_KEY presente en el entorno, tus documentos serían enviados a OpenAI para ser vectorizados, sin advertencia. Para un RAG confidencial, establece siempre Settings.llm y Settings.embed_model antes de indexar, como se indica en la sección siguiente.

#Instalación para un RAG 100 % local

El comando pip install llama-index instala un paquete de inicio que incluye llama-index-core, las integraciones de OpenAI para el LLM y los embeddings, y los lectores de archivos. Para la ejecución local, añade las integraciones de Ollama y de embeddings (llama-index-embeddings-ollama si prefieres OllamaEmbedding); los paquetes de OpenAI del paquete de inicio siguen instalados, pero no se utilizan siempre que configures Settings.

Terminal
pip install llama-index \
            llama-index-llms-ollama \
            llama-index-embeddings-huggingface

ollama pull mistral

El nombre de un paquete indica cómo importarlo: llama-index-llms-ollama corresponde a llama_index.llms.ollama. En cuanto a la memoria, ten en cuenta los pesos del LLM (alrededor de 5 GB para un 7-8B en Q4, referencia del sitio), el modelo de embeddings y el contexto: un equipo con 16 GB sirve para un corpus pequeño; más memoria ofrece margen.

#Un RAG en diez líneas (con sus ajustes por defecto de OpenAI)

Python
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

docs = SimpleDirectoryReader("./docs").load_data()
index = VectorStoreIndex.from_documents(docs)

query = index.as_query_engine()
print(query.query("Résume les points clés du contrat X"))

Este código es válido, pero utiliza los modelos predeterminados de OpenAI: falla sin clave y con clave envía tus textos al proveedor. Sirve de esqueleto. La sección siguiente añade las líneas necesarias para hacerlo local.

#Pasar a una ejecución local con Ollama y embeddings en francés

Bastan tres bloques de configuración: el LLM, el modelo de embeddings y la división en fragmentos. Para el francés, BGE-M3 es una opción habitual: su ficha indica más de 100 idiomas y entradas de hasta 8.192 tokens. La descarga del modelo pesa aproximadamente 2,3 GB (archivo pytorch_model.bin del repositorio de Hugging Face) y se realiza una sola vez.

Python
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.llms.ollama import Ollama
from llama_index.embeddings.huggingface import HuggingFaceEmbedding

# Configuration globale : tout est local
Settings.llm = Ollama(
    model="mistral",
    base_url="http://localhost:11434",
    request_timeout=120.0,   # le défaut est de 30 s
    context_window=8000,     # transmis à Ollama comme num_ctx
)
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-m3")
Settings.chunk_size = 700
Settings.chunk_overlap = 100

# Pipeline
docs = SimpleDirectoryReader("./docs").load_data()
index = VectorStoreIndex.from_documents(docs, show_progress=True)

# Persister sur disque
index.storage_context.persist(persist_dir="./storage")

# Requêter
query_engine = index.as_query_engine(similarity_top_k=5)
reponse = query_engine.query("Quels sont les risques identifiés ?")
print(reponse)
for src in reponse.source_nodes:
    print(f"  - {src.metadata.get('file_name')} ({src.score:.2f})")
Python
from llama_index.core import load_index_from_storage, StorageContext

storage = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage)

#Por qué importan context_window y request_timeout

El código fuente de la integración de Ollama en LlamaIndex pasa el valor de context_window a Ollama con el nombre num_ctx. Sin ello, Ollama aplica su ventana predeterminada, de unos 4.000 tokens cuando hay menos de 24 GiB de VRAM, según su documentación. El cálculo es sencillo: cinco fragmentos de 700 tokens suman 3.500 tokens, sin contar todavía la pregunta, las instrucciones de la plantilla del prompt y la respuesta. Con 4.000 tokens, el prompt supera el límite y el contexto se trunca, a menudo sin ningún error visible. Con 8.000, hay margen.

El tiempo de espera es la otra trampa: el cliente Ollama de LlamaIndex lo fija en 30 segundos por defecto. Una primera llamada que carga el modelo en memoria y procesa un prompt largo puede superar ese límite. Los 120 segundos del ejemplo son un punto de partida que debes ajustar según tu hardware.

→
Embeddings mediante Ollama en lugar de Hugging Face
Si no quieres instalar PyTorch para los embeddings, LlamaIndex ofrece OllamaEmbedding: utiliza el servidor Ollama ya arrancado, con un modelo de embeddings obtenido mediante ollama pull. La biblioteca Ollama ofrece bge-m3. Cambiar el modelo de embeddings implica reindexar todos los documentos, ya que los vectores de dos modelos no son comparables.

#Cargar tus archivos: ajustes de SimpleDirectoryReader

SimpleDirectoryReader lee un directorio completo y maneja muchos formatos: PDF, Word, PowerPoint, Markdown, imágenes, audio y video. Algunos parámetros evitan indexar cualquier cosa.

Python
from llama_index.core import SimpleDirectoryReader

docs = SimpleDirectoryReader(
    input_dir="./docs",
    required_exts=[".pdf", ".docx"],  # ne charger que ces formats
    num_files_limit=100,              # plafond pour un premier essai
).load_data()

Los conectores hacia servicios (Notion, Google Docs, Slack, Discord) obtienen los datos en línea: es inevitable, ya que allí se almacenan. Una vez cargados los documentos, la indexación y la consulta permanecen locales, con tus embeddings y tu LLM Ollama. Haz una prueba inicial con algunos archivos: un PDF escaneado sin capa de texto no dará resultados hasta que no pase por un OCR, como explica la guía Tesseract.

#Elegir un modo de consulta y su costo en llamadas al LLM

El modo de síntesis determina cuántas veces se llama al LLM, por lo tanto el tiempo de respuesta local. La tabla muestra los modos documentados y su costo, con un ejemplo de cinco pasajes de 700 tokens y una ventana de 8.000 tokens (estimación).

Modos de respuesta y número de llamadas al LLM
ModoPrincipio (documentación)Llamadas en el ejemplo
compact (predeterminado)Concatena tantos chunks como permita la ventana, luego consulta1 llamada: 3.500 tokens entran en 8.000
refineRecorre los chunks uno por uno, con una llamada por chunk5 llamadas, consecutivas
tree_summarizeConsulta por grupos y luego resume recursivamente las respuestas1 llamada si todo cabe en la ventana, de lo contrario varias, luego un resumen final
simple_summarizeTrunca todo para que quepa en un solo prompt1 llamada, con pérdida de detalle
no_textSolo ejecuta el retriever, sin llamar al LLM0 llamadas; útil para depurar la búsqueda

Para una pregunta factual, mantén compact. Para resumir un documento largo, tree_summarize está diseñado para ello, a costa de varias llamadas: en una máquina local, calcula que tardará varias veces lo que tarda una respuesta sencilla. no_text es útil para comprobar lo que devuelve la búsqueda, sin esperar al LLM.

#Añadir un reranker local

Cuando la respuesta correcta está entre los 20 primeros pasajes pero no entre los 5 primeros, un reranker reordena los candidatos antes de enviarlos al LLM. La documentación de LlamaIndex recomienda SentenceTransformerRerank como opción predeterminada que no requiere clave API y se ejecuta localmente; es un cross-encoder que utiliza sentence-transformers. También menciona Qwen3-Reranker-0.6B para una mejor calidad multilingüe.

Python
from llama_index.core.postprocessor import SentenceTransformerRerank

reranker = SentenceTransformerRerank(
    model="cross-encoder/ms-marco-MiniLM-L2-v2",
    top_n=3,
)
query_engine = index.as_query_engine(
    similarity_top_k=15,             # large pour rattraper la bonne réponse
    node_postprocessors=[reranker],  # puis resserre à 3
)

El modelo proporcionado aquí es el del ejemplo oficial, elegido por su rapidez; está diseñado para el inglés: para documentos en francés, prueba un reranker multilingüe. La guía dedicada detalla la elección y la evaluación.

#Subpreguntas y enrutamiento

SubQuestionQueryEngine
Descompone una pregunta compleja en subpreguntas que envía a herramientas de consulta y luego sintetiza los resultados. «Compara las estrategias de 2024 y 2025» se convierte en dos búsquedas separadas.
RouterQueryEngine
Elige, para cada pregunta, el motor adecuado entre varios (por ejemplo, un índice de resúmenes o un índice vectorial).

Estos dos motores multiplican las llamadas al LLM: una descomposición en tres subpreguntas añade la generación de las subpreguntas, tres respuestas y la síntesis final, lo que supone al menos cinco llamadas. En hardware local, resérvalos para las preguntas que justifiquen su uso.

#Agentes: la API actual ya no es la de los tutoriales antiguos

Muchos tutoriales utilizan ReActAgent.from_tools. Esta clase ya no existe en el código fuente actual: el módulo agent/react/base.py que la contenía ha desaparecido del repositorio. Los agentes son ahora flujos de trabajo asíncronos: FunctionAgent (un agente que llama a funciones o herramientas), la versión de ReActAgent basada en flujos de trabajo y AgentWorkflow para orquestar varios agentes. El tutorial oficial para uso local construye el agente con AgentWorkflow.from_tools_or_functions y lo ejecuta con await agent.run.

Python
import asyncio
from llama_index.core import Settings
from llama_index.core.agent.workflow import AgentWorkflow

async def search_documents(query: str) -> str:
    """Répond aux questions sur les contrats clients."""
    response = await query_engine.aquery(query)
    return str(response)

agent = AgentWorkflow.from_tools_or_functions(
    [search_documents],
    llm=Settings.llm,
    system_prompt="Tu réponds uniquement à partir des contrats indexés.",
)

async def main():
    reponse = await agent.run("Y a-t-il une clause de non-concurrence chez Acme Corp ?")
    print(str(reponse))

asyncio.run(main())

El nombre, la descripción y los argumentos de la función (su docstring) se envían al LLM, que decide si debe llamarla: cuida, por tanto, esa descripción. El funcionamiento de FunctionAgent se basa en llamadas nativas a funciones; con un modelo local, elige uno que admita herramientas en Ollama y mantén el RAG sencillo si el tuyo no tiene esa capacidad.

#LlamaIndex, LangChain o RAG propio: cómo elegir

Tres enfoques para un RAG local
CriterioRAG propio (ChromaDB, embeddings)LlamaIndexLangChain
Objetivo principalEntender cada paso, control totalPipeline documental con componentes listosOrquestación de herramientas y agentes
Tiempo de puesta en marchaMás largo: todo se tiene que escribirCorto para un primer RAGCorto para una cadena, más largo para un RAG completo
PersonalizaciónIlimitado, a tu cargoAjustes por componentes, objetos reemplazablesMuy flexible, más verboso
Riesgo principalReinventar un pipeline existenteDefectos de OpenAI, API que evoluciona rápidoAPI que evoluciona rápidamente

Regla práctica: un RAG documental con fuentes citadas, formatos variados y algunas opciones de consulta se construye rápidamente con LlamaIndex. Si quieres entender primero el mecanismo, escribe una implementación propia una vez: la guía de ChromaDB muestra los pasos. Para un agente que maneje muchas herramientas externas, puedes comparar LangChain y los workflows de LlamaIndex según tu forma habitual de trabajar.

#Los escollos que hacen perder tiempo

Reindexar en cada ejecución
Sin persist, el índice permanece en memoria y desaparece al finalizar el script. Guarda el índice de forma persistente y luego vuelve a cargarlo con load_index_from_storage.
Cambiar de modelo sin reindexar
Los vectores de dos modelos de embeddings no son comparables: modificar embed_model o la división en fragmentos obliga a reconstruir el índice.
Contexto truncado en silencio
Un prompt más largo que la ventana de Ollama se trunca: verifica context_window si las respuestas ignoran los últimos pasajes.
Copiar un antiguo tutorial
Las API de agentes han cambiado: verifica que los imports de un ejemplo existan en la versión instalada (0.14.25 al momento de redacción).
No medir nunca
Un RAG sin evaluación se desvía sin que lo sepas: la guía sobre Ragas muestra cómo cuantificar esa desviación.
FAQ
¿Funciona completamente LlamaIndex en local?+
Sí, siempre que se definan Settings.llm (por ejemplo, Ollama) y Settings.embed_model (Hugging Face o Ollama) antes de indexar. De lo contrario, la documentación indica que LlamaIndex utiliza por defecto los modelos de OpenAI. Solo los conectores a servicios en línea, como Notion o Slack, necesariamente salen de la máquina para recuperar los datos.
¿Qué modelo de embeddings elegir para documentos en francés?+
BGE-M3 es una opción común: su ficha anuncia más de 100 idiomas, entradas de hasta 8.192 tokens y una descarga de aproximadamente 2,3 GB. Las referencias varían según tus documentos: pruébalo con tus propias preguntas antes de generalizar y consulta la guía de embeddings para francés para comparar las alternativas.
¿Por qué mi RAG LlamaIndex olvida pasajes?+
A menudo porque el contexto se trunca: Ollama aplica por defecto alrededor de 4 000 tokens cuando la VRAM es inferior a 24 GiB, y cinco fragmentos de 700 tokens ya ocupan 3 500. Establece context_window en el objeto Ollama, aumenta la memoria disponible si es necesario o reduce similarity_top_k.
¿Cómo evitar reindexar cada vez que se inicia?+
Guarda el índice de forma persistente con index.storage_context.persist(persist_dir="./storage"), luego vuelve a cargarlo con StorageContext.from_defaults y load_index_from_storage. Por defecto, LlamaIndex mantiene los datos en memoria y los pierde al finalizar el script. Si cambias de modelo de embeddings o de tamaño de chunk, los vectores calculados cambian: entonces debes reconstruir el índice y volver a guardarlo de forma persistente.
ReActAgent.from_tools ya no funciona, ¿qué hacer?+
Esta API de los tutoriales antiguos ya no está disponible en las fuentes actuales. Usa los agentes de flujo de trabajo: AgentWorkflow.from_tools_or_functions o FunctionAgent, con funciones asíncronas y await agent.run. Asegúrate de que tu modelo Ollama soporte herramientas; de lo contrario, mantén un RAG simple sin agente, o prueba el flujo de trabajo ReActAgent, que no requiere llamadas a funciones nativas.
¿LlamaIndex o LangChain para un RAG local?+
LlamaIndex se centra en los datos y en el RAG: carga, índice, modos de consulta. LangChain se enfoca en la orquestación de herramientas y agentes. Para conversar con tus documentos, LlamaIndex permite empezar más rápido; para un agente con múltiples herramientas, compara ambos en un caso real y quédate con aquel cuya API domines.
¿Esta guía te ha ayudado?

¿Un comentario, un error, una precisión? Avísanos, eso mejora la guía para todos.