How to Build Knowledge Graphs from Multiple Data Sources Using Semantica

To build knowledge graphs from multiple data sources using Semantica, instantiate the GraphBuilder class with merge_entities=True and resolve_conflicts=True, then pass a list of heterogeneous sources—raw text, JSON dictionaries, or file paths—to the build() method, which normalizes inputs, extracts entities, resolves duplicates, and detects conflicts automatically.

The semantica-agi/semantica repository provides a comprehensive framework for knowledge graph construction. Its central component, the GraphBuilder class located in semantica/kg/graph_builder.py, orchestrates the ingestion of heterogeneous data formats into a unified, queryable knowledge graph. This guide demonstrates how to leverage the builder's pipeline to integrate PDFs, web data, ontologies, and raw text into a coherent temporal graph structure.

Understanding the GraphBuilder Pipeline Architecture

The GraphBuilder implements a seven-stage pipeline for knowledge graph construction. Each stage handles specific concerns, from input normalization to persistent storage, allowing developers to process diverse data sources through a single interface.

When you invoke the build() method, the component automatically detects source types and applies the appropriate extraction and transformation logic. The pipeline supports optional entity resolution, conflict detection, and temporal versioning, making it suitable for production-grade knowledge management systems.

Normalizing Heterogeneous Input Sources

Before extraction begins, GraphBuilder._normalize_graph standardizes all inputs into a canonical dictionary structure containing entities, relationships, and optional metadata fields. This normalization accepts single sources, lists of sources, or dictionaries with pre-extracted graph fragments.

According to the implementation in semantica/visualization/kg_visualizer.py, the builder handles raw text strings, pre-extracted entity dictionaries, relationship mappings, and file references (JSON, CSV) seamlessly. This ensures that whether you ingest a PDF paragraph or a structured API response, the data conforms to the internal graph schema before processing continues.

Extracting Entities and Relationships from Raw Text

For unstructured text inputs, the builder triggers local extraction pipelines via _extract_from_text in semantica/kg/graph_builder.py. You control extraction behavior through boolean flags and method selectors:

  • extract: Enable named entity recognition (NER)
  • extract_relations: Extract binary relationships between entities
  • extract_triplets: Extract subject-predicate-object triplets
  • ner_method: Choose between "ml" (local ML model), "pattern", or "llm" backends
  • relation_method and triplet_method: Configure respective extraction backends

When ner_method="ml", the builder utilizes semantica/semantic_extract/ner_extractor.py for local processing without requiring external API keys.

Entity Resolution and Conflict Handling

Two critical features ensure graph integrity when merging multiple sources: entity resolution and conflict detection.

Entity Resolution: Setting merge_entities=True instantiates an EntityResolver (defaults to fuzzy matching) from semantica/kgraph/entity_resolver.py. This component deduplicates entities across sources, and _remap_relationship_endpoints updates relationship source/target IDs to reference the canonical entity identifiers.

Conflict Detection: With resolve_conflicts=True, the builder invokes ConflictDetector from semantica/conflicts/conflict_detector.py to identify contradictory facts. The system flags inconsistencies between sources, enabling automated or manual resolution strategies.

Implementing Temporal Knowledge Graphs

Semantica supports time-bound graph semantics through explicit temporal methods. After building the initial graph, you can augment it with temporal edges or create historical snapshots:

  • add_temporal_edge: Creates time-valid relationships between entities with valid_from and valid_until timestamps
  • create_temporal_snapshot: Generates a point-in-time view of the graph, useful for historical analysis or audit trails

These methods, implemented in semantica/kg/graph_builder.py, allow you to model entity states and relationship evolution over time.

Complete Implementation Example

The following implementation demonstrates ingesting PDF text, pre-extracted JSON, and ontology fragments into a unified knowledge graph:


# 1️⃣  Initialise the builder – enable merging and conflict handling

from semantica.kg import GraphBuilder
builder = GraphBuilder(merge_entities=True, resolve_conflicts=True)

