omni-model-builder

Par exploreomni · omni-agent-skills

Créez et modifiez des définitions de modèle sémantique Omni Analytics — vues, topics, dimensions, mesures, relations et query views — en YAML via l'Omni CLI. Utilisez cette skill dès que quelqu'un souhaite ajouter un champ, créer une nouvelle dimension ou mesure, définir un topic, configurer des jointures entre tables, modifier le modèle de données, construire une nouvelle vue, ajouter un champ calculé, créer une relation, éditer du YAML, travailler sur une branch, promouvoir des changements de modèle, ou toute variante de « modéliser ces données », « ajouter cette métrique », « créer une vue pour » ou « configurer une jointure entre ». À utiliser également pour migrer des patterns de modélisation, le YAML d'Omni étant conceptuellement similaire à d'autres définitions de semantic layer.

npx skills add https://github.com/exploreomni/omni-agent-skills --skill omni-model-builder

Omni Model Builder

Créez et modifiez le modèle sémantique d'Omni via l'API YAML — vues, rubriques, dimensions, mesures, relations et vues de requête.

Conseil : Utilisez toujours omni-model-explorer en premier pour comprendre le modèle existant.

Conditions préalables

# Vérifiez que l'Omni CLI est installée — sinon, demandez à l'utilisateur de l'installer
# Voir : https://github.com/exploreomni/cli#readme
command -v omni >/dev/null || echo "ERROR: Omni CLI is not installed."
# Affichez les profils disponibles et sélectionnez celui approprié
omni config show
# S'il existe plusieurs profils, demandez à l'utilisateur lequel utiliser, puis changez :
omni config use <profile-name>

Vous avez besoin des permissions Modeler ou Connection Admin.

Conseil : Utilisez -o json pour forcer une sortie structurée pour l'analyse programmatique, ou -o human pour des tableaux lisibles. Le paramètre par défaut est auto (human dans un TTY, JSON quand redirigé).

Architecture de modélisation en couches d'Omni

Omni utilise une approche en couches où chaque couche s'appuie sur la précédente :

  1. Couche Schema — Générée automatiquement à partir de votre base de données. Reflète les tableaux, vues, colonnes et leurs types. Maintenue à jour via l'actualisation du schéma.

  2. Couche Shared Model — Votre modèle sémantique gouverné. C'est là que vous définissez les dimensions, mesures, jointures et rubriques réutilisables dans l'organisation.

  3. Couche Workbook Model — Extensions ad hoc au sein de classeurs individuels. Utilisée pour les champs expérimentaux avant promotion au modèle partagé.

  4. Couche Branch — Couche de développement intermédiaire. Utilisée lors du travail dans les branches avant de fusionner les modifications au modèle partagé.

Concept clé : La couche schéma est la fondation et la source de vérité pour la structure des tableaux et colonnes. Quand votre schéma de base de données change (nouveaux tableaux, colonnes supprimées, modifications de type), vous actualisez le schéma pour garder Omni synchronisé. Tout le contenu créé par l'utilisateur (dimensions, mesures, relations, rubriques) circule par la couche modèle partagé.

Flux de développement : Lors de la création ou modification du modèle, vous travaillez dans les branches (voir « Safe Development Workflow » ci-dessous). Les branches sont des copies isolées où vous pouvez expérimenter en toute sécurité avant de fusionner les modifications au modèle partagé. Cette compétence couvre la création et l'édition de définitions de modèles dans les branches et les modèles partagés.

Déterminer le dialecte SQL

Avant d'écrire toute expression SQL, confirmez le dialecte à partir de la connexion — ne deviez pas d'après le nom de la connexion :

# 1. Listez les modèles pour trouver le connectionId
omni models list

# 2. Recherchez le dialecte de la connexion
omni connections list
# → trouvez votre connectionId et lisez le champ « dialect »
# → par exemple « bigquery », « postgres », « snowflake », « databricks »

Utilisez les fonctions appropriées au dialecte dans votre SQL (par ex. SAFE_DIVIDE pour BigQuery, NULLIF(a/b) pour Postgres/Snowflake).

Schema Refresh : Synchronisation avec les modifications de base de données

La couche schéma est générée automatiquement à partir de votre base de données. Quand votre schéma de base de données change (colonnes ajoutées/supprimées/renommées, modifications de type), actualisez la couche schéma d'Omni pour rester synchronisé.

