Building GraphRAG Pipelines with Entity-Aware Chunking in Semantica: A Complete Architecture Guide

Semantica provides a graph-native RAG framework that uses entity-aware chunking to preserve named entities and relationships across text boundaries, enabling deterministic knowledge graph construction and auditable reasoning pipelines.

Semantica is an open-source AGI framework that moves beyond traditional embedding-only retrieval by treating documents as living knowledge graphs. The framework's GraphRAG pipeline leverages entity-aware chunking to ensure that named entities, semantic relationships, and ontology concepts remain intact during document segmentation. This approach guarantees that downstream graph construction maintains the true semantic structure of source documents, supporting deterministic reasoning and full audit trails.

Architecture of the GraphRAG Pipeline

The Semantica pipeline consists of seven distinct layers, each implemented as modular Python packages with clear separation of concerns.

Ingestion Layer

The ingestion layer supports multiple data sources through the semantica.ingest module. Classes like FileIngestor, WebIngestor, and DatabricksIngestor handle raw data acquisition from local files, web pages, and enterprise data platforms.

Source: [semantica/ingest/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/ingest/__init__.py)

Normalization and Entity-Aware Splitting

Text segmentation occurs in semantica.split, where the TextSplitter class implements entity-aware chunking. Unlike standard token-based splitters, this component uses NER-driven boundary detection to expand or contract chunk boundaries, preventing named entities from being split across segments.

Source: [semantica/split/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/split/__init__.py)

Semantic Extraction

The semantica.semantic_extract module provides NamedEntityRecognizer, RelationExtractor, and TripletExtractor classes. These components perform NER, relation extraction, and event detection with configurable confidence thresholds.

Source: [semantica/semantic_extract/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/semantic_extract/__init__.py)

Conflict Detection and Deduplication

Before graph insertion, the ConflictDetector and DuplicateDetector classes identify contradictory facts and resolve duplicate entities. This ensures the knowledge graph maintains internal consistency.

Source: [semantica/conflicts.py](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts.py)

Knowledge Graph Construction

The GraphBuilder class in semantica.kg constructs the context graph where entities, relationships, and decisions become first-class nodes. It supports bi-temporal fact handling and entity merging.

Source: [semantica/kg/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/kg/__init__.py)

Reasoning and Decision Intelligence

The reasoning layer includes ReteEngine for forward-chaining inference and ContextGraph.record_decision for auditable decision tracking. Every reasoning step generates provenance metadata that can be exported as PROV-O.

Source: [semantica/reasoning/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/reasoning/__init__.py) and [semantica/context/context_graph.py](https://github.com/semantica-agi/semantica/blob/main/semantica/context/context_graph.py)

Storage and Hybrid Retrieval

The VectorStore class provides a polyglot backend abstraction supporting FAISS, RDF triple stores, and labeled property graphs. The HybridSearch interface combines dense vector similarity with sparse graph traversal.

Source: [semantica/vector_store/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/vector_store/__init__.py)

How Entity-Aware Chunking Preserves Semantic Integrity

Traditional chunking strategies often split named entities (e.g., "New York City" or "Dr. Sarah Johnson") across boundaries, destroying relationship extraction accuracy. Semantica implements two complementary strategies to prevent this.

NER-Driven Boundary Detection

The TextSplitter class in [semantica/split/text_splitter.py](https://github.com/semantica-agi/semantica/blob/main/semantica/split/text_splitter.py) uses a configurable NER backend to locate entity spans before generating chunks. When a standard chunk boundary would intersect an entity, the splitter adjusts the boundary to keep the entity intact.

from semantica.split import TextSplitter

splitter = TextSplitter(
    method="entity_aware",
    chunk_size=1000,
    chunk_overlap=200
)
chunks = splitter.split(document_text)

This guarantees that downstream NamedEntityRecognizer instances see complete entities, which is essential for accurate relation extraction.

Relation-Aware Chunking for Triplets

For applications requiring complete semantic triplets, the RelationAwareChunker in [semantica/split/relation_aware_chunker.py](https://github.com/semantica-agi/semantica/blob/main/semantica/split/relation_aware_chunker.py) ensures that full (subject, predicate, object) structures remain within single chunks. This prevents partial relations from being fragmented during splitting, maintaining graph connectivity.

Implementing a Complete GraphRAG Pipeline

Semantica provides both declarative and imperative APIs for pipeline construction.

Declarative Pipeline Construction

Use the PipelineBuilder DSL to chain components with explicit data flow:

from semantica.pipeline import PipelineBuilder, ExecutionEngine

builder = PipelineBuilder()
builder.add_step("ingest", step_type="ingest", source="./data/")
builder.add_step("split", step_type="split", method="entity_aware")
builder.add_step("extract", step_type="ner_extract")
builder.add_step("kg", step_type="kg_build", merge_entities=True)
builder.add_step("dedup", step_type="deduplicate")
builder.add_step("export", step_type="export", format="turtle")

pipeline = (
    builder
    .connect_steps("ingest", "split")
    .connect_steps("split", "extract")
    .connect_steps("extract", "kg")
    .connect_steps("kg", "dedup")
    .connect_steps("dedup", "export")
    .set_parallelism(4)
    .build(name="graph_rag_pipeline")
)

engine = ExecutionEngine()
engine.execute_pipeline(pipeline)

Source: [semantica/pipeline/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/pipeline/__init__.py)

End-to-End Imperative Implementation

For fine-grained control, instantiate components directly:

from semantica.ingest import FileIngestor
from semantica.split import TextSplitter
from semantica.semantic_extract import NamedEntityRecognizer, RelationExtractor
from semantica.kg import GraphBuilder
from semantica.context import ContextGraph
from semantica.vector_store import VectorStore, HybridSearch
from semantica.visualization import KGVisualizer

# 1. Ingest documents

docs = FileIngestor().ingest_directory("./contracts/", recursive=True)

# 2. Entity-aware chunking

splitter = TextSplitter(method="entity_aware", chunk_size=1000, chunk_overlap=200)
chunks = [splitter.split(doc["text"]) for doc in docs]

# 3. Extract entities and relations

ner = NamedEntityRecognizer(confidence_threshold=0.7)
rel = RelationExtractor(confidence_threshold=0.6, bidirectional=True)

entities = [ner.extract_entities(chunk) for chunk_group in chunks for chunk in chunk_group]
relations = [rel.extract_relations(chunk, entities=entities) for chunk_group in chunks for chunk in chunk_group]

# 4. Build knowledge graph with deduplication

kg = GraphBuilder(merge_entities=True, enable_temporal=True).build(docs)

# 5. Store for hybrid retrieval

vs = VectorStore(backend="faiss", dimension=1536)
vs.store_kg(kg)

# 6. Hybrid search

results = HybridSearch(vector_store=vs).search("who approved the renewal?")

# 7. Visualize

KGVisualizer(layout="force").visualize_network(kg, output="interactive", file_path="kg.html")

Recording Decisions with Full Provenance

The ContextGraph class provides audit-ready decision tracking through the record_decision method, which creates immutable provenance chains.

from semantica.context import ContextGraph
from semantica.provenance import ProvenanceManager

graph = ContextGraph(advanced_analytics=True)
prov = ProvenanceManager(storage_path="./audit.db")

decision_id = graph.record_decision(
    category="vendor_selection",
    scenario="Choose cloud provider for HIPAA workload",
    reasoning="AWS offers BAA, mature HIPAA tooling, and existing team expertise",
    outcome="selected_aws",
    confidence=0.93,
)

prov.track_entity(
    entity_id="aws",
    source="vendor_comparison.xlsx",
    metadata={"page": 2, "extractor": "NamedEntityRecognizer"},
)

# Export to PROV-O/Turtle

from semantica.export import RDFExporter
RDFExporter().export(graph.to_kg_dict(), "audit_trail.ttl", format="turtle")

This implementation ensures every GraphRAG retrieval and reasoning step maintains a complete audit trail suitable for regulatory compliance.

Key Source Files and Implementation Details

Understanding the codebase structure is essential for customizing GraphRAG pipelines:

Summary

  • Entity-aware chunking preserves named entities and relationships during document segmentation by using NER-driven boundary detection in TextSplitter.
  • The GraphRAG pipeline consists of seven modular layers: ingestion, entity-aware splitting, semantic extraction, conflict resolution, knowledge graph construction, reasoning, and hybrid retrieval.
  • Semantica provides both declarative (PipelineBuilder) and imperative APIs for constructing production-grade RAG systems.
  • Decision provenance is implemented as first-class graph nodes via ContextGraph.record_decision, enabling complete audit trails exportable to PROV-O standards.
  • The framework supports polyglot storage (FAISS, RDF stores, LPGs) and hybrid search combining vector similarity with graph traversal.

Frequently Asked Questions

What is entity-aware chunking in GraphRAG?

Entity-aware chunking is a document segmentation strategy that uses named entity recognition to adjust chunk boundaries, ensuring that entities like "New York City" or "Dr. Sarah Johnson" remain intact within single chunks. In Semantica, this is implemented in the TextSplitter class with method="entity_aware", which prevents relationship fragmentation and improves downstream knowledge graph accuracy.

How does Semantica handle conflicting entities during graph construction?

The framework uses the ConflictDetector and DuplicateDetector classes (located in [semantica/conflicts.py](https://github.com/semantica-agi/semantica/blob/main/semantica/conflicts.py)) to identify contradictory facts and resolve duplicates before graph insertion. The GraphBuilder class can merge entities and handle bi-temporal facts to maintain internal consistency.

Can Semantica export knowledge graphs to standard RDF formats?

Yes, the RDFExporter class in [semantica/export/__init__.py](https://github.com/semantica-agi/semantica/blob/main/semantica/export/__init__.py) supports export to Turtle, RDF/XML, and JSON-LD formats. The ContextGraph.to_kg_dict() method serializes the entire graph including provenance metadata into standards-compliant RDF.

The VectorStore abstraction supports multiple backends including FAISS for dense vector search, RDF triple stores for semantic queries, and labeled property graphs (LPGs). The HybridSearch class combines these with sparse retrieval signals for comprehensive GraphRAG retrieval.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →