Metadata-Version: 2.4
Name: nomox-semantics
Version: 0.1.0
Summary: Semantic data model for LLM-consumable data catalog - shared contract across Nomox services.
Author-email: nomox <admin@get-nomox.com>
License-Expression: MIT
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Requires-Dist: pydantic<3,>=2.7
Provides-Extra: dev
Requires-Dist: mypy>=1; extra == 'dev'
Requires-Dist: pytest-cov>=4; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Description-Content-Type: text/markdown

# Nomox Semantic Model

The shared knowledge contract between every Nomox service. Describes what data exists (physical layer) and what it means (ontology), and ties the two together so an agent can move from a natural-language concept all the way down to a specific column in a specific table.

## Installation

```bash
pip install git+https://${GITHUB_TOKEN}@github.com/Nomox-ai/semantics-model.git
```

Pin to a tag for reproducible installs:

```bash
pip install git+https://${GITHUB_TOKEN}@github.com/Nomox-ai/semantics-model.git@v0.1.0
```

## Quickstart

```python
from uuid import uuid4
from nomox_semantics import (
    SemanticCatalog, DataSource, SourceType, Table, Column, ColumnDataType,
    Entity, EntityAttribute, EntityTableMapping, AttributeRole, SemanticType,
)

# 1. Physical layer — what exists in the database
src   = DataSource(slug="prod", name="Prod", source_type=SourceType.POSTGRES)
users = Table(source_id=src.id, schema_name="public", table_name="users")
ltv   = Column(table_id=users.id, source_id=src.id, column_name="ltv_cents",
               ordinal_position=1, data_type=ColumnDataType.BIGINT, raw_data_type="bigint")

# 2. Semantic layer — what the data means in business terms
customer = Entity(
    slug="customer", name="Customer", plural_name="Customers",
    aliases=["user", "account holder"],                      # for natural-language matching
    table_mappings=[EntityTableMapping(table_id=users.id, source_id=src.id)],  # entity -> table
)

# An EntityAttribute binds a business field to a physical column
ltv_attr = EntityAttribute(
    entity_id=customer.id, column_id=ltv.id, source_id=src.id,
    name="lifetime_value", display_name="Lifetime Value",
    role=AttributeRole.MEASURE, default_aggregation="SUM",   # tells the query engine it's aggregatable
    semantic_type=SemanticType.CURRENCY, unit="EUR",         # values are EUR, not raw cents
)

# 3. Assemble the catalog — the root object every Nomox service consumes
catalog = SemanticCatalog(organisation_id=uuid4(), name="Acme")
catalog.sources[src.id] = src
catalog.tables[users.id] = users
catalog.columns[ltv.id] = ltv
catalog.entities[customer.id] = customer
catalog.attributes[ltv_attr.id] = ltv_attr
```

## Documentation

See [docs/](docs/) for the full design documentation.
