Skip to content

Semantic Store

The semantic store provides persistence for the Vocabulary pillar: concept schemes, concepts, relationships, and versioned LinkML schema configs. Use it when you need a central registry for business concepts and their relationships, or to store and retrieve LinkML configs by name and version (e.g. for the Vocabulary workspace in the Web UI).

Overview

from pycharter.semantic_store import PostgresSemanticStore

store = PostgresSemanticStore("postgresql://...")
store.connect()

# Store a concept scheme
store.store_scheme("trading-domain", "1.0.0", title="Trading Domain", description="...")

# Store concepts within the scheme
store.store_concept(
    "OrderId", "trading-domain", label="Order Identifier", definition="Unique order ID"
)
store.store_concept(
    "CustomerId", "trading-domain", label="Customer Identifier", broader="PartyId"
)

# Store a relationship
store.store_relationship("OrderId", "CustomerId", "references")

# Store a versioned LinkML schema config
store.store_config("trading_domain", "1.0.0", linkml_yaml="...")

# Retrieve
scheme = store.get_scheme("trading-domain")
concepts = store.list_concepts(scheme_key="trading-domain")
config = store.get_config("trading_domain", "1.0.0")
store.disconnect()

When to use

  • Vocabulary workspace — The Web UI uses the semantic store for concept schemes, concepts, relationships, and LinkML schema configs.
  • Contract field bindings — Field-level links from contract fields to concepts are stored with the contract store; the semantic store holds the concept definitions and schemes.
  • Governance — Central vocabulary of business terms and their relationships.

Store implementations

Class Backend Use case
InMemorySemanticStore Memory Testing
SQLiteSemanticStore SQLite Development
PostgresSemanticStore PostgreSQL Production, API

Semantic store does not currently implement MongoDB or Redis backends.

Explicit SQL initialization

connect(auto_initialize=True) creates the five managed semantic tables, including versioned concept-scheme snapshots. It also adds a missing snapshot table to an existing core-only store. Repeating explicit initialization keeps stored schemes, snapshots and unrelated tables intact.

Ordinary connect() and reconnect retain their existing validation behavior: they accept an existing four-table core store and do not implicitly create a snapshot table. validate_schema_on_connect=False also retains its existing behavior. Request explicit initialization when adding snapshot storage, or use the normal database migration workflow. This option creates missing tables; it does not migrate incompatible columns or change namespace and mutation policies. Explicit initialization uses the same atomic bootstrap as the other SQL Stores, including SQLite schema translation and the standard PostgreSQL pycharter schema. It does not repair custom-schema routing.

SemanticStoreClient

Base interface for all semantic stores. Operations are grouped into: concept schemes, concepts, relationships, and LinkML schema configs.

SemanticStoreClient

SemanticStoreClient(connection_string: str | None = None)

Bases: VersionedArtifactStore, _ConceptSchemeAbstractMixin, _ConceptAbstractMixin, _RelationshipAbstractMixin, _SchemeDocumentAbstractMixin

Client for the knowledge graph and its versioned LinkML configs.

