Ontologies in EvidenceGraph
Intention
An ontology defines what an EvidenceGraph can know about: the types of things (entities) and the types of relationships between them that matter for a given problem. Anything that is not described in the ontology cannot be extracted from text and does not become part of the graph.
The ontology is meant to be small and supervised by a human. The world is complex, but a problem such as money laundering or fraud involves relatively few types of entities (persons, companies, accounts, payments…) and even fewer types of relationships. An owner of the EvidenceGraph decides what is in scope and should be able to read and understand the whole ontology. The number of instances can be very large; the number of types should not.
Two pieces describe what an EvidenceGraph works with:
- The ontology says what can exist. It is a single
AgenticGraphwhose nodes are the types of entities (e.g.,person,person|student) and whose edges are the types of relationships between them (e.g.,works_on, frompersontoproject). - The initial graph says what is already known before reading any document: instances (e.g.,
person|student|Noah Kim) and the relationships between them. It is the starting point of theEvidenceGraph.
The examples on this page come from the endpoint created by the mge command line tool (a small school with students, teachers, clubs
and projects). You can find the files of its ontology in ontology_source/ and those of its initial graph in initial_graph/ inside
any new endpoint.
Hierarchical IDs
Everything in an ontology is identified by a hierarchical ID whose levels are separated by |. Each level refines its parent:
place
place|room
place|room|laboratory
A hierarchy is natural in many domains. In banking, a specific credit card is not an isolated concept: it is a credit card, which is a credit product, which is a financial product. Using a hierarchy is optional: an ontology where every ID has a single level is valid.
This is the same mechanism Source uses to index text, and it is what the agent interface
exposes (see How agents explore the ontology). Because | separates levels, it cannot be used
inside a name.
Entities: the nodes of the ontology
The types of entities are listed in entities_concepts.csv. Each one has an id and a definition:
id definition
person A human being.
person|student A person who studies at a school.
person|teacher A person who teaches a subject at a school.
place A physical location, such as a building or a room.
place|room A room inside a building.
place|room|laboratory A room equipped for scientific work.
The definitions are not just documentation. The Formalizer gives every type of
entity and its definition to the extraction model, so a clear definition directly improves what is found in the text.
Relationships: the edges of the ontology
The types of relationships are listed in relationships_concepts.csv. Each one is an edge that goes from a type of entity (src) to
another one (dst), and has an id and a definition:
id src dst definition
teaches_at person|teacher organization|school A teacher teaches at a school.
belongs_to organization|club organization|school A club belongs to a school.
works_on person project A person works on a project.
works_on|leads person project A person leads a project.
Relationships are hierarchical too: works_on|leads is a more specific way of working on a project. A relationship connects the same
types as its parent or descendants of them: works_on|leads could go from person|student, but not from organization.
The id of a relationship is unique. Two relationships cannot have the same id and different types: a name is one meaning. When the
same word seems to fit two pairs of types, they usually mean different things and deserve different names. For example, a person
belonging to an organization is being a member of it (member_of), while a club belonging to a school is being a part of it
(part_of). When they really mean the same, declare the relationship once between the most general types and let the hierarchy do the
rest: part_of from organization to organization already covers a club that is part of a school.
The initial graph
The initial graph holds the instances known beforehand. It is not part of the ontology: it is the first version of the graph that the
EvidenceGraph builds, before reading any document.
Instances are its nodes, listed in initial_graph/nodes.csv. The id of an instance is its type of entity followed by a name, so
person|student|Noah Kim tells you, without looking anything up, that Noah Kim is a student and therefore a person:
id
person|student|Noah Kim
person|teacher|Elena Ruiz
organization|school|Riverside High School
project|Helios Solar Car
Relationships between instances are its edges, listed in initial_graph/edges.csv. Each edge has its own id and a relation
with the id of its type of relationship in the ontology:
src dst relation id
person|teacher|Elena Ruiz organization|school|Riverside High School teaches_at id_elena_teaches_rhs
person|student|Noah Kim project|Helios Solar Car works_on|leads id_noah_leads_helios
The initial graph must match the ontology. This is where the hierarchy pays off: Noah Kim can lead a project because works_on|leads
goes from person, and a student is a person.
Configuration and persistence
The ontology is configured in the ontologies section of an endpoint (ontologies.jsonc in a new endpoint) as an AgenticGraph:
"ontology": {
"name": "ontology",
"extra_args": {
"description": ["This ontology holds the types of entities and of relationships that can be used in the Evidence Graph.", "..."],
"file_format": {"src": "src", "dst": "dst", "id": "id", "directed": true, "sep": "\t"},
"nodes": {"type": "csv", "$path": "ontology_source/entities_concepts.csv"},
"edges": {"type": "csv", "$path": "ontology_source/relationships_concepts.csv"},
"persistence": {"type": "pickle", "$path": "graphs/ontology.pickle"},
"max_results": 50
},
"tools": []
}
nodesandedgesare the tab separated files above. Any column other thanid(orsrc,dstandidfor edges) becomes an attribute.file_formatis optional and changes the column names and the separator. Any key left out takes its default value.persistenceis where the graph is saved, as a pickle, when the endpoint closes. If that file exists, it is loaded and the .csv files are ignored. After editing the .csv files, delete the pickle so that the ontology is built again. A message is logged for every .csv file modified after the pickle was saved.max_resultslimits the entries of every answer given to agents.descriptionis what agents read about the ontology.
The Formalizer names the ontology it uses in its own configuration (in
formalizers.jsonc). The key is the role and the value is the name of the AgenticGraph, which must also be one of its tools:
"ontology": "ontology"
The initial graph is configured in the EvidenceGraph (in
evidence_graphs.jsonc), with the same format of files:
"initial_nodes": {"type": "csv", "$path": "initial_graph/nodes.csv"},
"initial_edges": {"type": "csv", "$path": "initial_graph/edges.csv"},
"persistence": {"type": "pickle", "$path": "graphs/e_graph.pickle"}
The names of the keys tell the difference: nodes and edges define the ontology, while initial_nodes and initial_edges are only
the starting point of a graph that grows. Both are only read when their pickle does not exist.
Validation
The ontology and the initial graph are checked at three moments. If anything is wrong, every problem is logged and the object does not become ready.
- When any graph is loaded from its files (see
graph_from_files()): ids are unique, edges cannot be loaded without a file of nodes, and thesrcanddstof every edge are declared nodes. A typo such asprojecas thedstof a relationship is reported instead of becoming a new node. - When the Formalizer is piloted (see
validate_ontology()): every type of entity and relationship has its parent defined, and every relationship connects the types of its parent or descendants of them. For example,works_on|leadsfromorganizationis rejected whenworks_ongoes fromperson. - When the EvidenceGraph is piloted with its initial graph (see
validate_initial_graph()): every instance is of a type of entity of the ontology, and every edge has a relationship of the ontology between instances of its types or of descendants of them. For example,person|student|Noah Kimcan be thesrcofworks_on|leads, but not ofteaches_at, which goes fromperson|teacher. An initial graph that fails is not saved, so the next start checks it again.
How agents explore the ontology
Through the agent interface, the ontology is navigated by id, in a similar way to a Source. Unlike in a Source, ids are used
exactly as they are written in the .csv files, without the name of the ontology in front, and an empty id is the root. Entities and
relationships are navigated separately, in two trees:
children_entities_by_idx_<ontology>: the types of entities under an id, with their definitions, one or several levels down.entity_by_idx_<ontology>: a type of entity with its definition and its ancestors, to know what something is.search_entities_<ontology>: the types of entities whose id or definition contains a text.children_relationships_by_idx_<ontology>,relationship_by_idx_<ontology>andsearch_relationships_<ontology>: the same for the types of relationships, which also come with the types of entities they connect (srcanddst).relations_for_<ontology>: the types of relationships a type of entity can take part in, assrc,dstor both, including those declared for its ancestors. Aperson|studentcan take part instudies_atand also inworks_on, declared forperson.
The capabilities of relationships only appear when the ontology has relationships. Entries with "more": true have children of their
own, and every answer is limited to max_results entries and says when it has been cut. The exact capabilities are listed in the
AgenticGraph reference.
Known limitations
- There is no graph query language: agents explore the ontology through the capabilities above, one question at a time.
- The initial graph is loaded into the EvidenceGraph, but it cannot be explored through capabilities yet.
- The ontology cannot be edited at runtime: it is defined by its .csv files (deleting its pickle to apply changes).
Formalizer.is_a(), which should score whether something is a type of a given type of entity, is not implemented yet.
Reference
mercury.graph.evidence.agentic_graph.graph_from_files(nodes=None, edges=None, file_format=None)
Returns a MultiGraph built from a file of nodes and a file of edges (empty if there are none).
Every id must be unique, and every src and dst of the edges must be one of the nodes. Edges cannot be loaded without nodes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
nodes
|
dict
|
the optional file of nodes, a dictionary with a "type" ("csv" or "pickle") and a "path". |
None
|
edges
|
dict
|
the optional file of edges, like nodes. |
None
|
file_format
|
dict
|
the optional names of the columns ("src", "dst" and "id"), "directed" and the separator ("sep") of the .csv files. Every key left out takes its default value. |
None
|
Returns:
| Type | Description |
|---|---|
MultiGraph
|
the graph. |
Source code in mercury/graph/evidence/agentic_graph.py
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | |
mercury.graph.evidence.formalizer.validate_ontology(ontology)
Checks that an ontology (entities as nodes and relationships as edges between them) is coherent.
The checks are:
- Every entity has its parent (the id without its last
|level) defined. - Every relationship has its parent defined (e.g.,
works_onforworks_on|leads). - The
srcanddstof a relationship are those of its parent or descendants of them (e.g.,works_on|leadscan go fromperson|studentifworks_ongoes fromperson).
That ids are unique and that the src and dst of every relationship are entities of the ontology is already checked when it is
loaded (see
graph_from_files()).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ontology
|
AgenticGraph
|
the ontology. It must be loaded (piloted) before being validated, otherwise that is the only problem reported. |
required |
Returns:
| Type | Description |
|---|---|
list
|
A list of strings, one for each problem found. It is empty if the ontology is valid. |
Source code in mercury/graph/evidence/formalizer.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | |
mercury.graph.evidence.formalizer.validate_initial_graph(ntx, ontology)
Checks that an initial graph of instances (such as the one an EvidenceGraph starts from) matches an ontology.
The checks are:
- Every instance is a name under a type of entity of the ontology (e.g.,
person|student|Noah Kimunderperson|student). - Every edge has a
relationthat is a relationship of the ontology, and the types of the instances it connects are thesrcanddstof that relationship or descendants of them (e.g., aperson|studentcan be thesrcof a relationship fromperson).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ntx
|
MultiDiGraph
|
the initial graph, with the instances as nodes and their relationships as edges. |
required |
ontology
|
AgenticGraph
|
the ontology. It must be loaded. |
required |
Returns:
| Type | Description |
|---|---|
list
|
A list of strings, one for each problem found. It is empty if the initial graph is valid. |
Source code in mercury/graph/evidence/formalizer.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |