BXUP Track progress & test yourself — free
Data Engineering · Playbook · Core · ~4 min read
DATA ENGINEERING · PLAYBOOK · CORE

Draft a Semantic Model and Metric Definitions from Your Marts

A semantic layer — measures, dimensions, joins, and metric definitions sitting on top of your marts — is the accuracy backbone for both BI self-serve and text-to-SQL. It is also tedious to author: most of it is a mechanical restatement of structure that already exists in your mart SQL.

Tier: Core · Workflow area: Docs, lineage & governance

This playbook has an LLM draft the semantic model from your marts, then pins correctness the only way that counts: reproducing known-good report numbers.

When to reach for this

  • Standing up a semantic layer (dbt Semantic Layer/MetricFlow, Cube, Snowflake semantic views) over an existing, mature set of marts.
  • Consolidating metric definitions that currently live as tribal knowledge across five dashboards that disagree.
  • Preparing a governed foundation for a text-to-SQL or AI-analyst rollout — ungoverned schemas are where those projects die.

Don't start here if the marts themselves are unstable; a semantic layer over churning models multiplies the churn.

The workflow

  1. Collect the ground truth first. Before any generation, assemble 5–10 known-good numbers from trusted reports: "Q1 net revenue = 4,213,882", "active customers March = 18,440", with the exact filters used. These are your acceptance tests; without them, review of the generated layer is vibes.

  2. Feed marts + conventions, ask for the draft. With dbt Copilot this is a built-in generation flow; with a repo-scale assistant, prompt explicitly:

    Draft a semantic model (MetricFlow YAML) over these marts:
    fct_orders, fct_refunds, dim_customers, dim_products (SQL and schema.yml attached).
    
    Requirements:
    - Entities/joins: derive from the actual keys in the SQL, not from column-name
      similarity. State the join cardinality you inferred for each.
    - Dimensions: every categorical and date column that appears in a GROUP BY
      anywhere in the attached dashboard SQL (also attached).
    - Measures: sum/count/count_distinct as appropriate; name them with our convention
      (net_ vs gross_ prefixes; _usd suffix on monetary).
    - Metrics: define net_revenue, refund_rate, active_customers. For each, state IN A
      COMMENT the business rule you assumed (e.g. what counts as "active") so a human
      can confirm or correct it.
    - Do not invent columns. If a metric needs a column that doesn't exist, say so.
    

    Expected output: valid semantic-layer YAML where every assumed business rule is surfaced as a comment — the comments are the review surface.

  3. Review the assumptions, not the syntax. The YAML will parse; that's not the risk. The risk is refund_rate defined as refunds/orders when finance defines it as refund_amount/gross_revenue. Walk the assumption comments with the metric owner and correct definitions before any validation run — this is the human pass that cannot be skipped.

  4. Validate against the known-good numbers. Compile and run each metric through the semantic layer for the exact period/filters of your ground-truth set:

    # dbt Semantic Layer example
    dbt sl query --metrics net_revenue --group-by metric_time__quarter
    

    Compare to the trusted report values. Exact match, or explainable difference (timezone, late-arriving data, a dashboard that was itself wrong) — chase every discrepancy to a written root cause. A semantic layer that ships with unexplained deltas will be distrusted forever.

  5. Lock it with CI. Encode the ground-truth checks as tests (a scheduled query comparing semantic-layer output to pinned values, or dbt tests on metric outputs) so future edits to marts or metric YAML re-verify automatically.

  6. Point consumers at it. Migrate one dashboard and, if relevant, your text-to-SQL system to query the semantic layer instead of raw marts. The Uber-Finch-style lesson generalizes: text-to-SQL accuracy comes mostly from the semantic layer underneath, not the model on top.

Key Takeaway:

Generated semantic models are validated by reproducing known-good report numbers, never by reading the YAML. Collect the ground-truth numbers before you generate, and chase every delta to a written root cause.

Verify before you trust it

  • All ground-truth numbers reproduce exactly or with a documented, owner-accepted explanation.
  • Every join in the model matches a key relationship provable in the data (SELECT count(*) FROM fct_orders o LEFT JOIN dim_customers c USING (customer_id) WHERE c.customer_id IS NULL returns what the stated cardinality implies).
  • Each metric's assumption comment has been confirmed or corrected by a named owner — record who, in the PR.
  • Two differently-phrased queries for the same metric through the layer return identical numbers (the whole point of the layer).

Pitfalls

  • Fan-out joins inflating measures. A one-to-many join the model guessed as one-to-one silently doubles revenue. Always verify inferred cardinality against the data.
  • Codifying a broken dashboard. If your ground-truth source was itself wrong, the layer faithfully reproduces the error. Cross-check ground truth against two independent sources where stakes are high.
  • Metric sprawl by generation. It is now cheap to define 200 metrics; governance cost scales with count. Draft broadly, but publish only owner-approved metrics.
  • Time-grain ambiguity. "Monthly revenue" on order date vs. payment date differs materially. Force the model to state the time dimension per metric and confirm each.
  • Skipping re-validation after mart changes. The layer is downstream of the marts; without the CI check, a mart refactor breaks metrics silently.

Tools

  • dbt Copilot (Semantic Layer generation)first-party drafting from project metadata for dbt platform users; dbt Core + MetricFlow with a generic assistant is the free path.
  • Claude Code / Cursorrepo-scale drafting when you need custom conventions or a non-dbt target (Cube, Snowflake semantic views).
  • Warehouse CLI / dbt sl querythe validation harness; whatever executes metrics so numbers, not YAML, get reviewed.

Client-safe variant

For client work, the ground-truth numbers are the sensitive artifact — real revenue figures should not appear in prompts to external APIs. Generate the semantic model from structure only (SQL + schema), run all numeric validation inside the client's environment, and if an external assistant is prohibited entirely, use the client's in-platform option (dbt Copilot, Genie) or a self-hosted model. Deliver the validation matrix (metric × ground-truth source × match status × sign-off owner) as part of the engagement artifacts — it doubles as UAT evidence and makes the semantic layer auditable after you roll off.

This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in