DS DevShelfHub Projects · AI tools
Cheatsheets / LlamaIndex
Cheatsheet · AI frameworks

LlamaIndex Cheatsheet: Documents, Retrievers, Agents and RAG

By DevShelfHub

LlamaIndex is a Python data framework for building LLM applications over custom documents: it handles ingestion (SimpleDirectoryReader, PDF, web), chunking, embedding, vector storage, and retrieval in a single opinionated pipeline. This cheatsheet covers Documents, Nodes, VectorStoreIndex, retrievers, query engines, the chat engine pattern, agents, tools, and production configuration.

97 items ◷ 7 min Indices Retrievers QueryEngines

LlamaIndex (formerly GPT Index) is a Python data framework purpose-built for LLM applications that need to reason over custom documents. Its central abstraction is the index: you load documents, LlamaIndex chunks and embeds them, stores the vectors, and wraps the whole pipeline in a query engine that retrieves relevant chunks and synthesises an answer. The framework is deliberately opinionated — the default pipeline works well out of the box with minimal configuration, making it faster to get a RAG application running than with a more modular tool like LangChain.

The data model flows from Documents (raw content + metadata, produced by readers like SimpleDirectoryReader, PyMuPDFReader, or web loaders) through Nodes (chunks with relationships to their source document and neighbours) into an Index (most commonly VectorStoreIndex). A QueryEngine wraps the index for single-turn Q&A; a ChatEngine adds conversation history for multi-turn use. Both can be backed by any vector store — the built-in in-memory store is fine for prototypes, while Qdrant, Pinecone, or Chroma scale to production corpora.

LlamaIndex ships with a growing agents layer: ReActAgent and FunctionCallingAgent follow the standard tool-use loop, and QueryEngineTool wraps any index as a callable tool so agents can route across multiple document collections. The LlamaIndex Hub provides pre-built loaders and tools for dozens of data sources. This cheatsheet covers the everyday surface: ingestion, indexing, retrieval, query and chat engines, agents, tools, and the key configuration knobs for embedding models, LLMs, and vector stores.

Start hereQuick start · 6 you’ll reach for daily

Load docsSimpleDirectoryReader("./data").load_data()
Build indexVectorStoreIndex.from_documents(docs)
Askindex.as_query_engine().query("…")
Chatindex.as_chat_engine().chat("…")
Set defaultsSettings.llm = OpenAI(…)
Persiststorage_context.persist(persist_dir=…)

Target versions · paceVersions

Targets: llama-index ≥ 0.12 llama-index-core ≥ 0.12 python ≥ 3.10

LlamaIndex split into ~200 sub-packages around 0.10 — provider integrations now live as llama-index-llms-*, llama-index-embeddings-*, llama-index-vector-stores-*, llama-index-readers-*. The umbrella llama-index still works but pulls many. Pin individual sub-packages in production. Names current as of May 2026.

install · env · defaultsSetup

bash
# Core package + the integrations you'll need
pip install llama-index                              # umbrella metapackage
pip install llama-index-core                         # if you want to pick & mix
pip install llama-index-llms-openai \
            llama-index-embeddings-openai \
            llama-index-readers-file \
            llama-index-vector-stores-chroma

# env
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-...
export LLAMA_CLOUD_API_KEY=llx-...   # optional, LlamaParse / LlamaCloud

# Global defaults (used by every index/engine unless overridden)
python - <<'PY'
from llama_index.core import Settings
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
Settings.llm = OpenAI(model="gpt-4o-mini", temperature=0)
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
PY

where things liveCommon imports

Core abstractions sit in llama_index.core. Provider bindings are split into their own llama_index.{llms,embeddings,readers,vector_stores}.* sub-packages.

from llama_index.core import VectorStoreIndex, SummaryIndex, KeywordTableIndexIndex classes.
from llama_index.core import Document, Settings, StorageContextDocument, global config, storage.
from llama_index.core import SimpleDirectoryReaderLocal-file loader.
from llama_index.core.node_parser import SentenceSplitter, MarkdownNodeParserChunkers.
from llama_index.core.ingestion import IngestionPipelineReusable ETL.
from llama_index.core.retrievers import VectorIndexRetriever, BM25RetrieverHand-rolled retrievers.
from llama_index.core.query_engine import RetrieverQueryEngine, SubQuestionQueryEngineQuery engines.
from llama_index.core.chat_engine import CondenseQuestionChatEngine, ContextChatEngineChat engines.
from llama_index.core.tools import FunctionTool, QueryEngineToolTool wrappers for agents.
from llama_index.core.agent.workflow import FunctionAgent, ReActAgentAgent classes.
from llama_index.llms.openai import OpenAIOpenAI LLM.
from llama_index.llms.anthropic import AnthropicAnthropic LLM.
from llama_index.embeddings.openai import OpenAIEmbeddingOpenAI embeddings.
from llama_index.vector_stores.chroma import ChromaVectorStoreChroma backend.
from llama_index.readers.file import PDFReader, DocxReaderFormat-specific readers.

raw input · chunked atomsDocuments & nodes

Document(text="…", metadata={"src":"…"})Construct from raw text.
SimpleDirectoryReader("./data").load_data()All supported files in a folder.
SimpleDirectoryReader(…, recursive=True, required_exts=[".md"])Filter by extension.
PDFReader().load_data(file=Path("a.pdf"))Single PDF loader.
doc.excluded_llm_metadata_keysHide metadata fields from the LLM.
doc.excluded_embed_metadata_keysHide metadata from embeddings.
SentenceSplitter(chunk_size=800, chunk_overlap=120)Default chunker. Splits on sentence then ¶.
MarkdownNodeParser()Header-aware split for Markdown.
CodeSplitter(language="python")AST-aware code splitter.
SemanticSplitterNodeParser(embed_model=…)Splits by embedding similarity. Smarter, slower.
parser.get_nodes_from_documents(docs)Documents → nodes manually.
node.metadata, node.text, node.relationshipsWhat every node carries.

how docs are organisedIndices

VectorStoreIndex.from_documents(docs)Preferred for semantic search.
VectorStoreIndex.from_vector_store(store)Reload an existing store without re-embedding.
SummaryIndex.from_documents(docs)Walks every node. Use for “summarise everything” tasks.
KeywordTableIndex.from_documents(docs)Sparse keyword-based. No embeddings.
PropertyGraphIndex.from_documents(docs)Knowledge-graph index. Entities + relations.
DocumentSummaryIndex.from_documents(docs)One summary per doc; retrieves whole docs.
index.insert(doc)Add one document to a live index.
index.delete_ref_doc(ref_doc_id)Remove all nodes from a given doc.
index.storage_context.persist(persist_dir="./store")Persist to disk.
load_index_from_storage(StorageContext.from_defaults(persist_dir=…))Reload from disk.

find the right nodesRetrievers

index.as_retriever(similarity_top_k=6)Default vector retriever from any index.
VectorIndexRetriever(index=…, similarity_top_k=6)Explicit construction.
BM25Retriever.from_defaults(nodes=…, similarity_top_k=10)Lexical / sparse retrieval.
QueryFusionRetriever(retrievers=[a,b], mode="reciprocal_rerank")Preferred Hybrid: dense + sparse, RRF-blended.
AutoMergingRetriever(base, storage_context)Merges sibling chunks back into parents.
RecursiveRetriever("root", retriever_dict=…)Follow node relationships across indices.
retriever.retrieve("query")→ list[NodeWithScore].

Postprocessors (re-rank / filter)

SimilarityPostprocessor(similarity_cutoff=0.7)Drop low-similarity hits.
KeywordNodePostprocessor(required_keywords=["policy"])Filter by required terms.
CohereRerank(top_n=3)Provider rerank. Strong default for accuracy.
LLMRerank(top_n=3, choice_batch_size=5)LLM-judged rerank. Slow, accurate.
SentenceEmbeddingOptimizer(percentile_cutoff=0.5)Drop low-relevance sentences within each node.

retrieve + synthesiseQuery engines

index.as_query_engine()Default. Vector retriever + compact synthesis.
index.as_query_engine(similarity_top_k=6, response_mode="tree_summarize")Tune k and synthesis mode.
response_mode="compact"Preferred Pack as much context as fits in one call.
response_mode="refine"Walk nodes one-by-one, refining the answer.
response_mode="tree_summarize"Hierarchical map-reduce. Good for long answers.
response_mode="no_text"Return raw nodes only. Use when you do your own synthesis.
RetrieverQueryEngine.from_args(retriever, node_postprocessors=[…])Fully custom pipeline.
SubQuestionQueryEngine.from_defaults(query_engine_tools=[…])Decompose a question across multiple sources.
RouterQueryEngine(selector=…, query_engine_tools=[…])Pick one engine per query.
resp = engine.query("…")Returns a Response. resp.source_nodes for citations.
engine.stream_query("…")Stream tokens as they arrive.
python
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.core.postprocessor import SimilarityPostprocessor
from llama_index.core.response_synthesizers import get_response_synthesizer

# Reload the existing store as an index (no re-embedding)
index = VectorStoreIndex.from_vector_store(store)

# Hand-roll the pipeline: retriever -> postprocessors -> synthesizer
retriever = index.as_retriever(similarity_top_k=6)
postprocessors = [SimilarityPostprocessor(similarity_cutoff=0.7)]
synth = get_response_synthesizer(response_mode="compact")

# Or use the prebuilt query engine
query_engine = index.as_query_engine(
    similarity_top_k=6,
    response_mode="compact",
    node_postprocessors=postprocessors,
)

resp = query_engine.query("What does the onboarding doc say about access?")
print(str(resp))
for n in resp.source_nodes:
    print(n.score, n.node.metadata.get("file_name"))

multi-turn over an indexChat engines

index.as_chat_engine(chat_mode="condense_plus_context")Preferred Rewrites the question, then retrieves.
chat_mode="context"Plain retrieval + chat. No rewrite.
chat_mode="condense_question"Rewrites follow-ups into standalone questions.
chat_mode="simple"LLM only, no retrieval. Lets you A/B test.
chat_mode="react"ReAct loop with the index as a tool.
chat_engine.chat("…")Single turn.
chat_engine.stream_chat("…")Streaming variant.
chat_engine.reset()Clear history.

reusable ETLIngestion pipeline

IngestionPipeline bundles transformations (splitting, embedding, extractors) and writes resulting nodes to a vector store. Hash-based caching skips work on re-runs.

IngestionPipeline(transformations=[…], vector_store=…)Build a pipeline.
pipeline.run(documents=docs)Run once. Returns nodes.
arun(documents=docs)Async variant.
IngestionCache(cache=…, collection=…)Persist transform outputs by hash.
TitleExtractor(nodes=5)LLM-generated titles in metadata.
QuestionsAnsweredExtractor(questions=3)Generate candidate questions per node.
SummaryExtractor()Per-node summaries.
python
from llama_index.core import SimpleDirectoryReader
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.ingestion import IngestionPipeline
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.vector_stores.chroma import ChromaVectorStore
import chromadb

# 1 · Load
docs = SimpleDirectoryReader("./data", recursive=True).load_data()

# 2 · Build a reusable pipeline (splitter + embeddings + sink)
chroma = chromadb.PersistentClient(path="./chroma")
store = ChromaVectorStore(chroma_collection=chroma.get_or_create_collection("docs"))

pipeline = IngestionPipeline(
    transformations=[
        SentenceSplitter(chunk_size=800, chunk_overlap=120),
        OpenAIEmbedding(model="text-embedding-3-small"),
    ],
    vector_store=store,
)

# 3 · Run — produces nodes and writes them to the vector store
nodes = pipeline.run(documents=docs, show_progress=True)

tools + reasoning loopAgents

FunctionTool.from_defaults(fn=callable)Wrap a Python function. Docstring + type hints become the schema.
QueryEngineTool.from_defaults(query_engine=…, name=…, description=…)Expose an index as a tool.
ToolMetadata(name=…, description=…)Attach metadata explicitly when wrapping.
FunctionAgent(tools=[…], llm=…)Preferred Tool-call-native agent.
ReActAgent(tools=[…], llm=…)Reasoning-trace-based. Useful for non-tool-call models.
CodeActAgent(tools=[…], code_execute_fn=…)Generates & runs Python; tools are functions in scope.
await agent.run("…")One async call. Returns final string + state.
handler = agent.run_step(…)Step-by-step control for HITL.
AgentWorkflow(agents=[…], root_agent=…)Multi-agent orchestration.
python
from llama_index.core.tools import FunctionTool, QueryEngineTool
from llama_index.core.agent.workflow import FunctionAgent
from llama_index.llms.openai import OpenAI

def add(a: int, b: int) -> int:
    """Return a + b."""
    return a + b

calc = FunctionTool.from_defaults(fn=add)

docs_tool = QueryEngineTool.from_defaults(
    query_engine=query_engine,
    name="company_docs",
    description="Search internal onboarding + HR docs.",
)

agent = FunctionAgent(
    tools=[calc, docs_tool],
    llm=OpenAI(model="gpt-4o-mini"),
    system_prompt="You are a precise assistant. Cite sources.",
)

resp = await agent.run("How many vacation days do new hires get? Then add 3.")
print(resp)

where embeddings liveVector stores

