← Back to list

Part 5: Extracting Ontology-Compliant Knowledge Graphs from Sources

A series of articles on semantic foundations for goal-directed intelligence: Table of Content

Yuan An, PhD · 2026-07-01 03:28 · 2 claps · 16.6 min read paywalled
#knowlege-graph-extraction #ontology-knowlege-graph #knowledge-graph #map-triples-to-ontology #verify-triples-semantics
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval PHI · Philosophy LNG · Linguistics & Language

Part 5: Extracting Ontology-Compliant Knowledge Graphs from Sources

A series of articles on semantic foundations for goal-directed intelligence: Table of Content

What you will learn

  • Understand the distinction between building a T-Box (Article 4) and populating it with A-Box individuals (this article).
  • Walk Stage 1: run a spaCy pass and a batched LLM pass over source text to surface entity mentions and raw triples, then merge both into normalized candidate triples, with negated triples tracked explicitly.
  • Walk Stage 2: map each candidate triple’s surface subject, predicate, and object onto ontology IRIs or typed literals through a three-step cascade of embedding lookup and LLM fallback, with inverse-predicate detection handled automatically.
  • Walk Stage 3: sort mapped triples by confidence, then run domain, range, disjointness, and cardinality checks in sequence; repair datatype mismatches where possible; emit deduplicated rdf:type assertions for all admitted individuals.
  • See how the confidence sort guarantees deterministic conflict resolution: the higher-confidence triple wins without backtracking.
  • Apply the full pipeline to an incident report and produce an ontology-compliant SCIMA A-Box with zero schema violations.

1. From schema to instances: what this article does

Article 4 produced SCIMA-OWL v0.6: a T-Box of classes, properties, and axioms extracted from source documents. scima:IncidentCommander is a class; a specific commander dispatched to a specific spill is an individual that instantiates that class.

This article fills the A-Box. The pipeline takes a source text and a given ontology file, reads the ontology as a fixed contract, and produces ontology-compliant individuals: typed entities linked by properties declared in the schema.

The core challenge is that source text is free-form. It uses surface predicates (“commands”, “was dispatched to”, “received”) that must be matched to ontology properties. It names individuals informally (“Commander Diaz”, “the IC”, “the hazmat crew”) that must be typed against ontology classes and minted as stable IRIs. It expresses relationships in either direction (active and passive voice). And it sometimes negates facts explicitly (“did not command”), which must be tracked rather than silently dropped.

Three sequential stages solve this. Stage 1 is fully open and recall-first: it extracts entity mentions and raw triples without consulting the ontology. Stage 2 maps each candidate triple’s surface terms onto ontology IRIs using a cascade of embedding similarity and LLM fallback. Stage 3 verifies each mapped triple against the ontology’s structural constraints and admits, repairs, or rejects it.

2. The three-stage pipeline at a glance

Figure 1. The three-stage pipeline. Stage 1 runs over source text with no ontology consultation. Stage 2 reads the ontology once at entry, pre-computes an index, and maps each candidate triple onto ontology IRIs. Stage 3 reads the pre-computed index (not the raw ontology file) and verifies each mapped triple against structural constraints. The ontology feeds only Stages 2 and 3 and is never modified.

3. Stage 1: Extract

Stage 1 runs over the full source text. Its job is recall: surface every entity mention and every value mention, generate raw triples from two complementary extractors, and merge both streams into a unified candidate set. Nothing is dropped at this stage except explicitly negated triples, which are quarantined in a separate file rather than deleted.

The spaCy pass

One spaCy run over the full text performs four jobs simultaneously. Named entity recognition tags spans with entity types: the NER types PERSON, ORG, GPE, EVENT, and similar types produce mention_type: entity; CARDINAL, QUANTITY, DATE, TIME, and MONEY produce mention_type: value. Noun-phrase chunking catches multi-word conceptual phrases that NER misses, defaulting to mention_type: entity. Sentence segmentation produces _sentences.json, the index that both the LLM pass and Stage 2 refer back to by sentence index. Dependency parsing extracts one structural triple per sentence: the (subject, root-verb, direct-object) pattern. A negation check walks the dependency tree for any child of the root verb with dep_ == "neg"; if found, the triple is marked negated: true.

The LLM pass

The LLM pass iterates over _sentences.json in batches of five to ten sentences. Each batch is one LLM call with this prompt:

For each sentence below, perform two tasks:
1. Extract all entity and value mentions. Classify each as entity (a named thing,
   a type, a category, an event) or value (a number, measurement, date, string literal).
   Keep unit strings together with their number as one surface form (e.g., "47 psi").
2. Extract all (subject, predicate, object) triples readable from the sentence,
   using only the entities and values identified in task 1. Be open and thorough.
   Do not filter by any schema. If a sentence negates a relationship, include
   the triple but set negated: true. Do not silently omit negated triples.

Return results keyed by sentence index.

The batched LLM prompt. Task 1 produces entity mentions; Task 2 produces raw triples. Both are returned per sentence index so the pipeline can join them back to the sentence text from _sentences.json.

Entity mention merge

After both passes, mentions from NER, noun-phrase chunking, and the LLM are merged on normalized surface form (lowercase, whitespace-stripped). Each unique surface form becomes one record in _entity_mentions.json carrying the union of all source tags and the set of sentence indices where it appeared. The mention_type field resolves by priority: the LLM classification wins when sources disagree. If the LLM tags a mention as entity, that overrides a spaCy CARDINAL or DATE tag, because spaCy commonly mislabels proper names and compound identifiers as numeric types. If the LLM did not surface the mention at all, the spaCy tag stands unchallenged.

Triple merge

Dependency-parse triples and LLM triples are combined into a single candidate set. Normalization is asymmetric: subjects and objects are normalized by lowercase and whitespace-collapse only (lemmatization would distort named entities and multi-word identifiers), while predicates are normalized by lowercase plus lemmatization (predicates are verbs or verb phrases where lemmatization is well-defined). Duplicates across sources are merged into one record carrying a sources field with both tags.

When the same surface triple appears in multiple sentences, all sentence indices are collected into sentence_indices and the lowest index is recorded as sentence_index for Stage 2's context lookup. The object_type field is inherited from _entity_mentions.json and is nullable: objects that neither extractor surfaced as named mentions simply carry no object_type, and Stage 2 handles the absent case by letting the predicate kind determine the mapping path.

A triple is marked negated: true if either source marked it negated. The negated flag from one source overrides a positive result from the other, preventing a missed negation in one extractor from laundering a negated fact into the candidate set. After merge, negated triples are excluded from _candidate_triples.json and written to _negated_triples.json instead.

Figure 2. Stage 1 in detail. The spaCy pass and LLM pass run independently over the same text. Their entity mentions feed the mention merge (green): one record per normalized surface form, with the LLM’s mention_type winning on conflict. Their raw triples feed the triple merge (amber): duplicates collapse into single records with combined sources fields. Triples marked negated by either source are quarantined in _negated_triples.json (red) rather than dropped.

4. Stage 2: Map onto the ontology

Stage 2 reads the ontology file once at entry and pre-computes a structured index covering: the class list with labels and annotations; the property list with labels, domain, range, kind (object_property or datatype_property), and declared inverses; the subclass closure; disjointness pairs; and per-property functional, inverse-functional, and maximum-cardinality flags. This index is written to _ontology_index.json so Stage 3 reads it directly without re-parsing the ontology.

Then, for every candidate triple, Stage 2 runs three sub-steps in sequence: subject typing, predicate mapping, and object mapping. Each sub-step has a three-tier cascade: fast string or embedding lookup, then LLM fallback. A triple is dropped the moment any sub-step fails to find a mapping.

Subject typing

The surface subject is normalized into a slug (lowercase, non-alphanumeric characters replaced by underscores, consecutive underscores collapsed). The slug is used to mint the IRI: <namespace><ClassName>_<slug>. A minted IRI registry tracks every (class_iri, slug) pair: repeated mentions of the same entity reuse the existing IRI; collisions between distinct surface forms that produce the same slug are disambiguated by appending an incrementing counter.

Typing uses a two-tier cascade. The surface form and its sentence are concatenated as "[surface form] - [sentence text]" and an embedding cosine is computed against each class label. If the top score exceeds the threshold, the class is assigned and the component confidence is recorded as high. If no class exceeds the threshold, the LLM is invoked with the surface form, its sentence, and the full class list; if the LLM assigns a class, the component confidence is low. If the LLM also fails, the triple is dropped.

Predicate mapping

Every property in the ontology index carries two label sets: its own direct labels and aliases, and the labels of its declared inverse (the owl:inverseOf partner, if any). The cascade searches both sets at each tier.

Tier 1: lemma-match and string-match the surface predicate against all direct and inverse labels. Tier 2: concatenate the surface predicate and sentence and run embedding cosine over the full property list using both label sets. Tier 3: invoke the LLM with the surface predicate, its sentence, and the property list, asking which property the surface predicate maps to and whether the match is direct or inverse.

A direct match assigns predicate_iri to the matched property with no flag. An inverse match assigns predicate_iri to the forward property and sets inverted: true. When both a direct and inverse match occur at the same tier, the direct match wins. The mapped predicate carries its predicate_kind (object_property or datatype_property) from the ontology; this is the authoritative guide for the object mapping step.

Object mapping

The predicate kind determines the mapping path unconditionally. Stage 1’s object_type field is a consistency signal only; the predicate kind overrides it when they conflict.

  • Predicate is object_property: the object is treated as a class instance. The same two-tier embedding-then-LLM cascade as subject typing is applied. On success, an IRI is minted using the same registry. On failure, the triple is dropped.
  • Predicate is datatype_property: the object is parsed as a literal. Unit strings such as "47 psi" are split into numeric value 47 and unit annotation psi. The datatype is inferred from the surface form (integer, float, date, or string). If the surface form cannot be parsed, the triple is dropped.

Triple inversion

When predicate mapping set inverted: true, the grammatical subject and object are in the wrong positions for the forward property: the text expressed the relationship in passive or reversed form. After both subject typing and object mapping complete, the two typed positions are swapped. The swap is safe at this point because both ends are fully typed: subject typing resolved the grammatical subject and object mapping resolved the grammatical object. After the swap, domain and range checks in Stage 3 run against the corrected positions. The inverted flag is consumed here and not written to _mapped_triples.json.

Confidence aggregation

Each triple’s overall mapping_confidence is the minimum of its three component confidences (subject typing, predicate mapping, object typing or parsing). A triple earns high overall confidence only if every sub-step scored high; one LLM fallback anywhere drops the overall to low. This field flows into Stage 3's sort.

Figure 3. Stage 2 mapping cascade for the candidate triple (Commander Diaz, commands, HazmatTeam Alpha). Each sub-step runs its own tier cascade. Here all three hit on the first tier (embedding and string match), so all component confidences are high and the aggregated mapping_confidence is high. The predicate matched directly, so no inversion is applied.

5. Stage 3: Verify and admit

Stage 3 reads _mapped_triples.json and _ontology_index.json. The ontology is not re-parsed here. The stage runs five checks on each triple, stopping at the first failure. It maintains three pieces of running state across all triples: the admitted type set, the cardinality counter, and the inverse-functional tracker.

Pre-processing: sort by confidence

Before any checks run, all mapped triples are sorted descending by a three-level key so that when two triples conflict on disjointness or cardinality, the higher-confidence triple is processed first and wins. The sort ensures deterministic outcomes without backtracking.

Check 1: Domain

Is the subject’s assigned type a subclass of the property’s declared domain, using the pre-computed subclass closure? If the ontology declares no domain for the property, the check passes unconditionally (OWL open-world: an absent domain places no restriction). On failure: verdict: reject, reason: domain_violation.

