Ontologies
An ontology supplies a domain vocabulary and validation policy. It refines the broad POLE+O categories without requiring every application to treat all entities as generic people, places, or objects.
Since 0.7.0, client.ontology works on both backends: BoltOntology stores versioned ontologies in your own Neo4j database, and NamsOntology manages them in a hosted workspace. Both implement one OntologyAPI protocol, so ontology-management code reads the same either way; Bolt and NAMS mechanics lists where the mechanics differ. See also Backend capabilities and Bolt and NAMS.
|
What is an ontology?
An ontology describes entity types, properties, and allowed relationships for a domain. For example, a research domain can distinguish a study from a dataset and describe how they are connected while retaining a broad POLE+O category.
A schema makes the vocabulary explicit. It does not guarantee that extracted information is true or that the model selected the correct type. The complete document structure belongs in the ontology reference.
One document, four consumers
On Bolt an ontology is more than a validation schema: it is the one document the local extraction and storage pipeline agrees on. The client resolves the effective document once per connection and hands it to:
-
GLiNER2.5’s JointIE schema, compiled from the document. Entity descriptions become zero-shot annotation guidelines, and each relationship’s
sourceandtargetlabels are enforced during decoding rather than filtered afterwards. -
The LLM extractor’s prompt, where the same descriptions and the permitted
SOURCE -[REL]→ TARGETpatterns replace a fixed POLE+O block. -
Relation validation, which drops relations whose endpoint labels the ontology does not permit. This matters most for extraction stages that have no endpoint typing of their own.
-
Entity resolution, which uses
EntityTypeDef.aliasesas its gazetteer andresolution_threshold/review_thresholdas per-type bands.
That is why the document model carries extension fields: description on entity types, relationships and properties; aliases; a per-label threshold; resolution_threshold and review_threshold; the decoding constraints unique_source, unique_target, acyclic, allow_self and inverse; and the document-level no_self_loops. All of them have defaults, so a document written before 0.7.0, or fetched from NAMS, still parses.
Two design choices follow from JointIE’s flat label space. A fine-grained type is declared as its own label with a pole_type and a subtype, rather than recovered by a second classification pass. A relationship’s source and target each name a single label; several relationship definitions may share one type, and the compiler groups them.
Templates and workspace-owned ontologies
A system template offers a starting vocabulary. A workspace-owned copy allows an application to adapt that vocabulary without modifying the shared template.
An active ontology version determines the workspace’s validation policy. Template availability and active-version behavior are part of the service contract; retrieve the available and active records rather than depending on a fixed template count. See Use ontologies.
On Bolt the scope is a database rather than a workspace. Its templates are the eight built-in domain templates (poleo, podcast, news, scientific, business, entertainment, medical, legal), the same catalog the extractors use. They are synthesized rather than stored: each carries a template:<name> id, has no revision history, and cannot be updated or deleted. clone() turns one into an editable stored ontology at revision 1. Nothing is bound in a new database until you activate a version; until then, a client given no ontology of its own falls back to the template named by schema_config.ontology_template (POLE+O by default).
Versioning and immutability
A version identifies a particular schema revision. Changing a schema and activating a version are distinct operations: an editable definition is not necessarily the one governing current writes.
Version history supports comparison and deliberate rollout. Changing the active version may affect other applications using the workspace. A tutorial or experiment should preserve the previous active version or use a disposable workspace, rather than treating activation as local program state.
Validation tradeoffs
Permissive validation favors accepting input while recording non-conformance. Strict validation favors rejecting writes that violate the active schema. The right choice depends on whether the application can tolerate incomplete ingestion or imperfectly typed records.
Validation enforces the declared constraints. It cannot determine whether a source statement is factually correct. See Validation modes and errors for the current request and result contract.
On Bolt the mode is enforced in the client, and one rule holds in both modes: extracted relations the ontology does not permit are dropped before storage, because writing an edge the schema forbids is never the intent. strict adds entity-level enforcement. long_term.add_entity and add_relationship raise ValidationError for an undeclared type, an undeclared relationship name or a forbidden endpoint pair, and message ingestion drops extracted entities whose (type, subtype) the ontology does not declare. The client takes the mode from schema_config.validation_mode, then from the active stored version when that version supplied the document, and otherwise uses strict when schema_config.strict_types is set and permissive when it is not.
Bolt and NAMS mechanics
The method surface is the same on both backends; the mechanics behind it are not.
| Concern | Bolt (BoltOntology) |
NAMS (NamsOntology) |
|---|---|---|
Storage |
|
Server-side, per workspace. |
Templates |
The eight built-in domain templates, listed as read-only |
The service’s system templates, with revision rows. |
Active version |
One per database. Nothing is bound until you call |
One per workspace. |
|
Raises |
Raises |
|
Converted locally: |
Every service format, including a server-side URL fetch. |
|
Runs synchronously, one transaction per label pair, and returns a finished |
Enqueues a background job that you poll with |
Validation |
In the client: |
Server-side, at write time. |
Extension fields (descriptions, aliases, thresholds, decoding constraints) |
Drive the local pipeline: the JointIE schema, the LLM prompt and the resolver. |
Sent only when set: extension fields left at their defaults are omitted from the request body, so a document without extensions keeps its earlier shape. Whether the service keeps fields it does not model is not verified for this release; its extraction and resolution use its own engine. |
Effect on extraction |
Local, from the document resolved at connect time. |
Server-side and asynchronous after a write. |
The same rename runs on both backends in the repository’s two lifecycle examples, examples/ontology-lifecycle/ (NAMS) and examples/ontology-lifecycle-bolt/. Rename an ontology type and migrate a Bolt graph walks through the Bolt one.
Relationship to extraction
On NAMS, the active vocabulary informs the server-side graph extraction and validation path. A completed message write does not necessarily mean that asynchronous extraction has finished.
Applications that need extracted entities before their next operation must observe the supported extraction-completion mechanism. The ontology guide provides the exact waiting and verification steps. Activating a new version is also separate from migrating already stored records.
On Bolt, extraction runs in your process during the write, so there is nothing to wait for. The ontology is resolved once at connect time and compiled into the extractor before the first message is stored. The first available source wins: the MemoryClient(ontology=…) keyword, schema_config.ontology_path, schema_config.custom_schema_path, the active stored version (when schema_config.use_active_ontology is on), SchemaModel.CUSTOM with entity_types, and finally the built-in template named by schema_config.ontology_template. Because resolution happens at connect time, activating a version affects the next connection, not the client that activated it. client.ontology_document and client.validation_mode report what the client resolved. See drive extraction from an ontology for the Bolt procedure.