# How to Build Knowledge Graphs from Multiple Data Sources Using Semantica

> Learn how to build knowledge graphs from multiple data sources with Semantica. Effortlessly merge entities and resolve conflicts for unified insights.

- Repository: [Semantica /semantica](https://github.com/semantica-agi/semantica)
- Tags: how-to-guide
- Published: 2026-08-18

---

**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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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:

```python

# 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:

```python

# 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:

```python

# 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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/semantica/semantic_extract/relation_extractor.py) and [`semantica/semantic_extract/triplet_extractor.py`](https://github.com/semantica-agi/semantica/blob/main/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`](https://github.com/semantica-agi/semantica/blob/main/semantica/kg/graph_builder.py), enable time-travel queries and audit trails by filtering entities and relationships based on temporal validity periods.