Quand activer :

  • Nouveaux tableaux ajoutés à votre base de données
  • Colonne ajoutée/renommée/supprimée dans les tableaux existants
  • Création d'une nouvelle vue à partir de zéro et vous voulez les dimensions de base générées automatiquement
  • Le modèle n'est pas synchronisé avec la base de données

Ce qu'il fait :

  • Inspecte votre entrepôt de données
  • Génère automatiquement les dimensions de base pour toutes les colonnes avec les types et granularités corrects
  • Détecte les suppressions et les références cassées
  • S'exécute en tant que tâche de fond (peut prendre plusieurs minutes)

Effet secondaire : Peut générer automatiquement des dimensions pour les colonnes dont vous n'avez pas besoin. Supprimez-les avec hidden: true dans votre couche d'extension.

Activez via l'API :

omni models refresh <modelId>

# Avec une branche :
omni models refresh <modelId> --branch-id <branchId>

Nécessite les permissions Connection Admin.

Découvrir les commandes

omni models --help              # Lister toutes les opérations de modèle
omni models yaml-create --help  # Afficher les drapeaux pour l'écriture YAML

Safe Development Workflow

Travaillez toujours dans une branche. N'écrivez jamais directement en production.

Step 0 : Créer une branche

omni models create-branch <modelId> --name "my-feature-branch"

La réponse model.id est votre branchId — un UUID que vous transmettrez à tous les appels d'API suivants. Pour lister les branches existantes à tout moment :

omni models list --include activeBranches

Modèles connectés à git : Si votre modèle est connecté à un dépôt git (omni models git-get <modelId> retourne un sshUrl), fusionner une branche Omni validera automatiquement les modifications dans votre baseBranch git. Choisissez un flux de travail et tenez-y vous — soit modifiez via l'API de branche Omni (puis git pull pour synchroniser les fichiers locaux), soit modifiez les fichiers locaux et poussez via git. Mélanger les deux entraîne des conflits.

Step 1 : Écrire du YAML dans une branche

omni models yaml-create <modelId> --body '{
  "fileName": "my_new_view.view",
  "yaml": "dimensions:\n  order_id:\n    primary_key: true\n  status:\n    label: Order Status\nmeasures:\n  count:\n    aggregate_type: count",
  "mode": "extension",
  "branchId": "{branchId}",
  "commitMessage": "Add my_new_view with status dimension and count measure"
}'

Note : Le paramètre branchId doit être un UUID du serveur (Step 0). Passer un nom de chaîne au lieu d'un UUID retournera 400 Bad Request: Unrecognized key: "branchName".

Step 2 : Valider et tester

Chaque écriture YAML doit être validée et testée avant fusion. Les défaillances silencieuses sont courantes — un champ peut être du YAML syntaxiquement valide mais produire des résultats incorrects ou des requêtes cassées.

2a. Exécutez la validation du modèle :

omni models validate <modelId> --branchid <branchId>

Vérifiez la réponse :

  • Si un problème a is_warning: false, c'est une erreur — corrigez avant de continuer
  • Erreurs courantes : références de colonnes cassées, noms de champs dupliqués, syntaxe SQL invalide, chemins de jointure manquants
  • Si auto_fix est présent, vérifiez la suggestion avant d'appliquer

2b. Testez les champs nouveaux/modifiés avec une requête :

Exécutez une requête qui teste les champs que vous venez de créer ou modifier :

Note : omni query run ne supporte actuellement pas le branchId — les requêtes s'exécutent toujours contre le modèle de production. Cela signifie que vous ne pouvez tester complètement les nouveaux champs qu'après fusion. Utilisez la validation du modèle (2a) et la vérification de champ (2d) comme filet de sécurité avant fusion, et exécutez les tests de requête immédiatement après fusion.

omni query run --body '{
  "query": {
    "modelId": "<modelId>",
    "table": "your_view",
    "fields": ["your_view.new_dimension", "your_view.new_measure"],
    "limit": 10,
    "join_paths_from_topic_name": "your_topic"
  }
}'

À vérifier :

  • Aucune erreur dans la réponse — si la requête retourne une erreur, le SQL du champ est cassé (mauvaise référence de colonne, agrégation incorrecte, incompatibilité de dialecte)
  • summary.row_count > 0 — confirme que le champ se résout aux données réelles
  • Les valeurs semblent correctes — vérifiez rapidement qu'une sum ne retourne pas un count, qu'une dimension booléenne retourne true/false (pas 0/1 inopinément), etc.
  • Les jointures fonctionnent — si votre champ référence une autre vue (par ex., ${users.id}), incluez des champs des deux vues pour confirmer que la jointure se résout

2c. Si vous avez modifié une relation ou une jointure de rubrique, testez le chemin de jointure :

omni query run --body '{
  "query": {
    "modelId": "<modelId>",
    "table": "base_view",
    "fields": ["base_view.id", "joined_view.some_field"],
    "limit": 10,
    "join_paths_from_topic_name": "your_topic"
  }
}'

Une jointure fonctionnelle retourne des lignes avec des données des deux vues. Une jointure cassée retourne une erreur ou des valeurs null dans les colonnes jointes.

2d. Vérifiez que le champ apparaît dans le modèle :

# Vérifiez la rubrique pour confirmer que les nouveaux champs sont listés
omni models get-topic <modelId> <topicName> --branch-id <branchId>

# Ou relisez le YAML que vous venez d'écrire
omni models yaml-get <modelId> --filename your_view.view --branchid <branchId>

Confirmez que vos nouveaux champs sont listés dans la réponse. S'ils manquent, l'écriture YAML peut avoir échoué silencieusement (par ex., mauvais fileName, chaîne YAML malformée) — ou la vue peut se trouver dans un schéma déchargé que yaml-get ne revient pas. Avant de conclure qu'une vue n'existe pas, exécutez le fallback de chargement lazy (voir « Fallback: View Missing from yaml-get » ci-dessous).

Step 3 : Fusionner la branche

Important : Demandez toujours la confirmation de l'utilisateur avant de fusionner. Fusionner applique les modifications au modèle de production et ne peut pas être facilement annulé. Fusionnez seulement après que la validation et les tests réussissent (Step 2).

omni models merge-branch <modelId> <branchName>

Si git avec PRs obligatoires est configuré, fusionnez plutôt via votre flux de travail git.

Après fusion, exécutez une validation finale contre le modèle de production pour confirmer que la fusion n'a pas introduit de conflits :

omni models validate <modelId>

Types de fichiers YAML

Type Extension Objectif
View .view Dimensions, mesures, filtres pour un tableau
Topic .topic Jointures de vues en unité interrogeable
Relationships (special) Définitions de jointures globales

Écrivez avec mode: "extension" (couche modèle partagé). Pour supprimer un fichier, envoyez un YAML vide.

Rédaction de vues

Chaque vue qui participe aux jointures DOIT avoir une vraie dimension primary_key: true. Sans une vraie clé primaire unique à la ligne, les requêtes qui joignent cette vue peuvent produire des erreurs de fanout ou des agrégations incorrectes. Utilisez l'identifiant unique naturel du tableau (par ex., id, order_id, user_id). S'il n'y a pas de colonne unique, construisez une clé composée à partir de colonnes au niveau de la ligne qui sont conjointement uniques, par exemple sql: ${order_id} || '-' || ${line_number}. Si vous ne pouvez pas définir une expression unique à la ligne, ne marquez pas encore une dimension comme primary_key: true ; corrigez d'abord la granularité ou évitez de joindre la vue jusqu'à ce qu'une vraie clé existe.

Vue basique

dimensions:
  order_id:
    primary_key: true
  status:
    label: Order Status
  created_at:
    label: Created Date
measures:
  count:
    aggregate_type: count
  total_revenue:
    sql: ${sale_price}
    aggregate_type: sum
    format: currency_2

Comprendre la couche Schema vs la couche Extension

Quand vous créez une vue, Omni sépare le schéma (structure de base de données) du modèle (votre logique métier) :

  • Couche schéma : Dimensions de base générées automatiquement, une par colonne. Les types proviennent de la base de données. Lecture seule, synchronisée via l'actualisation du schéma.
  • Couche extension : Votre YAML personnalisé. Peut remplacer les dimensions de base, ajouter de nouvelles dimensions/mesures, masquer des colonnes, ajouter de la logique métier.

Quand les deux couches existent pour un champ portant le même nom, votre définition d'extension gagne mais les informations de type proviennent de la couche schéma.

Exemple : Le tableau a les colonnes created_at (DATE) et revenue (NUMERIC).

# Couche schéma (générée automatiquement)
dimensions:
  created_at: {}  # type: DATE, génère automatiquement les granularités
  revenue: {}     # type: NUMERIC