# 2️⃣  Prepare heterogeneous sources

pdf_text = "The Lattice‑A2 radar covers low‑altitude threats."
web_json = {
    "entities": [{"id": "radar_1", "name": "Lattice‑A2", "type": "system"}],
    "relationships": []
}
ontology_file = {"entities": [], "relationships": []}      # could be loaded via ingest_ontology

sources = [
    {"text": pdf_text},                 # raw text – will be extracted

    web_json,                           # pre‑extracted dict

    ontology_file                       # already‑structured graph fragment

]

# 3️⃣  Build the KG (the builder will extract from text, resolve duplicates,

#    and run conflict detection automatically)

kg = builder.build(
    sources,
    extract=True,                     # run NER on raw strings

    extract_relations=False,
    extract_triplets=True,
    ner_method="ml",                  # local ML model (no API key needed)

)

print("Entities:", len(kg["entities"]))
print("Relationships:", len(kg["relationships"]))

To add temporal context to specific relationships:


# 4️⃣  Adding a temporal edge manually

from datetime import datetime, timezone
builder.add_temporal_edge(
    kg,
    source="radar_1",
    target="mission_42",
    relationship="SUPPORTS",
    valid_from=datetime(2025, 1, 1, tzinfo=timezone.utc),
    valid_until=None,
)

For historical analysis, generate temporal snapshots:


# 5️⃣  Creating a snapshot for a specific date

snapshot = builder.create_temporal_snapshot(
    kg,
    timestamp="2025-06-01T00:00:00Z",
    snapshot_name="mid‑2025"
)
print("Snapshot contains", len(snapshot["entities"]), "entities")

Summary

  • Instantiate GraphBuilder from semantica/kg/graph_builder.py with merge_entities=True and resolve_conflicts=True to enable entity deduplication and contradiction detection.
  • Normalize inputs through _normalize_graph, which converts raw text, JSON, CSV, and dictionaries into a canonical graph structure.
  • Extract entities using local ML models by setting extract=True and ner_method="ml", eliminating external API dependencies.
  • Resolve conflicts automatically using the ConflictDetector class when resolve_conflicts=True is enabled.
  • Add temporal dimensions with add_temporal_edge and create_temporal_snapshot to model time-bound relationships and historical graph states.
  • Track progress throughout the pipeline using the internal ProgressTracker and logging mechanisms.

Frequently Asked Questions

What data formats does Semantica's GraphBuilder support?

The GraphBuilder accepts raw text strings, Python dictionaries containing entities and relationships keys, and file paths to JSON or CSV documents. The _normalize_graph method in semantica/visualization/kg_visualizer.py handles format detection and conversion to the internal canonical structure, enabling seamless integration of PDF-extracted text, API responses, and ontology files within a single build() call.

How does entity resolution work when merging multiple sources?

When merge_entities=True is passed to the constructor, the builder instantiates an EntityResolver that applies fuzzy matching algorithms to identify duplicate entities across sources. After resolution, the _remap_relationship_endpoints method updates all relationship source and target IDs to reference the canonical entity identifiers, ensuring graph consistency even when different sources use varying names or identifiers for the same real-world entity.

Can I build knowledge graphs without using external LLM APIs?

Yes. Set ner_method="ml", relation_method="pattern", or triplet_method="pattern" to use local extraction backends. The semantica/semantic_extract/ner_extractor.py module provides a local ML-based NER implementation that requires no API keys, while pattern-based methods in semantica/semantic_extract/relation_extractor.py and semantica/semantic_extract/triplet_extractor.py apply rule-based extraction for offline processing.

How do I handle temporal data and graph versioning?

Use the add_temporal_edge method to create relationships with explicit valid_from and valid_until timestamps. For historical analysis, call create_temporal_snapshot with an ISO timestamp to generate a point-in-time view of the graph. These methods, implemented in semantica/kg/graph_builder.py, enable time-travel queries and audit trails by filtering entities and relationships based on temporal validity periods.

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 →