The versioned-artifact surface (save / get / list / list_versions / set_status / update / delete, inherited from :class:VersionedArtifactStore) operates on LinkML schema configs (the store's one versioned artifact); the document carries {linkml_yaml, description, scheme_key}. Graph operations keep explicit names: concepts by name, schemes by scheme_key, relationships by their own keys. Implementations extend this for specific backends (PostgreSQL, SQLite, InMemory).

connect abstractmethod

connect() -> None

Establish the backend connection.

disconnect

disconnect() -> None

Close the backend connection.

store_scheme abstractmethod

store_scheme(
    scheme_key: str,
    version: str,
    *,
    namespace: str | None = None,
    category: str = "domain",
    description: str | None = None,
    base_uri: str | None = None,
    author: str | None = None,
) -> str

Store a concept scheme.

Parameters:

Name Type Description Default
scheme_key str

Unique scheme identifier (e.g. "trading-domain").

required
version str

Version string (e.g. "1.0.0").

required
namespace str | None

Identity scope; None means the global namespace.

None
category str

"domain" or "pattern" (a starter vocabulary).

'domain'
description str | None

Optional description.

None
base_uri str | None

Optional base URI for concept URIs.

None
author str | None

Optional creator identifier.

None

Returns:

Type Description
str

Scheme ID (implementation-defined).

Raises:

Type Description
ValueError

If scheme_key already exists.

get_scheme abstractmethod

get_scheme(
    scheme_key: str, version: str | None = None
) -> dict[str, Any] | None

Retrieve a concept scheme by key.

Parameters:

Name Type Description Default
scheme_key str

Scheme identifier.

required
version str | None

Optional version filter. If None, returns latest.

None

Returns:

Type Description
dict[str, Any] | None

Scheme dict or None if not found.

list_schemes abstractmethod

list_schemes() -> list[dict[str, Any]]

List all concept schemes.

Returns:

Type Description
list[dict[str, Any]]

List of scheme summary dicts.

delete_scheme abstractmethod

delete_scheme(scheme_key: str) -> bool

Delete a concept scheme and its concepts.

Parameters:

Name Type Description Default
scheme_key str

Scheme identifier.

required

Returns:

Type Description
bool

True if deleted, False if not found.

store_concept abstractmethod

store_concept(
    name: str,
    scheme_key: str,
    *,
    concept_key: str | None = None,
    label: str | None = None,
    definition: str | None = None,
    broader: str | None = None,
    concept_type: str | None = None,
    tier: str = "free",
    uri: str | None = None,
    notation: str | None = None,
    deprecated: bool = False,
    author: str | None = None,
) -> str

Store a concept within a scheme.

Parameters:

Name Type Description Default
name str

Unique concept name (e.g. "OrderIdentifier").

required
scheme_key str

Parent scheme identifier.

required
concept_key str | None

Stable cross-artifact identifier; defaults to name when omitted.

None
label str | None

Human-readable label.

None
definition str | None

Text definition.

None
broader str | None

Name of the parent concept (for hierarchy).

None
concept_type str | None

Concept type (entity, event, etc.).

None
tier str

Governance tier (core, domain, free).

'free'
uri str | None

Full concept URI.

None
notation str | None

Short notation code.

None
deprecated bool

Whether the concept is deprecated.

False
author str | None

Creator identifier.

None

Returns:

Type Description
str

Concept ID (implementation-defined).

Raises:

Type Description
ValueError

If name already exists.

get_concept abstractmethod

get_concept(
    name: str, *, scheme_key: str | None = None
) -> dict[str, Any] | None

Retrieve a concept by name.

Parameters:

Name Type Description Default
name str

Concept name.

required

Returns:

Type Description
dict[str, Any] | None

Concept dict or None if not found.

list_concepts abstractmethod

list_concepts(
    scheme_key: str | None = None,
) -> list[dict[str, Any]]

List concepts, optionally filtered by scheme.

Parameters:

Name Type Description Default
scheme_key str | None

Optional scheme filter.

None

Returns:

Type Description
list[dict[str, Any]]

List of concept dicts.

update_concept abstractmethod

update_concept(name: str, **fields: Any) -> None

Update mutable fields on a concept.

Parameters:

Name Type Description Default
name str

Concept name.

required
**fields Any

Fields to update (label, definition, concept_type, tier, deprecated, etc.).

{}

Raises:

Type Description
ValueError

If the concept does not exist.

delete_concept abstractmethod

delete_concept(name: str) -> bool

Delete a concept by name.

Parameters:

Name Type Description Default
name str

Concept name.

required

Returns:

Type Description
bool

True if deleted, False if not found.

store_relationship abstractmethod

store_relationship(
    source_name: str,
    target_name: str,
    relationship_type: str,
    *,
    author: str | None = None,
    scheme_id: str | None = None,
    origin: str | None = None,
) -> str

Store a relationship between two concepts.

Implementations must be idempotent: an existing edge with the same source, target, type, and scheme returns its id instead of creating a duplicate.

Parameters:

Name Type Description Default
source_name str

Source concept name.

required
target_name str

Target concept name.

required
relationship_type str

Relationship type (e.g. "is_a", "depends_on").

required
author str | None

Creator identifier.

None
scheme_id str | None

Owning concept scheme id — scheme-scoped graph readers only see edges that carry it.

None
origin str | None

Provenance origin (e.g. "asserted").

None

Returns:

Type Description
str

Relationship ID (implementation-defined).

Raises:

Type Description
ValueError

If source or target concept does not exist.

list_relationships abstractmethod

list_relationships(
    concept_name: str | None = None,
    rel_type: str | None = None,
) -> list[dict[str, Any]]

List relationships, optionally filtered.

Parameters:

Name Type Description Default
concept_name str | None

Filter by source or target concept name.

None
rel_type str | None

Filter by relationship type.

None

Returns:

Type Description
list[dict[str, Any]]

List of relationship dicts.

delete_relationship abstractmethod

delete_relationship(relationship_id: str) -> bool

Delete a relationship by ID.

Parameters:

Name Type Description Default
relationship_id str

Relationship identifier.

required

Returns:

Type Description
bool

True if deleted, False if not found.

list_versions

list_versions(name: str) -> list[str]

Return all versions for name, oldest to newest.

get_parsed_schema

get_parsed_schema(
    schema_name: str, schema_version: str
) -> LinkMLSchema | None

Return a parsed LinkMLSchema from the stored YAML.

Parameters:

Name Type Description Default
schema_name str

Ontology identifier.

required
schema_version str

Ontology version string.

required

Returns:

Type Description
LinkMLSchema | None

Parsed LinkMLSchema, or None if not found.

ingest_vocabulary

ingest_vocabulary(
    scheme: ConceptScheme, *, author: str = "seed"
) -> dict[str, int]

Bulk-load a ConceptScheme into the store.

Two-pass approach: first pass stores all concepts, second pass wires up parent references via update_concept.

Parameters:

Name Type Description Default
scheme ConceptScheme

Parsed concept scheme.

required
author str

Audit trail author string.

'seed'

Returns:

Type Description
dict[str, int]

Dict with created, updated, and total counts.

Concept schemes

Method Description
store_scheme(scheme_key, version, title, ...) Store a concept scheme. Optional: description, base_uri, author.
get_scheme(scheme_key, version=None) Retrieve a scheme; if version is None, returns latest.
list_schemes() List all concept schemes.
delete_scheme(scheme_key) Delete a scheme and its concepts.

Concepts

Method Description
store_concept(name, scheme_key, ...) Store a concept. Optional: label, definition, broader, concept_type, tier, uri, notation, deprecated, author.
get_concept(name) Retrieve a concept by name.
list_concepts(scheme_key=None) List concepts, optionally filtered by scheme.
update_concept(name, **fields) Update mutable fields.
delete_concept(name) Delete a concept.

Relationships

Method Description
store_relationship(source_name, target_name, relationship_type, ...) Store a relationship between two concepts.
list_relationships(concept_name=None, rel_type=None) List relationships with optional filters.
delete_relationship(relationship_id) Delete a relationship by ID.

LinkML schema configurations

Versioned LinkML YAML artifacts are stored and retrieved by schema_name and schema_version.

Method Description
store_config(name, version, linkml_yaml, ...) Store a LinkML schema config. Optional: description, scheme_key, created_by.
get_config(name, version) Retrieve the full config dict.
list_configs(name=None) List stored configs.
list_versions(name) List versions for a schema.
update_status(...) Update lifecycle status.
delete_config(name, version) Delete a config.
get_parsed_schema(name, version) Return a parsed LinkMLSchema from the stored YAML.
ingest_vocabulary(scheme, author=...) Bulk-load a ConceptScheme into the store (concepts + hierarchy).

SQLite and Postgres

from pycharter.semantic_store import SQLiteSemanticStore, PostgresSemanticStore

# SQLite (development)
store = SQLiteSemanticStore(connection_string="sqlite:///pycharter.db")
store.connect()

# Postgres (production / API)
store = PostgresSemanticStore(
    connection_string="postgresql://user:pass@localhost/pycharter"
)
store.connect()

In-memory

from pycharter.semantic_store import InMemorySemanticStore

store = InMemorySemanticStore()
store.connect()

See also