Knowledge graph
The knowledge graph stores source structure, searchable chunks, extracted entities, and links between them in Neo4j. This lets retrieval move from a match to related facts and back to the text that supports them.
Why it exists
Every fact in an answer must trace back to text. A graph of only entities cannot show where a fact came from. A graph of only text cannot connect facts.
Agentic GraphRAG keeps both text and structure in one graph. An entity links to the chunks that mention it, and a chunk links to its document and sections. Retrieval can therefore use relationships without losing the path back to source evidence.
How it works
The node kinds and their edges. Entity nodes use your schema's type names as labels. HAS_PART also joins a document to each section, table and figure.
The main node kinds serve different roles in retrieval and provenance:
- Document: one node for each logical document. Its
document_keystays the same when the content changes. It holds the source location, the title, the current content hash, optionalpublished_atandcontent_datedates, and the name, version and fingerprints of the schema and extraction setup that produced it. - Section: one heading of a document, or the unheaded content when the document has no headings yet. It holds the heading, its depth, and its page range or character range. It holds no text. The chunks under it hold the text. A section has a stable
section_keythat stays the same while the heading path and the place among sections with that path stay the same. - Table and Figure: one node for each table or figure. A table holds its caption, its column names and its row count. A figure holds its caption and its page box. It does not store the image.
- Source: one node for each record file, such as a CSV file. It joins each of its row documents with
HAS_DOCUMENT. - Chunk: one retrieval-sized piece of text. It holds the text, its location in the source, the headings above it, the sections it covers and the chunker that made it.
- Entity: one node for each name and type, such as the person "Ada Lovelace". Its label is the type from your schema. A type with parents also adds the labels of its parents to the node. The same name with two types makes two entities. It records which chunks mention it.
- ResolvedEntity (see Matching and resolved entities): a group of entities that the resolver decided are the same thing. It exists only for groups of two or more.
- Community (see Communities): a group of related entities. It holds a title, a summary, a rating and findings.
The edges connect them:
HAS_CHILDbuilds the tree. It joins a document or section to its sections, tables, figures and chunks, and a table to its chunks. It carries anorder, the reading order of the child.HAS_DOCUMENTjoins the source file of a record file, such as a CSV file, to each of its row documents.HAS_PARTjoins a document to each of its sections, tables, figures and chunks. It has a start time and an end time. The edge is open while the node belongs to the current version of the document.HAS_CHILDgives the reading order.HAS_PARTsays which document version owns a node.NEXT_CHUNKjoins two neighbouring chunks of one document.MENTIONED_INjoins a chunk to each entity it mentions.- A schema relation joins two entities, for example
WORKED_WITH. Only the patterns that your schema allows can exist. MATCHESjoins two entities that the resolver matched. See Matching and resolved entities.RESOLVED_ASjoins an entity to its resolved entity.MEMBER_OFjoins an entity to its community.
Example
Take a note with two sentences about Ada Lovelace, Charles Babbage and the Analytical Engine. With DEFAULT_SCHEMA, one run writes the document, the section, the chunk, one entity node for each distinct person, place, product or event it finds, and a relation edge when the text states one of the eight relations. A schema for your domain gives the extractor more specific targets.
Design choices
Why are chunks nodes? A chunk node lets an answer cite its source. It also lets a search step from one chunk to its neighbours.
Why does HAS_PART have an end time instead of being deleted? A changed document closes its old edges and opens new ones. The old chunks stay as history. Search reads only open edges, so a removed document leaves retrieval at once.
Why does the resolver add a ResolvedEntity instead of merging entities? A match is a judgement. The original entity nodes stay, so a wrong match loses no information.
Why is the type the label? The type is what you filter and index by. A parent type is a label too, so a filter on Organization returns Vendor entities. Every Agentic GraphRAG node also carries an internal marker label, so Agentic GraphRAG can find its own nodes in a shared database.
Why does a chunk list its sections as a property and not as edges? A chunk can span several sections. It stores their ids in section_ids, so a reader can find them without a traversal. The Chunking page explains how a chunk records its sections.
Related
- Ingestion pipeline describes how the graph is written.
- Chunking describes how chunks are made.
- Update and delete documents shows how versions work.
- Common API lists the models.