You load a document, call an index builder, and receive an answer. What happened to the document between those steps? LlamaIndex provides useful abstractions, but a reliable application needs to inspect the data inside them.
Before you begin: Understand chunking, embeddings, and retrieval. Python knowledge is useful for the optional example.
Follow the data, not just the helper calls
A document represents source material and metadata. A node is a unit derived from that material, often a text chunk with links back to its source. An index organizes nodes for retrieval. A retriever chooses candidates; a query engine can combine retrieval with response generation.
These are separate responsibilities. If the wrong chunk is retrieved, changing the writer's tone will not repair the evidence. If parsing dropped a table header, a good embedding model cannot recover its missing meaning.
Consider two fictional notices. N1 says W1 has capacity 12. N2 says W2 has capacity 8. Keep IDs attached throughout indexing so that “capacity 12” can be traced to W1. A paragraph without its source metadata is harder to verify or update.
Inspect nodes before making a model call
This complete package example requires llama-index-core. It performs local document splitting, with no LLM or embedding provider. Its API follows the official document and node guides reviewed on September 10, 2026; package execution is not implied by the course's standard-library test count.
from llama_index.core import Document
from llama_index.core.node_parser import SentenceSplitter
documents = [
Document(
text="W1 has capacity 12. Booking status is unknown.",
metadata={"source_id": "N1", "version": "1"},
),
Document(
text="W2 has capacity 8. It starts at 10:00.",
metadata={"source_id": "N2", "version": "1"},
),
]
splitter = SentenceSplitter(chunk_size=128, chunk_overlap=16)
nodes = splitter.get_nodes_from_documents(documents)
for node in nodes:
print(node.metadata["source_id"], node.get_content())
assert {node.metadata["source_id"] for node in nodes} == {"N1", "N2"}
The chunk limits refer to the splitter's token accounting, not a promise of exactly 128 words per node. Short source documents can remain much smaller. Inspect the produced boundaries instead of assuming a setting guarantees coherent chunks.
Add retrieval deliberately
The VectorStoreIndex abstraction can embed and index documents or nodes. Choose the embedding integration explicitly and record its model identifier. The query embedding must be compatible with the indexed vectors. Do not rely on an old tutorial's default provider or model being the right choice today.
When adding a query engine, configure its generation model separately from the embedding model. Embeddings choose evidence; generation writes an answer from that evidence. A provider may charge for both operations. Keeping them separate also lets you evaluate retrieval without generating a paragraph for every test.
Persistence is another decision. Saving an index can avoid repeating ingestion, but you must also preserve source versions, transformation settings, and compatible embedding configuration. A saved index is not automatically a complete per-user application database.
Find the upstream defect
A retrieved node says “12” but has lost the workshop ID and the word “capacity.” Would a larger generation model reliably fix the answer?
Inspect the missing context
No. The evidence no longer identifies what 12 measures. Repair parsing or chunk construction so that the number stays with its label and source. Then verify retrieval and answer behavior separately. A larger model might guess the original relationship, but guessing is the defect the application was meant to avoid.
For practice, add a revised N1 and decide whether to replace the old version, retain both with dates, or expose an explicit conflict. Test that a deleted or unauthorized source cannot remain available through a stale index.
Next, explore how to present generated output while preserving the distinction between partial text and a completed answer.
Sources
Documents and nodes explains the data units. VectorStoreIndex describes indexing. Node parser usage covers splitting.