1 · Author
Pisz YAML ręcznie albo z modelera. Konwencja: project.yml + models/ +
metrics/ + facets/ + joints/ + lexicon/ + contracts/.
OpenDome Semantic Layer (OSL) to otwarta specyfikacja (Apache-2.0), która opisuje — w deklaratywnym YAML-u — model semantyczny obejmujący dwie fizyczne płaszczyzny: tabele ustrukturyzowane w Iceberg i kolekcje wektorowe w Lance. Jedna specyfikacja, jeden język, jeden łańcuch nadzoru.
Ta strona ustala słownictwo i model myślowy. Po normatywny kontrakt sięgnij do specyfikacji; po powierzchnię API zajrzyj do referencji.
Dzisiejsze warstwy semantyczne OSS (dbt MetricFlow, Cube, WrenAI) opisują tabele relacyjne. Żadna nie traktuje kolekcji wektorowych jako obywateli pierwszej kategorii. To wymusza dwa równoległe modele — semantyczno-SQL-owy i „to, co RAG wie o kliencie“ — które rozjeżdżają się następnego dnia po wdrożeniu.
OSL obejmuje obie płaszczyzny:
JointEntity, obiekt logiczny (Customer, Policy, Order),
który łączy kolumny Iceberg z fasetami Lance pod jednym kluczem głównym.Deklarujesz raz. Nadzór, lineage, API i agenci konsumują ten sam model.
Model
OSL opisuje model semantyczny nad dwoma fizycznymi substratami jednym
deklaratywnym językiem. Każda płaszczyzna ma własne prymitywy, własną konwencję
FQN, własny silnik wykonawczy i własną ścieżkę ewolucji. JointEntity to element,
który je składa.
Tabele Iceberg, zapytania SQL, agregacje, joiny. Tutaj OSL przepuszcza MetricFlow bez zmian:
semantic_models/*.yml opisują encje fizyczne wraz z ich wymiarami i measures.metrics/*.yml definiują certyfikowane metryki (simple, ratio, cumulative, derived).saved_queries/*.yml pakują wielokrotnie używane zapytania.time_spine.yml definiuje ziarno czasowe projektu.Silnik referencyjny (tenant-semantic-api) kompiluje te pliki YAML do SQL nad
Trino, wykonywanego na Iceberg w bucketcie tenanta.
Kolekcje Lance z zaindeksowanymi chunkami. Tutaj OSL definiuje nowe prymitywy:
facets/*.yml (kind: UnstructuredFacet) opisuje kolekcję Lance: jej dataset
path, chunk schema, model embeddingu, indeksy (wektor + FTS + skalarny), pola
metadanych, ACL na poziomie wiersza i limity retrievalu.Silnik wykonuje hybrydowy retrieval (wektor ⊕ BM25 ⊕ filtr metadanych) nad LanceDB i zwraca fragmenty z cytowaniem, respektując zadeklarowane ACL i limity.
joints/*.yml (kind: JointEntity) deklaruje obiekt logiczny, którego klucz
główny pochodzi z semantic_model i który eksponuje atrybuty złożone — część z
płaszczyzny ustrukturyzowanej (kolumny, metryki), część z nieustrukturyzowanej
(retrieval ograniczony do tego klucza).Most jest uczciwy: każde join_on mapuje klucz encji na autorytatywne,
zaindeksowane pole metadanych fasety. Pole z provenance: derived nigdy nie
może być kluczem joina — derywowana ekstrakcja dzieje się przy ingest, nigdy w
query time.
Agent wywołujący entity_get(Customer, customer_id=X) otrzymuje w jednej
odpowiedzi kanoniczne atrybuty encji, mające zastosowanie metryki preagregowane
oraz chunki Lance odfiltrowane po customer_id=X. Jedno wywołanie, jedna decyzja
polityki, jeden ślad audytu.
Choć specyfikacja ma osobne prymitywy (SemanticModel, JointEntity), kto
konsumuje OSL, widzi jedno słowo: Entity. To, co odróżnia jedną Entity od
drugiej, to nie jej kind, lecz jej kompozycja:
| Kompozycja | Czym jest | Skąd pochodzi |
|---|---|---|
structured |
Czysto tabelaryczna Entity (tylko Iceberg) | SemanticModel, który nie jest ani kotwicą jointa, ani mostem |
structured+content |
Kolumny ustrukturyzowane połączone z fasetami Lance | JointEntity z nogami nieustrukturyzowanymi |
content |
Samodzielny korpus Lance, bez kotwicy ustrukturyzowanej | UnstructuredFacet, którego żaden joint nie wchłania |
Relacje między Entities pochodzą z dwóch miejsc: współdzielonych encji MetricFlow
(primary / foreign / unique) dla sąsiadów ustrukturyzowany ↔ ustrukturyzowany
oraz N-N przez most — tabela łącząca (SemanticModel z ≥2 encjami foreign),
która zwija się do bezpośredniej krawędzi N-N zamiast być węzłem.
To słownictwo serwuje domain-map (GET /osl/domain-map): jeden rodzaj węzła
entity oznaczony kompozycją, plus węzły metric i candidate.
| Rodzina | Kind | Cel | MetricFlow |
|---|---|---|---|
| Modelowanie ustrukturyzowane | SemanticModel, Metric, SavedQuery, TimeSpine |
Opisać tabele Iceberg + metryki | ✅ identyczne / rozszerzone |
| Modelowanie nieustrukturyzowane | UnstructuredFacet |
Opisać kolekcję Lance | ❌ OSL-only |
| Kompozycja | JointEntity |
Połączyć obie płaszczyzny pod jedną encją logiczną | ❌ OSL-only |
| Katalog i kontrakty | Lexicon, DataContract, PolicyBinding |
Synonimika, SLA, hinty dla PDP | ❌ OSL-only |
Każdy prymityw niesie apiVersion: osl.opendome.eu/v1, kind i unikalny name.
Tożsamość obiektu to (kind, name) — z wyjątkiem SemanticModel, którego
tożsamość to (catalog, schema, table).
OSL deklaruje; silnik wykonuje. Między nimi jest krok kompilacji.
1 · Author
Pisz YAML ręcznie albo z modelera. Konwencja: project.yml + models/ +
metrics/ + facets/ + joints/ + lexicon/ + contracts/.
2 · Validate
osl validate uruchamia JSON Schema per plik plus cross-reference (każdy
referowany FQN musi istnieć). Błędy w E0xx (schema) lub E1xx (resolve).
3 · Compile
osl compile emituje pojedynczy target/manifest.json — kanoniczną,
odtwarzalną reprezentację, którą serwuje silnik i czyta policy engine.
4 · Publish
osl publish wgrywa manifest do silnika tenanta. Atomowo (revert przez
osl publish --revert), emituje zdarzenie lineage osl.publish.
Od tego momentu silnik serwuje zapytania: REST dla BI/aplikacji, narzędzia MCP dla agentów.
OSL jest rygorystyczny co do nazw, bo polityki od nich zależą. Cztery przestrzenie FQN:
| Przestrzeń | Forma | Przykład |
|---|---|---|
| Ustrukturyzowana | <catalog>.<schema>.<table>[:<column>] |
iceberg.curated.customer:email |
| Nieustrukturyzowana | lance://<collection>[/*][:<metadata_field>] |
lance://meeting_transcripts:attendees |
| Narzędzia | <tool_kind>:<resource> |
metrics:revenue, joints:Customer |
| Joint-exposed | joint://<Entity>.<attribute> |
joint://Customer.recent_meeting_topics |
FQN-y rozróżniają wielkość liter i nie niosą wersji — wersjonowanie żyje w
skompilowanym, podpisanym SHA manifeście. Policy engine konsumuje te FQN-y w swojej
4-wymiarowej krotce (data, action, actor, context). OSL nie wymyśla równoległej
semantyki dostępu; emituje fakty, które PDP indeksuje.
OSL to wspólna specyfikacja między wszystkimi tymi częściami, a nie same części.