Knowledge Graph Construction from Unstructured Data: Building the Pipeline
Why Construction Is the Hard Part
Knowledge graphs are only as valuable as the data they contain. Querying, visualising, and reasoning over a graph are well-understood problems — but the hardest engineering challenge remains the first mile: how do you populate a knowledge graph from raw, unstructured text?
Most enterprises sit on terabytes of documents — PDFs, emails, internal wikis, support tickets, news articles — all containing entities and relationships that never make it into a structured database. Extracting that structure at scale is the critical bottleneck.
This article walks through the end-to-end pipeline for constructing a knowledge graph from unstructured text, from document ingestion through entity extraction, relationship inference, entity resolution, and graph population. We compare traditional NLP approaches with modern LLM-based pipelines and give you a decision framework for when each makes sense.
The Pipeline at a Glance
A production knowledge graph construction pipeline has six stages:
- Document Ingestion — Parse PDFs, HTML, Markdown, and plain text into standardised chunks
- Entity Extraction — Identify entities (people, organisations, concepts, products) in each chunk
- Relationship Inference — Determine how entities relate to one another
- Entity Resolution — Deduplicate: merge "Apple Inc." and "Apple Computer Company" into a single node
- Graph Population — Write nodes, relationships, and properties to Neo4j (or your graph database of choice)
- Quality Assurance — Validate against schema constraints, measure precision and recall
Each stage introduces design decisions that ripple through the entire pipeline. Let us examine each in turn.
1. Document Ingestion
The ingestion layer normalises diverse input formats into a uniform representation. A common pattern stores each document as a :Document node with its text content, metadata, and chunked passages as :ContentChunk children:
(:Document {title, source, date})-[:CONTAINS]->(:ContentChunk {text, index})
Chunking strategy matters. Overlapping chunks with sentence boundaries (not fixed token counts) preserve entity context across chunks, which is especially important when entities span paragraph breaks. A sliding window of 256 tokens with 32-token overlap strikes a good balance for most domains.
2. Entity Extraction
Entity extraction is where most engineering effort concentrates. Two approaches dominate in 2026:
Traditional NER Pipelines
Fine-tuned NER models (SpaCy, GLiNER, or BERT-based) offer fast, cheap extraction for well-defined entity types:
import spacy
nlp = spacy.load("en_core_web_trf")
doc = nlp("Neo4j announced GraphRAG support at GraphSummit London.")
for ent in doc.ents:
print(f"{ent.text} -> {ent.label_}")
# Neo4j -> ORG
# GraphRAG -> PRODUCT
# GraphSummit London -> EVENT
Traditional NER excels at precision for fixed types (Person, Organisation, Location) but struggles with domain-specific entities — API names, CVE identifiers, product versions — without costly fine-tuning.
LLM-Based Extraction
LLMs can extract arbitrary entity types from any domain without fine-tuning:
import openai
def extract_entities(text: str, entity_types: list[str]) -> list[dict]:
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": f"Extract JSON entities: {entity_types}"
}, {
"role": "user",
"content": text
}]
)
return json.loads(response.choices[0].message.content)
The trade-off is cost and latency — LLM-based extraction is 10–100× more expensive per entity than traditional NER. The pragmatic approach is a hybrid pipeline: use traditional NER for high-volume standard entities and route only ambiguous or domain-specific cases to an LLM.
3. Relationship Inference
Once entities are extracted, you need edges between them. Three common strategies offer different trade-offs:
| Strategy | Approach | Precision | Recall | Cost |
|---|---|---|---|---|
| Co-occurrence | Entities in same sentence → edge | Low | High | Free |
| Dependency parsing | Subject-verb-object extraction | Medium | Medium | Low |
| LLM prompting | Extract relationships explicitly | High | High | High |
Co-occurrence is the simplest heuristic: if two entities appear in the same sentence, create an edge. This produces dense graphs with high recall but low precision — most co-occurring entities are related in the broadest sense but not in a semantically meaningful way.
Dependency parsing uses grammatical structure to extract subject-verb-object triples from each sentence. For "Neo4j acquired a startup," dependency parsing identifies Neo4j as the subject, acquired as the verb, and startup as the object, yielding (:Entity {name: "Neo4j"})-[:ACQUIRED]->(:Entity {name: "startup"}).
LLM-based extraction produces the highest-quality relationships but at the highest cost. A sensible middle ground: use dependency parsing as a first pass, then task an LLM with validating and refining only the extracted triples that fall below a confidence threshold.
4. Entity Resolution
Entity resolution — also called deduplication or record linkage — is the most underestimated component of KG construction. A graph built without deduplication quickly becomes unusable as the same real-world entity accrues multiple nodes with slight name variations.
Resolution techniques ranked by sophistication:
- Exact string match — Catches duplicates with identical names. Covers roughly 30% of real-world duplicates.
- Fuzzy string matching — Levenshtein or Jaro-Winkler distance for near-misses like "Google Inc." versus "Google Incorporated."
- Blocking plus similarity scoring — Group candidates by a blocking key (first three characters, date range) then score with TF-IDF or embedding cosine similarity.
- LLM-based resolution — Prompt the model with "Are these two entities the same?" and supporting evidence.
In production, a rule-based blocker followed by an embedding similarity scorer with a tunable threshold captures 90% or more of duplicates at acceptable latency.
5. Graph Population
With entities resolved and relationships inferred, you load the graph into Neo4j. Use periodic batching with MERGE to avoid duplicating nodes:
:auto USING PERIODIC COMMIT 500
LOAD CSV FROM 'file:///entities.csv' AS row
MERGE (e:Entity {id: row.id})
ON CREATE SET e.name = row.name,
e.type = row.type,
e.source = row.source
For relationships, batch via UNWIND:
UNWIND $relationships AS rel
MATCH (a:Entity {id: rel.source_id})
MATCH (b:Entity {id: rel.target_id})
MERGE (a)-[r:HAS_RELATIONSHIP {type: rel.type}]->(b)
SET r.confidence = rel.confidence,
r.evidence = rel.evidence
Always store a confidence score and evidence trace (source document ID, sentence) on each relationship. These enable downstream quality filtering and auditability — critical for the regulated use cases discussed in Knowledge Graphs Are the Antidote to AI Hallucination Liability.
6. Quality Assurance
A pipeline without QA metrics is one that silently degrades. Track these four signals:
- Entity precision and recall against a held-out gold set
- Relationship validity — sample 100 edges and manually label correct versus incorrect
- Graph density — unexpected density spikes indicate over-extraction
- Schema compliance — every node has required properties, every edge conforms to expected types
For ontology-aware validation, apply the principles from Ontology in Graph Databases: your construction pipeline should honour the node labels, property constraints, and relationship types defined by your ontology. When the pipeline produces a node that does not match the schema, it should either be transformed or flagged for review.
Which Approach Should You Choose?
| Factor | Traditional NLP | LLM-Based | Hybrid |
|---|---|---|---|
| Entity coverage | Limited to trained types | Unlimited | Both |
| Per-entity cost | Pennies per million | Cents per hundred | Tiered |
| Latency | Milliseconds | Seconds | Configurable |
| Precision | High (known types) | High (good prompts) | High |
| Recall | Low (misses domain entities) | High | High |
| Setup complexity | Fine-tuning pipeline | Prompt engineering | Both |
For most production KG construction workloads in 2026, the hybrid approach wins: fast traditional NER for high-volume standard entities, LLM-based extraction for domain-specific concepts and complex relationship inference, and a rule-based entity resolution layer that keeps the graph clean.
Putting It All Together
Building a knowledge graph from unstructured data is not a one-shot ETL job — it is an iterative process that improves as you add better extraction models, refine your ontology, and accumulate more training data for entity resolution. Start with a simple pipeline (co-occurrence plus exact match), measure quality, then layer in sophistication where the quality gap is widest.
For a deeper dive into the ontology design that your construction pipeline should target, see Ontology in Graph Databases. And for how the finished graph powers AI applications, read Neo4j + AI: Building Intelligent Applications.