# Couche extension (votre YAML)
dimensions:
  created_at:
    label: "Order Created"
    description: "When the order was placed"

  revenue:
    hidden: true  # Masquer la colonne brute

measures:
  total_revenue:
    sql: SUM(${revenue})
    aggregate_type: sum
    format: currency_2

Résultat : created_at hérite son type de la couche schéma (DATE avec granularités semaine/mois/année automatiques) mais obtient votre étiquette. La colonne brute revenue est masquée, exposée uniquement via la mesure total_revenue.

Point clé : Si votre couche extension définit une dimension mais il n'y a pas de dimension de base de couche schéma pour fournir les informations de type, Omni ne peut pas inférer les granularités ou les types. Solution : déclenchez une actualisation du schéma pour générer automatiquement la couche schéma (voir la section « Schema Refresh » ci-dessus).

Paramètres de dimension

Voir references/modelParameters.md pour la liste complète des 35+ paramètres de dimension, valeurs de format et granularités.

Paramètres les plus courants :

  • sql — Expression SQL utilisant les références ${field_name}
  • label — Nom d'affichage · description — Texte d'aide (aussi utilisé par Blobby)
  • primary_key: true — Clé unique (critique pour les agrégations)
  • hidden: true — Masque du sélecteur, toujours utilisable en SQL
  • formatnumber_2, currency_2, percent_2, id
  • group_label — Groupe les champs dans le sélecteur
  • synonyms — Noms alternatifs pour la correspondance IA (par ex., [client, account, buyer])

Paramètres de mesure

Voir references/modelParameters.md pour la liste complète des 24+ paramètres de mesure et tous les 13 types d'agrégation.

Les filtres de mesure restreignent les lignes avant l'agrégation :

measures:
  completed_orders:
    aggregate_type: count
    filters:
      status:
        is: complete
  california_revenue:
    sql: ${sale_price}
    aggregate_type: sum
    filters:
      state:
        is: California

Voir references/yaml-filter-syntax.md pour la référence d'opérateur complète couvrant les opérateurs conditionnels, numériques, de chaîne et date/heure, la négation, les valeurs de tableau et la gestion booléenne.

Fallback : Vue manquante de yaml-get

Avant de conclure qu'une vue n'existe pas, exécutez toujours cette vérification en deux étapes. yaml-get retourne seulement les vues des schémas actuellement chargés — les vues dans des schémas déchargés ou inactifs n'apparaissent pas, mais elles sont toujours disponibles.

# 1. Lister tous les schémas connus de la connexion (chargés, déchargés et inactifs)
omni models get-schemas <modelId>
# → {"schemas": ["ANALYTICS", "PUBLIC", "STAGING", ...]}

# 2. Si le schéma cible apparaît dans la liste, chargez-le explicitement
omni models yaml-get <modelId> --includeschemas PUBLIC

Règles pour --includeschemas :

  • Accepte exactement un nom de schéma par appel — les virgules sont rejetées. Chargez les schémas un à la fois.
  • La réponse contiendra seulement les vues de ce schéma ; les relations vers d'autres schémas sont préservées.
  • Pour limiter à une branche, ajoutez --branchid <id> à yaml-get ou --branch-id <id> à get-schemas (les noms de drapeaux diffèrent selon la commande).

Si le schéma n'est pas du tout dans la liste get-schemas, la connexion n'a probablement pas accès ou le schéma n'est pas synchronisé — vérifiez auprès d'un Connection Admin.

Rédaction de rubriques

Avant de rédiger une rubrique, vérifiez que toutes les vues que vous envisagez de référencer existent réellement. Exécutez omni models yaml-get <modelId> et confirmez que chaque vue apparaît. Si une vue manque, exécutez le fallback de chargement lazy ci-dessus avant de conclure qu'elle n'existe pas — elle peut simplement se trouver dans un schéma déchargé.

Voir Topics setup pour les exemples YAML complets avec jointures, champs et ai_context, et Topic parameters pour toutes les options disponibles.

Éléments clés de rubrique :

  • base_view — la vue primaire pour cette rubrique
  • joins — structure imbriquée pour les chaînes de jointure (par ex., users: {} ou inventory_items: { products: {} })
  • ai_context — guide la correspondance de champ de Blobby (par ex., « Map 'revenue' → total_revenue »)
  • default_filters — appliqué à toutes les requêtes sauf s'il est supprimé
  • always_where_sql — filtre WHERE non supprimable utilisant une expression SQL (ne peut pas être supprimé par les utilisateurs)
  • always_where_filters — filtre WHERE non supprimable utilisant les spécifications de filtre (ne peut pas être supprimé par les utilisateurs)
  • always_having_sql — filtre HAVING non supprimable utilisant une expression SQL, appliqué après l'agrégation (ne peut pas être supprimé par les utilisateurs)
  • always_having_filters — filtre HAVING non supprimable utilisant les spécifications de filtre, appliqué après l'agrégation (ne peut pas être supprimé par les utilisateurs)
  • fields — conservation de champs : [order_items.*, users.name, -users.internal_id]

Expressions de filtre pour les rubriques

Lors de la configuration de default_filters, always_where_filters ou always_having_filters sur une rubrique, utilisez la syntaxe de condition de filtre YAML — la même syntaxe utilisée dans les filtres de mesure. Voir references/yaml-filter-syntax.md pour la référence complète.

Si la bonne configuration de filtre pour un cas d'usage donné n'est pas évidente, utilisez l'Omni AI CLI pour rechercher dans la documentation :

omni ai search-omni-docs "how do I configure always_where_filters on a topic in Omni?"

Utilisez des questions ciblées pour obtenir des exemples YAML précis pour votre besoin de filtrage spécifique avant de rédiger le YAML du modèle.

Rédaction de relations

- join_from_view: order_items
  join_to_view: users
  on_sql: ${order_items.user_id} = ${users.id}
  relationship_type: many_to_one
  join_type: always_left
Type Quand l'utiliser
many_to_one Orders → Users
one_to_many Users → Orders
one_to_one Users → User Settings
many_to_many Tags ↔ Products (rare)

Bien déterminer le relationship_type prévient le fanout et les erreurs d'agrégation symétrique.

Vues de requête

Tables virtuelles définies par une requête sauvegardée. Comme les vues ordinaires, les vues de requête doivent inclure une dimension primary_key: true pour être joignables :

schema: PUBLIC
query:
  fields:
    order_items.user_id: user_id
    order_items.count: order_count
    order_items.total_revenue: lifetime_value
  base_view: order_items
  topic: order_items

dimensions:
  user_id:
    primary_key: true
  order_count: {}
  lifetime_value:
    format: currency_2

Ou avec du SQL brut :

schema: PUBLIC
sql: |
  SELECT user_id, COUNT(*) as order_count, SUM(sale_price) as lifetime_value
  FROM order_items GROUP BY 1

Erreurs courantes de validation

Erreur Correctif
« No view X » Vérifiez l'orthographe du nom de vue
« No join path from X to Y » Ajoutez une relation
« Duplicate field name » Supprimez le doublon ou renommez (ou supprimez avec hidden: true si l'un est auto-généré)
« Invalid YAML syntax » Vérifiez l'indentation (2 espaces, pas de tabs)
Fanout / agrégations incorrectes sur les jointures Ajoutez primary_key: true à la vue jointe — chaque vue qui participe à une jointure doit avoir une clé primaire
Erreur de référence de colonne (par ex., « Column X not found ») Vérifiez que le tableau existe et que votre connexion Omni y a accès

Dépannage : Modèle désynchronisé avec la base de données

Si votre modèle ne reflète pas la base de données (colonnes manquantes, références cassées, types incorrects), déclenchez une actualisation du schéma (voir la section « Schema Refresh » ci-dessus). Puis validez :

omni models validate <modelId>

Problèmes courants et correctifs :

Problème Cause Correctif
Références de colonnes cassées La colonne n'existe plus dans la base de données Supprimez ou mettez à jour la référence sql
Collision de noms de champs Une dimension auto-générée entre en conflit avec votre mesure Supprimez avec hidden: true ou renommez
Types de champs inconnus Les informations de type ne sont pas disponibles à partir du schéma Vérifiez que la colonne existe et que la connexion y a accès
Tableaux manquants Le tableau n'est pas dans le schéma après l'actualisation Vérifiez que le tableau existe et que la connexion inclut sa base de données/schéma

Référence de documentation

Compétences associées

  • omni-model-explorer — comprendre le modèle avant modification
  • omni-ai-optimizer — ajouter du contexte IA après construction des rubriques
  • omni-query — tester les nouveaux champs

Skills similaires