Check 2: Range (object property)

If predicate_kind: object_property: is the object's assigned type a subclass of the declared range? An absent range passes unconditionally. On failure: verdict: reject, reason: range_violation.

Check 3: Range and repair (datatype property)

If predicate_kind: datatype_property: is the object literal's datatype compatible with the declared range datatype? On mismatch, a repair is attempted: cast the literal to the declared datatype (for example, a string "47" to xsd:integer 47, or "true" to xsd:boolean). If the cast succeeds: verdict: repaired, carrying the corrected datatype into the admitted set. If the cast fails: verdict: reject, reason: datatype_mismatch.

Check 4: Disjointness

Would typing the subject or object in this triple, combined with typings already in the admitted type set, violate any owl:disjointWith axiom from the ontology index? Because triples are sorted by confidence before processing, the higher-confidence triple was already admitted and its typing is already in the running set. The lower-confidence conflicting triple is the one rejected. On failure: verdict: reject, reason: disjointness_violation.

This is a greedy one-pass algorithm. When confidence is fully tied, the sentence-index tiebreaker makes the outcome deterministic, but it does not guarantee a globally optimal assignment.

Check 5: Cardinality

Two sub-checks run in order.

5a (functional / max-cardinality, subject side): if the property is declared owl:FunctionalProperty, or carries owl:maxCardinality N or owl:exactCardinality N for the subject's class, count already-admitted triples with the same (subject_iri, predicate_iri) pair in the cardinality counter. If that count equals the allowed maximum, reject.

5b (inverse-functional, object side): if the property is declared owl:InverseFunctionalProperty, check whether the inverse-functional tracker already contains any triple with the same (predicate_iri, object_iri) but a different subject_iri. If so, reject.

On failure: verdict: reject, reason: cardinality_violation. Lower-bound constraints (owl:minCardinality) are not checked: a KG extracted from text is inherently partial, and a missing triple reflects text coverage, not a constraint violation.

Admission and running-state update

After each admit or repaired verdict, three running-state updates happen: the subject and object type assertions are added to the admitted type set (enabling future disjointness checks); the (subject_iri, predicate_iri) count is incremented in the cardinality counter; and the (predicate_iri, object_iri) pair is recorded in the inverse-functional tracker.

rdf:type emission

After all triples are processed, deduplicated rdf:type triples are written to _type_assertions.json. Every admitted triple has a typed subject, so a rdf:type triple is always emitted for the subject. An rdf:type triple is emitted for the object only when predicate_kind: object_property: datatype-property objects are literals with no class type and produce no type assertion. Each (individual_iri, class_iri) pair is emitted exactly once regardless of how many admitted triples reference the same individual.

Figure 4. The Stage 3 verification funnel. Triples flow through five checks in sequence; the first failure determines the verdict. Repairs (blue dashed) happen at Check 3 for coercible datatype mismatches and are admitted into the knowledge graph with verdict repaired. Running state (bottom right) accumulates on every admit and feeds Checks 4 and 5 for subsequent triples.

6. One triple through the full pipeline

Interactive: trace (Commander Diaz, commands, HazmatTeam Alpha) through all three stages.

Stage 1: Extract

Stage 2: Map

Stage 3: Verify

7. SCIMA example: populating SCIMA-OWL v0.6 from Incident Report I-204

The emergency-management system receives a structured incident report. The text below is the narrative section, which feeds the pipeline as the source document. The target schema is SCIMA-OWL v0.6, the ontology built in Article 4. The pipeline produces a compliant A-Box: no new classes or properties are added; only individuals are created.

Stage 1 output

spaCy tags Commander Diaz and HazmatTeam Alpha as PERSON/ORG, extracts dep-parse triples from each sentence, and segments all six sentences. The LLM pass confirms the same entities and produces matching triples for sentences 1, 2, 3, 4, and 5. Sentence 6 is returned by the LLM with negated: true; the dep parse also flags the negation (auxiliary "did not" detected as neg child of "command"). The merged negation flag from both sources quarantines the triple in _negated_triples.json.

