Document și Node (TextNode): unitățile de date din LlamaIndex în LlamaIndex & Data RAG

Ingestie, Parsare & Indexare Nivel: începător

Document este containerul pentru o sursă de date (fișier, răspuns API, rând din baza de date); Node este o bucată dintr-un Document, cu metadate și relații, și este unitatea pe care o indexează și o regăsește LlamaIndex.

Sintaxă & invocare Python
from llama_index.core import Document
from llama_index.core.node_parser import SentenceSplitter

doc = Document(text="Contractul se reînnoiește anual.", metadata={"categorie": "juridic"})
nodes = SentenceSplitter().get_nodes_from_documents([doc])
print(nodes[0].node_id, nodes[0].metadata)

Documentația numește Document și Node abstracțiile de bază ale LlamaIndex. Un Document învelește o sursă de date: un PDF, ieșirea unui API sau date dintr-o bază de date. Îl creează cititorii (de exemplu SimpleDirectoryReader) sau îl construiești manual. Are text, metadata (un dicționar) și relationships. Document este o subclasă a lui TextNode, deci opțiunile de mai jos se aplică și nodurilor.

Un Node este o bucată (chunk) dintr-un Document: text, imagine sau alt tip. Nodurile se obțin cu un NodeParser (SentenceSplitter și ceilalți) și moștenesc metadatele documentului din care provin, de exemplu file_name. Relațiile (NodeRelationship.SOURCE, PREVIOUS, NEXT, PARENT, CHILD) leagă nodul de document și de vecini.

Metadatele sunt incluse implicit în textul trimis atât modelului de embedding, cât și LLM-ului. Cu excluded_embed_metadata_keys și excluded_llm_metadata_keys alegi ce chei vede fiecare, iar get_content(metadata_mode=MetadataMode.LLM) sau MetadataMode.EMBED îți arată textul exact. doc_id (sau id_) identifică documentul la actualizări; SimpleDirectoryReader(..., filename_as_id=True) îl setează la calea fișierului.

Concepte cheie și caracteristici

Concept / Parametru Descriere practică
Document(text=..., metadata=...) Creează un document manual. Document.example() întoarce un document de test.
metadata Dicționar de adnotări. Unele baze vectoriale cer chei string și valori plate (str, int, float).
doc_id / id_ ID-ul documentului, folosit de refresh_ref_docs() și de gestiunea documentelor din IngestionPipeline.
excluded_llm_metadata_keys / excluded_embed_metadata_keys Cheile de metadate ascunse LLM-ului, respectiv modelului de embedding.
metadata_template / metadata_separator / text_template Formatul în care metadatele sunt lipite de text. Implicit "{key}: {value}", separator "\n" și "{metadata_str}\n\n{content}". În constructor, documentația folosește aliasul metadata_seperator (cu această ortografie) pentru câmpul metadata_separator.
TextNode(text=..., id_=...) Nod creat manual, din llama_index.core.schema; VectorStoreIndex(nodes) îl indexează direct.
node.relationships Dicționar NodeRelationship → RelatedNodeInfo; parserii setează automat SOURCE, PREVIOUS și NEXT.

Exemple practice și scenarii reale

Exemplul 1: Ce vede LLM-ul și ce vede modelul de embedding

După exemplul din documentație: file_name ajută căutarea, dar nu e nevoie să ajungă în promptul LLM-ului.

from llama_index.core import Document
from llama_index.core.schema import MetadataMode

doc = Document(
    text="Plata se face în 30 de zile de la factură.",
    metadata={"file_name": "contract_2026.pdf", "categorie": "juridic"},
    excluded_llm_metadata_keys=["file_name"],
)
print(doc.get_content(metadata_mode=MetadataMode.LLM))
print(doc.get_content(metadata_mode=MetadataMode.EMBED))

Exemplul 2: Noduri create manual, cu relații

from llama_index.core import VectorStoreIndex
from llama_index.core.schema import TextNode, NodeRelationship, RelatedNodeInfo

n1 = TextNode(text="Capitolul 1: obiectul contractului.", id_="n1")
n2 = TextNode(text="Capitolul 2: prețul și plata.", id_="n2")
n1.relationships[NodeRelationship.NEXT] = RelatedNodeInfo(node_id=n2.node_id)
n2.relationships[NodeRelationship.PREVIOUS] = RelatedNodeInfo(node_id=n1.node_id)

index = VectorStoreIndex([n1, n2])

Greșeli frecvente și capcane

  • Metadate lungi sau numeroase. Ele intră implicit în textul trimis la embedding și la LLM și ocupă din dimensiunea chunk-ului; ascunde cu excluded_*_metadata_keys ce nu ajută.
  • Valori imbricate (liste de dicționare) în metadate când folosești o bază vectorială externă. Multe cer valori plate.
  • Documente fără doc_id stabil. Fără el, refresh_ref_docs() și deduplicarea din IngestionPipeline nu recunosc același document la o rulare nouă.

Noțiuni și module înrudite