SimpleVectorStore()In-memory default. Dev only.
ChromaVectorStore(chroma_collection=…)Local persistent. llama-index-vector-stores-chroma.
QdrantVectorStore(client=…, collection_name=…)Self-host or cloud.
PineconeVectorStore(pinecone_index=…)Managed.
PGVectorStore.from_params(…)Postgres + pgvector.
WeaviateVectorStore(weaviate_client=…, index_name=…)Weaviate.
StorageContext.from_defaults(vector_store=…)Wrap a store as storage context for an index.

folder → index → answerEnd-to-end · Minimal RAG

Persistent Chroma store, global defaults, indexed from a folder, answered with a compact response. Replace the folder and you have a working doc-bot.

python
from llama_index.core import (
    SimpleDirectoryReader, VectorStoreIndex, Settings, StorageContext,
)
from llama_index.core.node_parser import SentenceSplitter
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.vector_stores.chroma import ChromaVectorStore
import chromadb

# 1 · Configure global defaults
Settings.llm = OpenAI(model="gpt-4o-mini", temperature=0)
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
Settings.node_parser = SentenceSplitter(chunk_size=800, chunk_overlap=120)

# 2 · Persistent vector store
client = chromadb.PersistentClient(path="./chroma")
store = ChromaVectorStore(chroma_collection=client.get_or_create_collection("docs"))
storage = StorageContext.from_defaults(vector_store=store)

# 3 · Build (or rebuild) the index from a folder
docs = SimpleDirectoryReader("./data", recursive=True).load_data()
index = VectorStoreIndex.from_documents(docs, storage_context=storage)

# 4 · Ask
engine = index.as_query_engine(similarity_top_k=4, response_mode="compact")
print(engine.query("Summarise the access policy in 3 bullets."))

Best practiceGood to know

Configure Settings once at module top. Settings.llm, Settings.embed_model, Settings.node_parser are picked up by every index / engine. Beats threading kwargs through.
Hybrid retrieval beats dense-only on FAQ-shaped corpora. Wire BM25Retriever + VectorIndexRetriever into QueryFusionRetriever. Cheap accuracy win.
Use IngestionPipeline with a cache. On repeat ingestion, unchanged chunks skip embedding entirely. Halves dev-loop cost.

Common trapsWatch out for

The umbrella llama-index package shifts heavy deps. In prod, pin only the sub-packages you import (llama-index-core + llama-index-llms-openai …). Otherwise you pull TF, torch, and friends transitively.
Settings is process-global. Two indices in the same process share the same LLM unless you pass a different one explicitly. Easy to have an “eval” index silently inherit your prod model.
Persisting a store doesn’t persist Settings. Reload requires re-setting Settings.embed_model to the same model used at ingest. Mismatched dims raise on the first query.

Go deeperSee also

LlamaIndex FAQ

What is LlamaIndex?

LlamaIndex is a Python framework for building retrieval-augmented generation (RAG) and data-aware LLM applications. It provides a standardised pipeline for ingesting documents, splitting and embedding them into nodes, storing them in a vector index, and querying with a query engine or chat engine. It competes with LangChain's retrieval stack and has a more opinionated RAG-first design.

What is the difference between LlamaIndex and LangChain?

LlamaIndex is optimised for structured data ingestion and RAG: it has richer document loaders, node pipelines, and index types (vector, summary, keyword, knowledge graph) out of the box. LangChain is broader, covering agent orchestration, tool use, memory, and LCEL composition. Many teams use LlamaIndex for the retrieval layer and LangGraph or raw model calls for the agent layer.

How do I build a RAG pipeline with LlamaIndex?

Load documents with a reader (SimpleDirectoryReader or a specific loader), parse them into nodes with a node parser, create a VectorStoreIndex from the nodes, then call index.as_query_engine() to get a query engine. Query with engine.query(question) and the engine retrieves the top-k relevant nodes and synthesises a response using your LLM.

What are query engines in LlamaIndex?

A query engine is a high-level interface that combines retrieval and synthesis into a single call. index.as_query_engine() returns the default retriever + response synthesiser pair. You can customise the retriever (top-k, similarity threshold, hybrid), the response mode (compact, refine, tree summarise), and the reranker. For multi-turn conversations, use index.as_chat_engine() instead.

What vector stores does LlamaIndex support?

LlamaIndex ships integration packages for Chroma, Pinecone, Weaviate, Qdrant, pgvector, Redis, Milvus, and many more. Swap stores by passing a different VectorStore object to VectorStoreIndex.from_vector_store(). The default SimpleVectorStore is in-memory and useful for prototyping; move to a persistent store like Chroma or pgvector before going to production.