Five positive candidate triples reach Stage 2:

{ "subject": "Commander Diaz",   "predicate": "commands",      "object": "HazmatTeam Alpha",   "sources": ["dep_parse","llm"], "sentence_index": 1 }
{ "subject": "HazmatTeam Alpha", "predicate": "dispatchedTo",  "object": "Incident I-204",      "sources": ["dep_parse","llm"], "sentence_index": 2 }
{ "subject": "Reading R1",       "predicate": "observedValue",  "object": "47 psi",             "sources": ["dep_parse","llm"], "sentence_index": 3 }
{ "subject": "WaterMain 7B",     "predicate": "dispatchedTo",  "object": "Incident I-204",      "sources": ["dep_parse","llm"], "sentence_index": 4 }
{ "subject": "Commander Diaz",   "predicate": "commands",      "object": "HazmatTeam Gamma",    "sources": ["dep_parse","llm"], "sentence_index": 5 }

_candidate_triples.json. All five are single-sentence triples with both sources. The negated triple (sentence 6) is absent here; it is in _negated_triples.json.

Stage 2 output

All five triples map successfully. The predicate observedValue string-matches scima:observedValue, a datatype property; its object path therefore parses "47 psi" as a literal and infers datatype xsd:string conservatively (because the surface form contains extra text). The numeric value 47 and unit annotation psi are split, but the initial parse records the datatype as xsd:string with literal "47" pending the range check in Stage 3.

{ "subject_iri": "scima:IncidentCommander_commander_diaz", "predicate_iri": "scima:commands",
  "object_iri":  "scima:HazmatTeam_hazmatteam_alpha",
  "predicate_kind": "object_property", "mapping_confidence": "high", "sentence_index": 1 }

{ "subject_iri": "scima:HazmatTeam_hazmatteam_alpha",      "predicate_iri": "scima:dispatchedTo",
  "object_iri":  "scima:HazMatSpill_incident_i204",
  "predicate_kind": "object_property", "mapping_confidence": "high", "sentence_index": 2 }

{ "subject_iri": "scima:SensorReading_reading_r1",          "predicate_iri": "scima:observedValue",
  "object_literal": "47", "object_datatype": "xsd:string",
  "predicate_kind": "datatype_property", "mapping_confidence": "high", "sentence_index": 3 }

{ "subject_iri": "scima:WaterMain_watermain_7b",            "predicate_iri": "scima:dispatchedTo",
  "object_iri":  "scima:HazMatSpill_incident_i204",
  "predicate_kind": "object_property", "mapping_confidence": "high", "sentence_index": 4 }

{ "subject_iri": "scima:IncidentCommander_commander_diaz",  "predicate_iri": "scima:commands",
  "object_iri":  "scima:HazmatTeam_hazmatteam_gamma",
  "predicate_kind": "object_property", "mapping_confidence": "high", "sentence_index": 5 }

_mapped_triples.json. All five triples mapped. Note WaterMain 7B typed as scima:WaterMain, which will matter in Stage 3.

Stage 3 output

All five triples share the same sort key (single-sentence, both sources, mapping_confidence high), so the tiebreaker is sentence_index ascending. Processing order is 1, 2, 3, 4, 5.

Three triples are admitted (two outright, one repaired). Two are rejected: the first for a domain violation (the text hallucinated that a water main was “dispatched to” an incident, confusing the infrastructure entity with a responder unit), and the second for a cardinality violation (a commander who commands one team cannot command a second under the functional-property constraint declared in v0.8).

The rdf:type emission step then collects all individuals referenced in admitted triples and writes one type assertion per unique pair:

