How Semantica's EntityLinker Resolves Entities Across Multiple Data Sources
Semantica's EntityLinker normalizes disparate identifiers from documents, APIs, and knowledge graphs into stable URIs and connects them via lexical similarity, explicit context relationships, and knowledge-graph lookups to create a unified, queryable entity web.
The EntityLinker class in the semantica-agi/semantica repository serves as the central component for entity resolution across heterogeneous data sources. It transforms fragmented entity mentions into a coherent knowledge graph by assigning canonical identifiers and discovering relationships across documents, external APIs, and knowledge-graph stores.
URI Assignment and Normalization
Every incoming entity receives a stable, globally-unique identifier through the URI generation pipeline implemented in semantica/context/entity_linker.py (lines 46‑82).
If the entity has a readable label, the linker generates a URL-safe string derived from that label using quote(entity_text…). When no label is available, the system generates a deterministic MD5 hash of the entity ID. An optional type fragment (#type) is appended to produce canonical URIs such as https://semantica.dev/entity/python#programming_language. The mapping entity_id → uri is maintained in self.entity_registry, ensuring consistent identifier resolution across all subsequent operations.
Cross-Source Linking Strategies
The linker discovers relationships between the current entity and all other sources through three complementary mechanisms.
Knowledge-Graph Similarity Matching
When a knowledge graph is supplied via self.knowledge_graph, the linker scans its entities list and computes a lightweight word-overlap similarity using _calculate_text_similarity. Entities whose similarity exceeds the configurable similarity_threshold (default 0.8) are converted into EntityLink objects with a same_as or related_to type depending on the score (lines 331‑349).
Contextual Relationship Extraction
When a context argument is supplied, the linker extracts explicit source_id → target_id relations from each context block. It creates corresponding EntityLink objects that preserve the original relationship type and confidence scores, enabling the integration of pre-defined ontologies or manual annotations (lines 511‑538).
Bidirectional Symmetry Enforcement
For symmetric link types such as related_to and same_as, the linker automatically inserts a reverse link to ensure the entity graph remains navigable in both directions. This bidirectional symmetry prevents orphaned entities and supports graph traversal operations regardless of the initial linking direction (lines 311‑327).
Entity Web Construction
After collecting all links, the build_entity_web() method aggregates them into a unified data structure (lines 506‑531). This structure contains:
- A flat map of
entity_id → {uri, link_count} - A list of link records with
source,target,type, andconfidencefields - Basic statistics including total entities and total links
The resulting dictionary can be exported, visualized, or queried further by downstream components.
Resolution APIs for Multi-Source Queries
The linker exposes several convenience methods that enable downstream components to resolve entities regardless of their originating source:
get_entity_uri(entity_id)– Fetches the canonical URI for any registered entityresolve_uri(uri)– Reverses the mapping, returning the full entity record from the knowledge graph if presentfind_similar(entity, threshold)– Wraps the similarity engine for ad-hoc queries against the knowledge graphfind_related(entity_id, max_hops)– Traverses the built web up to a configurable hop distance, aggregating related entities across all integrated sources
Practical Implementation Example
# Initialise the linker with an optional knowledge graph
from semantica.context import EntityLinker
kg = {
"entities": [
{"id": "e1", "text": "Python", "type": "PROGRAMMING_LANGUAGE"},
{"id": "e2", "text": "Py", "type": "PROGRAMMING_LANGUAGE"},
],
"nodes": [], # optional for advanced lookup
}
linker = EntityLinker(knowledge_graph=kg, similarity_threshold=0.75)
# 1. Assign a stable URI
uri = linker.assign_uri("e1", "Python", "PROGRAMMING_LANGUAGE")
print(uri) # → https://semantica.dev/entity/python#programming_language
# 2. Link a piece of text (cross‑document linking)
text = "Python is widely used for data science."
entities = [{"id": "e1", "text": "Python", "type": "PROGRAMMING_LANGUAGE"}]
linked = linker.link_text(text, entities)
print(linked[0].linked_entities) # → EntityLink(same_as) to "e2" (similarity ≈ 0.86)
# 3. Resolve a URI back to its graph record
record = linker.resolve_uri(uri)
print(record) # → {'entity_id': 'e1', 'uri': uri, 'text': 'Python', ...}
# 4. Retrieve the full entity web for export / visualisation
entity_web = linker.build_entity_web()
print(entity_web["statistics"])
# → {'total_entities': 2, 'total_links': 2}
Summary
- Source-agnostic normalization: The
EntityLinkerconverts disparate identifiers into a single URI namespace using URL-safe labels or MD5 hashes, stored inself.entity_registry. - Multi-factor linking: Entities are connected via lexical similarity matching against knowledge graphs, explicit context relationships, and bidirectional symmetry enforcement.
- Unified entity web: The
build_entity_web()method aggregates all connections into a queryable structure with full provenance tracking viaEntityLinkobjects. - Cross-source resolution: Methods like
resolve_uri()andfind_related()enable seamless traversal of entities regardless of their original data source.
Frequently Asked Questions
How does EntityLinker handle entities without readable labels?
When an entity lacks a readable label, the linker generates a deterministic MD5 hash of the entity ID to create the URI suffix. This ensures every entity receives a stable identifier even when textual descriptions are unavailable, as implemented in the URI assignment logic at lines 46‑82 of semantica/context/entity_linker.py.
What similarity threshold should I use for cross-source linking?
The default similarity_threshold is 0.8, which provides conservative matching suitable for high-precision entity linking. You can adjust this parameter during initialization (e.g., EntityLinker(similarity_threshold=0.75)) to balance precision and recall based on your specific domain's lexical variability.
How does the linker maintain consistency between related entities?
The linker enforces bidirectional symmetry for relationship types like same_as and related_to by automatically inserting reverse links during the linking phase (lines 311‑327). This ensures that if entity A links to entity B, entity B is immediately queryable as related to entity A, maintaining graph consistency.
Can EntityLinker resolve entities across more than two data sources simultaneously?
Yes, the linker is designed to integrate any number of data sources including documents, knowledge-graph stores, and external APIs. The build_entity_web() method aggregates links from all processed contexts and knowledge graphs into a single unified structure, enabling multi-hop traversal across heterogeneous sources via find_related().
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →