This is part of Ontotext’s AI-in-Action initiative aimed at enabling data scientists and engineers to benefit from the AI capabilities of our products.
What’s the difference between a graph and a knowledge graph? Our Knowledge Hub Fundamentals article What is a Knowledge Graph describes how knowledge graphs are more than just simple data graphs because they include a knowledge model that adds three things: formal semantics, descriptions that contribute to each other, and diverse data that is connected and described by semantic metadata. Standards-based entity linking contributes to all three of these goals because it makes it easier to add new, related data that provides context to other entities stored in a GraphDB model.
Identifying entities in natural language text
Ontotext’s Tag service analyzes natural language text and can identify, for example, whether a mention of “Ferrari” refers to a specific car, the company that made it, or the person who founded the company. You can play with this service interactively at https://tag.ontotext.com. With a paragraph from the Ferrari company’s Wikipedia entry pasted onto this page, the underlined parts below show the entities that Tag has recognized, and the scrolling list on the right provides more information about these entities:

You can also call this service programmatically. The GraphDB Text mining plugin documentation page describes several text analysis tools available to GraphDB developers; one of these is the Tag API tool, which lets you call Ontotext’s Tag service from your SPARQL queries. (This is the “standards-based” part of Ontotext’s entity linking – using SPARQL to retrieve RDF data about the analysis results means that both the process and the results can be plugged into applications that take advantage of these standards.)
The Tag API’s query results can include the DBpedia URIs that are often used as identifiers for these entities in the linked data cloud. The entity linking service can also return Wikidata identifiers for recognized entities in text input, such as http://www.wikidata.org/entity/Q181282 for company founder Enzo Ferrari. We’re going to see how we can use those URIs to retrieve additional contextual data about the relevant entities in order to enrich a local graph of information about the company.
To create a client for this service, we can copy the SPARQL update query shown on that documentation page, paste it into the GraphDB Workbench’s SPARQL editor, and make a few adjustments.
PREFIX txtm: <https://www.ontotext.com/textmining#>
PREFIX txtm-inst: <https://www.ontotext.com/textmining/instance#>
INSERT DATA {
txtm-inst:tagService txtm:connect txtm:Ces;
txtm:service "https://tagger.ontotext.com/extract" ;
txtm:header "X-API-Key: qQ-H4f>.G}9Tqbfi&=%i" .
}
One of these adjustments is the inclusion of the API key. The one shown above is for demo purposes and will return a limited number of results in the course of a day. (Contact your Ontotext representative about obtaining your own API key if you are interested in using the Tag service as part of your own applications.)
Generating triples about the identified entities
After the example on the Text mining plugin documentation page uses an INSERT request to set up the Tag service, it has a SELECT query that analyzes a few sentences about the Dyson vacuum company and returns six columns of data about the entities named in those sentences. Our next query will be different for three reasons:
- It will be a CONSTRUCT query so that it creates triples that we can load into a knowledge graph.
- It will have the service analyze the text shown above about the Ferrari company instead of text about the Dyson vacuum company.
Our new query’s CONSTRUCT clause creates two new triples about each identified entity:
- The first triple uses a property from the Dublin Core standard vocabulary to say that the entity is a subject of the analyzed document. (That’s “subject” in the sense of “topic”, not in the RDF subject-predicate-object sense of the term.)
- The second stores the identified entity’s annotation type. All of the annotation types shown in the documentation’s Dyson example are “Person” or “Keyphrase”; our new query has a FILTER indicating that we’re only interested in “Location”, “Person”, or “Organization” annotation types.
PREFIX txtm: <https://www.ontotext.com/textmining#>
PREFIX txtm-inst: <https://www.ontotext.com/textmining/instance#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
CONSTRUCT {
?searchDocument dc:subject ?wikidataId .
?wikidataId txtm:annotationType ?annotationType .
}
WHERE {
?searchDocument a txtm-inst:tagService;
txtm:text '''Enzo Ferrari died in 1988, an event that
saw Fiat expand its stake to 90%. The last car that he personally
approved—the F40—expanded on the flagship s-upercar approach first
tried by the 288 GTO four years earlier. Enzo was replaced in 1991 by
Luca Cordero di Montezemolo, under whose 23-year-long chairmanship the
company greatly expanded. Between 1991 and 2014, he increased the
profitability of Ferrari's road cars nearly tenfold, both by
increasing the range of cars offered and through limiting the total
number produced. Montezemolo's chairmanship also saw an expansion in
licensing deals, a drastic improvement in Ferrari's Formula One
performance (not least through the hiring of Michael Schumacher and
Jean Todt), and the production of three more flagship cars: the F50,
the Enzo, and the LaFerrari. In addition to his leadership of
Ferrari, Montezemolo was also the chairman of
Fiat proper between 2004 and 2010.''' .
GRAPH txtm-inst:tagService {
?annotatedDocument txtm:annotations ?annotation .
?annotation txtm:annotationText ?annotationText ;
txtm:annotationType ?annotationType .
OPTIONAL { ?annotation txtm:features/txtm:inst ?wikidataId . }
}
FILTER(?annotationType IN ("Location","Person","Organization"))
}
The following query results show that the company name found in the input text was identified as an Organization that has the Wikidata ID http://www.wikidata.org/entity/Q15678788 (Fiat Chrysler Automobiles) and that the three people shown (for example, http://www.wikidata.org/entity/Q181282 for Enzo Ferrari) were identified as Persons.

Using Wikidata URIs from the entity identification to retrieve contextual data
Imagine that you downloaded the triples created by the query above into a file and then imported that file into a repository. The repository would have URIs for some people associated with the company’s history, as you can see in the subject and object columns above. We can use these URIs to enrich the repository’s graph with additional contextual information about the entities that they identify.
In the query below, the WHERE clause looks for entities in the local repository that have an annotation type of “Person” and then uses the ?person variable to send the Wikidata URI of these entities to Wikidata’s SPARQL endpoint. The rest of the SERVICE clause that gets sent with this variable asks the endpoint for the person’s birthplace, birth date, and death date, if each of these are there. For any that are, the CONSTRUCT clause that begins the query creates triples about them. (Most of the triples use properties from the schema.org ontology but I could have used properties from other public or private schemas, or even from a mix of them.)
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX p: <http://www.wikidata.org/prop/>
PREFIX ps: <http://www.wikidata.org/prop/statement/>
PREFIX txtm: <https://www.ontotext.com/textmining#>
PREFIX schema: <http://schema.org/>
CONSTRUCT {
?subject rdfs:label ?name ;
schema:birthPlace ?birthPlace ;
schema:birthDate ?birthDate ;
schema:deathDate ?deathDate .
}
WHERE {
?document dc:subject ?subject .
?subject txtm:annotationType "Person" .
SERVICE <https://query.wikidata.org/sparql> {
?subject rdfs:label ?name ;
p:P569/ps:P569 ?birthDate ;
p:P19/ps:P19 ?birthPlace ;
OPTIONAL { ?subject p:P570/ps:P570 ?deathDate .}
FILTER ( lang(?name) = "en" )
}
}
Here are the triples created by this query:

As you can see, birthplace values are not names but URIs such as http://www.wikidata.org/entity/Q4060 for Michael Schumacher’s’s birthplace of Hürth, Germany. If we want the names of these places – or their latitude and longitude values, or current populations, or area in kilometers – we can use a SERVICE clause to retrieve these values just like we used one to retrieve data about the people mentioned in the first set of triples.
We can save the new triples created by this last query and import them into the repository about Ferrari entities created earlier. This new data provides context about the people in the graph that might help to answer questions about how the origin or death date of important figures in the company’s history may have affected that history.
Wikidata, as the database behind Wikipedia, has a lot more data about all kinds of entities that you can use to enrich your own graphs using these techniques.
Linking to Wikidata and more
The Tag service that we’ve seen here takes advantage of Ontotext’s new Common English Entity Linking (CEEL) technology. Other features of CEEL include:
- the ability to connect to other databases besides Wikidata
- the use of a transformer model that improves accuracy while still being very fast
- the use of zero-shot learning, enabling identification of entities that were introduced to the source after the initial analysis of the source was performed
- adaptability to your particular domain and knowledge base instances
Read more about what CEEL can do for you at Common English Entity Linking: Linking Text to Knowledge Quickly and Efficiently.