# _type_assertions.json (after deduplication)
{ "subject_iri": "scima:IncidentCommander_commander_diaz", "predicate_iri": "rdf:type", "object_iri": "scima:IncidentCommander" }
{ "subject_iri": "scima:HazmatTeam_hazmatteam_alpha",       "predicate_iri": "rdf:type", "object_iri": "scima:HazmatTeam"        }
{ "subject_iri": "scima:HazMatSpill_incident_i204",         "predicate_iri": "rdf:type", "object_iri": "scima:HazMatSpill"       }
{ "subject_iri": "scima:SensorReading_reading_r1",          "predicate_iri": "rdf:type", "object_iri": "scima:SensorReading"     }

WaterMain 7B and HazmatTeam Gamma produce no type assertions: the triples that would have established their types were rejected in Stage 3. Under the open-world assumption, they are unknown individuals, not absent ones.

The resulting A-Box in Turtle

Combining the admitted property triples and the type assertions produces an ontology-compliant A-Box that can be loaded alongside the SCIMA-OWL v0.6 schema without any schema violations. The v0.8 schema adds four classes, seven properties, and three new axioms (including owl:FunctionalProperty on scima:commands) needed to express the constraints used above.

@prefix scima: <http://scima.city/ontology#> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix prov:  <http://www.w3.org/ns/prov#> .
@prefix geo:   <http://www.opengis.net/ont/geosparql#> .

# ----- SCIMA-OWL v0.8: schema additions (delta over v0.6) -----
scima:IncidentReport a owl:Class ;
    rdfs:subClassOf prov:Entity ;
    rdfs:label "Incident Report" .

scima:PressureObservation a owl:Class ;
    rdfs:subClassOf scima:SensorReading ;
    rdfs:label "Pressure Observation" .

scima:TemperatureObservation a owl:Class ;
    rdfs:subClassOf scima:SensorReading ;
    rdfs:label "Temperature Observation" .

scima:ControlZone a owl:Class ;
    rdfs:subClassOf geo:Feature ;
    rdfs:label "Control Zone" .

scima:reportedAt       a owl:DatatypeProperty ; rdfs:domain scima:IncidentReport ;  rdfs:range xsd:dateTime .
scima:reportedBy       a owl:ObjectProperty ;  rdfs:domain scima:IncidentReport ;   rdfs:range scima:Agent .
scima:relatesToIncident a owl:ObjectProperty ;  rdfs:domain scima:IncidentReport ;  rdfs:range scima:Incident .
scima:hasUnit          a owl:DatatypeProperty ; rdfs:domain scima:SensorReading ;   rdfs:range xsd:string .
scima:measuredAt       a owl:DatatypeProperty ; rdfs:domain scima:SensorReading ;   rdfs:range xsd:dateTime .
scima:controlledBy     a owl:ObjectProperty ;  rdfs:domain scima:ControlZone ;      rdfs:range scima:IncidentCommander .
scima:extractedFrom    a owl:ObjectProperty ;  rdfs:domain owl:Thing ;              rdfs:range scima:IncidentReport .

# New axioms in v0.8
scima:commands       a owl:FunctionalProperty .   # at most one team per commander
scima:observedValue  a owl:FunctionalProperty .   # at most one value per reading
scima:reportedAt     a owl:FunctionalProperty .   # one timestamp per report

# ----- A-Box: individuals extracted from Incident Report I-204 -----
scima:IncidentCommander_commander_diaz a scima:IncidentCommander ;
    rdfs:label "Commander Diaz" ;
    scima:commands scima:HazmatTeam_hazmatteam_alpha .

scima:HazmatTeam_hazmatteam_alpha a scima:HazmatTeam ;
    rdfs:label "HazmatTeam Alpha" ;
    scima:dispatchedTo scima:HazMatSpill_incident_i204 .

scima:HazMatSpill_incident_i204 a scima:HazMatSpill ;
    rdfs:label "Incident I-204" .

scima:SensorReading_reading_r1 a scima:SensorReading ;
    rdfs:label "Reading R1" ;
    scima:observedValue 47 ;      # repaired from "47"^^xsd:string to 47^^xsd:integer
    scima:hasUnit "psi" .

