Zum Inhalt springen

Saiku-Semantik-Annotationen

Mondrians generischer <Annotation>-Block ist ein freiformiger Schlüssel/Wert-Beutel, der an jedes Schema-Element (Cube, Dimension, Hierarchy, Level, Measure, …) angehängt ist. Saiku reserviert den saiku.semantic.*-Namespace innerhalb dieses Beutels für ein kleines typisiertes Vokabular, das Folgendes antreibt:

  1. Die AI-Ask-Ebene — Beschreibungen und Synonyme geben dem LLM echten Business-Kontext; Aggregationsarten, Granularitäten und erforderliche Filter halten seine Abfragevorschläge vernünftig.
  2. PII-Schutz — der saiku.semantic.pii=true-Marker versetzt ein Level oder Measure in den Modus „strukturell präsent, aber opak” in agent-zugewandten Oberflächen und blockiert, dass Drillthrough-, Share-/Embed-Freigabe- und Download-Pfade die zugrundeliegenden Werte leaken.

Alle Schlüssel sind optional. Ein Schema ohne jegliche saiku.semantic.*-Annotationen läuft identisch zu einem ohne den Annotation-Block; der Namespace ist rein additiv.

Auf einen Blick

Annotation-SchlüsselGültig aufTyp / WerteZweck
saiku.semantic.descriptionDimension · Measure · LevelFreitextBusiness-Beschreibung; sichtbar in /ai/schema, sodass das LLM Kontext hat
saiku.semantic.synonymsDimension · Measure · LevelCSV-ListeAlternative Namen, sodass die AI „country” → „Store Country” auflösen kann
saiku.semantic.unitMeasureFreitext (z. B. USD, kWh, count)Einheiten-String; fließt in die AI-Zellenform {value, formatted, unit}
saiku.semantic.currencyMeasureISO-4217-Code (z. B. USD, EUR)Währungshinweis für monetäre Measures
saiku.semantic.aggregation_kindMeasureEnum: sum · count · distinct-count · non-additiveAggregationssemantik. Treibt Sortier-/Total-Semantik in der AI-Ebene.
saiku.semantic.cardinalityLevelEnum: low · medium · highMember-Anzahl-Hinweis. Treibt Picker-UX und AI-Kosten-Hinweise.
saiku.semantic.grainLevelEnum: year · quarter · month · week · day · hour · minuteZeit-Granularität für Datumsfilter-Modal und Zeitreihen-Chart-Inferenz
saiku.semantic.required_filtersLevelCSV von (hierarchy, level)-PaarenLevels, die die AI in filters einschließen muss, wann immer dieses Level berührt wird
saiku.semantic.piiLevel · MeasureBoolean (true / false)PII-Marker — siehe PII-Schutz unten

Unbekannte Werte für die enum-typisierten Felder werden auf WARN mit der erlaubten Liste geloggt und ansonsten ignoriert — ein Tippfehler bricht das Schema nicht.

Wohin damit

Annotationen hängen an jedem Schema-Element über einen Kind-<Annotations>-Block (XML) oder einen annotations:-Schlüssel (YAML).

<Measure name="Quantity" column="quantity_units" aggregator="sum" formatString="#,##0">
<Annotations>
<Annotation name="saiku.semantic.description">Total units prescribed (across all dispensings).</Annotation>
<Annotation name="saiku.semantic.synonyms">units, quantity, scripts</Annotation>
<Annotation name="saiku.semantic.unit">count</Annotation>
<Annotation name="saiku.semantic.aggregation_kind">sum</Annotation>
</Annotations>
</Measure>

Levels akzeptieren dieselbe <Annotations>-Form:

<Level name="Year" column="cal_year" type="Numeric" uniqueMembers="true" levelType="TimeYears">
<Annotations>
<Annotation name="saiku.semantic.description">Calendar year.</Annotation>
<Annotation name="saiku.semantic.synonyms">annual, yearly, fiscal year, y</Annotation>
<Annotation name="saiku.semantic.cardinality">low</Annotation>
<Annotation name="saiku.semantic.grain">year</Annotation>
</Annotations>
</Level>

PII-Schutz

Das Markieren eines Levels oder Measures mit saiku.semantic.pii=true meldet es in Saikus PII-Durchsetzungs-Stack an. Die Annotation ist die Deklaration — Saiku schichtet vier Durchsetzungspunkte darüber.

1. AI-Schema-Projektion — Captions und Samples entfernt

Der /ai/schema/{connection/catalog/schema/cube}-Endpunkt füttert dem LLM die Struktur des Cubes. Für jedes PII-markierte Element entfernt er:

  • caption
  • description
  • synonyms
  • Sample-Members (die Beispielwerte, die Agent-Guidance üblicherweise zeigt)

Das Level oder Measure erscheint weiterhin strukturell (der Agent weiß, dass es existiert, und kann es namentlich referenzieren), aber die Werte selbst bleiben opak. Der Agent kann Abfragen planen, die die PII-Spalte in der Projektion einschließen, ohne je tatsächliche Zeilen oder Sample-Members zu sehen.

2. Drillthrough-returns= blockiert

Drillthrough-Anfragen tragen einen returns=-Parameter, der die zu exportierenden Spalten auflistet. Wenn irgendein Token in returns= auf ein PII-markiertes Level oder Measure auflöst, wirft der Resolver AiPiiException, und der Endpunkt gibt 400 mit der beanstandeten Spalte im Body benannt zurück. Der Agent kann mit einer engeren Projektion erneut versuchen, die die PII-Spalte auslässt.

HTTP 400
{
"error": "Column 'Prescriber' is annotated PII (saiku.semantic.pii=true) and cannot be returned via drillthrough."
}

3. Embed-/Share-Tokens auto-redigieren

Wenn Sie einen Embed- oder Share-Token minten, der an eine Abfrage gebunden ist, die ein PII-markiertes Level berührt, eskaliert der Inspector die Redaktionsrichtlinie des Tokens auf FORCE_ON, unabhängig vom Standard des Operators. Empfänger des Tokens sehen redigierte Zellen, selbst wenn das Embed nicht explizit für Redaktion konfiguriert war. Beseitigt das „Ich habe vergessen, Redaktion einzuschalten”-Fußgeschütz auf geteilten Links.

4. AI-Datenrichtlinien-Gating

PII-Annotationen sind cube-level-Fakten. Sie paaren sich mit der SAIKU_AI_POLICY-Umgebungsvariable, die der deployment-level-Regler ist:

SAIKU_AI_POLICYWas die AI sieht
schema-onlyNur Schema + Sample-Members. Keine Cellset-Werte erreichen den Provider.
aggregatedAggregierte Zellsummen erreichen den Provider; Row-Level-Zellen entfernt.
row-levelVolle Zellen erreichen den Provider. PII-Annotationen redigieren dennoch Spezifika.

Die Annotation sagt „das ist sensibel”; die Richtlinie sagt „so viel sensible Daten lassen wir durch”. Zusammen entscheiden sie, was die AI pro Turn sieht. Der Standard ist schema-only — Deployments müssen sich für lockerere Stufen entscheiden.

Pre-Flight-Scanner

PiiScanner läuft beim Start über das Schema eines Cubes und loggt WARN-Zeilen für jede Spalte, deren Namensmuster PII-förmig aussieht (matcht gegen *name*, *ssn*, *email*, *npi*, *dob*, etc.), aber nicht annotiert ist. Die Warnung enthält einen einfügefertigen XML-Snippet, sodass der Schema-Autor die Spalte anmelden kann, ohne durch die Spezifikation zu jagen:

WARN [PiiScanner] Likely PII column 'prescribername' on level [Prescriber].[Prescriber] is not annotated. Add:
<Annotations>
<Annotation name="saiku.semantic.pii">true</Annotation>
</Annotations>

Der Scanner mutiert das Schema nie — er bringt nur Kandidaten zum Vorschein. Schema-Autoren entscheiden, was tatsächlich sensibel ist.

Durchgearbeitetes Beispiel — Pharma-Demo-Cube

Das Pharma-Demo-Schema wird mit PII-Annotationen auf Prescriber-Name + NPI ausgeliefert und lässt Specialty + Decile un-annotiert (die sind operativ sicher zu teilen). Auszug aus saiku-home/data/Pharma.xml:

<Dimension name="Prescriber" foreignKey="prescriberkey">
<Hierarchy hasAll="true" primaryKey="prescriberkey">
<Table name="dim_prescriber" schema="public"/>
<Level name="Specialty" column="specialty" uniqueMembers="false"/>
<Level name="Decile" column="decile" type="Numeric" uniqueMembers="false"/>
<Level name="Prescriber" column="prescriberkey" nameColumn="prescribername"
type="Numeric" uniqueMembers="true">
<Annotations>
<Annotation name="saiku.semantic.pii">true</Annotation>
</Annotations>
</Level>
</Hierarchy>
<Hierarchy name="NPI" hasAll="true" primaryKey="prescriberkey">
<Table name="dim_prescriber" schema="public"/>
<Level name="NPI" column="prescribernpi" type="Numeric" uniqueMembers="true">
<Annotations>
<Annotation name="saiku.semantic.pii">true</Annotation>
</Annotations>
</Level>
</Hierarchy>
</Dimension>

Mit diesem an Ort und Stelle gelingt einem AI-Agenten, der „break down Quantity by Specialty” fragt, das normal, aber „break down Quantity by Prescriber and download the rows” verweigert entweder (Drillthrough-Block) oder gibt aggregierte Buckets mit unterdrückten Prescriber-Namen zurück (abhängig von der AI-Richtlinienstufe).

Durchgearbeitetes Beispiel — FoodMart-Cube

FoodMart wird mit dem vollständigen deskriptiven Annotation-Satz ausgeliefert (keine PII-Spalten — synthetische Daten). Entnommen aus saiku-home/data/FoodMart4.xml:

<Level name="Store Country" column="store_country" uniqueMembers="true">
<Annotations>
<Annotation name="saiku.semantic.description">Store's country.</Annotation>
<Annotation name="saiku.semantic.synonyms">nation, country code</Annotation>
<Annotation name="saiku.semantic.cardinality">low</Annotation>
</Annotations>
</Level>
<Level name="Year" column="the_year" type="Numeric" uniqueMembers="true" levelType="TimeYears">
<Annotations>
<Annotation name="saiku.semantic.description">Calendar year.</Annotation>
<Annotation name="saiku.semantic.synonyms">annual, yearly, fiscal year, y</Annotation>
<Annotation name="saiku.semantic.cardinality">low</Annotation>
<Annotation name="saiku.semantic.grain">year</Annotation>
</Annotations>
</Level>

Dasselbe Muster skaliert über jede Dim + jedes Level. Jede Zeile ist unabhängig optional, sodass Sie die Annotationen inkrementell ausrollen können.

Validierung und unbekannte Werte

  • Enum-typisierte Felder (aggregation_kind, cardinality, grain) validieren gegen ihre erlaubte Liste. Unbekannte Werte loggen einen WARN mit dem beanstandeten Wert + der erlaubten Liste, und das Feld setzt auf unset zurück.
  • Boolean-Felder (pii) akzeptieren true / false ohne Beachtung von Groß-/Kleinschreibung nach Trim. Alles andere ist false. Schema-Autoren bekommen den konservativen Standard, wenn sie sich vertippen.
  • Freitext-Felder (description, unit, currency) werden getrimmt; leere Strings werden zu null.
  • synonyms und required_filters parsen als CSV; leere Einträge werden verworfen.

Verwandt

  • Export nach Apache Ossie — wie die saiku.semantic.*-Annotationen den Round-Trip in portables Ossie-YAML überstehen (Description + Synonyms heben sich in ai_context; alles andere reitet in custom_extensions als SAIKU-Vendor-Daten).
  • Wohlbekannte Ossie-Extensions — das Ossie-seitige Äquivalent (saiku.display, saiku.roles, saiku.pii) für YAML-Modelle. Gleiche Absicht, anderes Dateiformat.
  • Extensions: Funktionen und Formatter — der generische <Annotation>-Block, auf dem saiku.semantic.* aufbaut (und seine Locale-Metadaten-Konvention).
  • YAML-Schemas — vollständige YAML-Referenz, einschließlich annotations: auf jedem Element.
  • Zugriffskontrolle und Rollen — Zugriffsdurchsetzung auf Schema-Ebene (ergänzt PII-Annotationen: ACLs regeln, wer einen Cube abfragen kann; PII-Annotationen regeln, was das Ergebnis freilegt, sobald sie es können).