# Rejected (not present in the A-Box):
# scima:WaterMain_watermain_7b -- dispatchedTo failed domain check
# scima:HazmatTeam_hazmatteam_gamma -- commands failed cardinality check
# (commander_diaz, commands, hazmatteam_bravo) -- quarantined as negated triple

SCIMA-OWL v0.8 schema additions (cumulative: 30 classes, 41 properties, 18 axioms) and the A-Box extracted from Incident Report I-204. The A-Box and schema load cleanly into the same graph with no constraint violations.

Key takeaways

  • KG extraction is an A-Box task: the ontology (T-Box) is the fixed contract that drives and constrains extraction.
  • Stage 1 is recall-first and ontology-agnostic. spaCy and LLM extractors run independently and their outputs are merged; negated triples are quarantined, not deleted.
  • The LLM pass extracts both entity mentions and raw triples in a single batched call per sentence window, keyed by sentence index so Stage 2 can retrieve context on demand.
  • Stage 2 maps surface terms onto ontology IRIs using a cascade: fast string or embedding match, then LLM fallback. Every sub-step produces a component confidence; the overall confidence is the minimum of the three.
  • Predicate mapping checks both direct and inverse labels. A passive or reversed surface predicate sets inverted: true, triggering a subject-object swap after both ends are fully typed.
  • Stage 3 sorts triples by confidence before checking, so conflicts are resolved deterministically: the higher-confidence triple always wins without backtracking.
  • Five checks run in sequence for each triple: domain, range, datatype repair, disjointness, and cardinality. The first failure determines the verdict.
  • Datatype mismatches can be repaired (cast succeeds) or must be rejected (cast fails). Repaired triples enter the A-Box with verdict repaired.
  • rdf:type assertions are emitted separately after all triples are processed and are deduplicated: each individual receives exactly one type assertion per class, regardless of how many property triples reference it.

Further reading

  • Mintz, M., Bills, S., Snow, R., & Jurafsky, D. (2009, August). Distant supervision for relation extraction without labeled data. In Proceedings of the Joint Conference of the 47th Annual Meeting of the ACL and the 4th International Joint Conference on Natural Language Processing of the AFNLP (pp. 1003–1011).
  • Nakashole, N., Weikum, G., & Suchanek, F. (2012, July). PATTY: A taxonomy of relational patterns with semantic types. In Proceedings of the 2012 joint conference on empirical methods in natural language processing and computational natural language learning (pp. 1135–1145).
  • Shi, P., & Lin, J. (2019). Simple bert models for relation extraction and semantic role labeling. arXiv preprint arXiv:1904.05255.
  • Paulheim, H. (2016). Knowledge graph refinement: A survey of approaches and evaluation methods. Semantic web, 8(3), 489–508.
  • Knublauch, H., & Kontokostas, D. (2017). SHACL: Shapes constraint language. W3C Recommendation.
  • Pellissier Tanon, T., Vrandečić, D., Schaffert, S., Steiner, T., & Pintscher, L. (2016, April). From freebase to wikidata: The great migration. In Proceedings of the 25th international conference on world wide web (pp. 1419–1428).

[embed]AI_agent_applications/ontology_KG_extraction_skills/KG_extraction_skills at main ·… Contribute to anyuanay/AI_agent_applications development by creating an account on GitHub.github.com

Table of Content

If you found this helpful, clap 👏 to help others discover it, and follow for more!


메타데이터
post_id
0d579c6257c0
slug
part-5-extracting-ontology-compliant-knowledge-graphs-from-sources-0d579c6257c0
url
https://medium.com/@anyuanay/part-5-extracting-ontology-compliant-knowledge-graphs-from-sources-0d579c6257c0
canonical_url
https://medium.com/@anyuanay/part-5-extracting-ontology-compliant-knowledge-graphs-from-sources-0d579c6257c0
author_url
https://medium.com/@anyuanay
status
ok
fetched_at
2026-07-16 04:05:14