top of page

How I make a semantic model Copilot-ready

  • Jul 1
  • 3 min read

I set out to generate documentation for a semantic model, the kind you can hand over and someone can actually follow. But to document a model well it needs descriptions and sensible names first, and most models I get handed have neither. So the documentation job kept turning into a tidy-the-model job, and it grew into a small toolkit for making a model Copilot-ready. I'm sharing the toolkit here in case it saves you the same afternoons.


Here's the kind of thing I mean. Someone opened Copilot and typed "exports to Germany last year", and nothing useful came back. I looked at the model and understood why. There was a table called fact_trade_total_monthly, a column called value_gbp_millions, and not a single description anywhere. Copilot had nothing to go on, so it guessed, and then gave up.


It's the same gap on almost every model I get handed. The data is right, the model is fine, and it's no use to anyone who wasn't there when it was built.


I kept seeing two versions of the same problem.


The first is missing meaning. No descriptions, no synonyms, nothing that tells Copilot or Q&A what an object is. The model knows value_gbp_millions is a decimal. It doesn't know that's what someone means when they ask about trade value.


The second is cryptic names. The warehouse names come straight through into the model: dim_, fact_, _hmrc, _gbp. Every new report author has to learn what they all mean before they can build anything. And nobody fixes the names, because renaming a column on a published model breaks three reports.


What I built


I built two versions, and the one in the repo is the no-AI version. The chat-agent version you can do yourself pretty easily, with your own prompts, based on your preferences.


The scripts version, no AI. It reads the model's TMDL and writes a description for each object from what the structure already tells it: the name, the data type, the DAX inside a measure, the relationships a table sits in. It is rule-based and runs offline, no AI calls, the same model giving the same output every time. For a column called value_gbp_millions it writes something like:


Value in GBP millions. Decimal column on the monthly trade table.


Accurate, consistent, and a world better than a blank field. A little mechanical, because a rule can only describe what it can see in the structure of that one object.


The chat-agent version. This one hands the whole model's metadata to a chat agent (Copilot or Claude) and lets it read the picture: the table the column sits on, the measures built from it, the dimensions it relates to. Then it writes a description that fits the model, not just the column. For the same value_gbp_millions it writes something like:


Monthly UK trade value in GBP millions. The base figure behind the Total Exports, Total Imports, and Trade Balance measures, sliced by country, commodity, and trade flow.


That reads like someone who knows the model wrote it, because the agent saw the rest of the model, not just the one column. The trade-off is the obvious one: it is an LLM, so the model's metadata is shared with the agent, and you do not get the same line twice.


Both versions do the same jobs:


  • Write plain-English descriptions for tables, columns, and measures.

  • Generate synonyms so Copilot and Q&A follow how people actually ask questions.

  • Layer your own business glossary on top of the generated text.

  • Score the model out of 100 for Copilot readiness, and tell you what's pulling the number down.

  • Rename objects safely, across the model and its connected reports, checked with live DAX.

  • Produce before-and-after reports, so nothing changes without you seeing it first.


The Copilot Readiness report: an overall score of 81 out of 100, with description and synonym coverage at 100% and a per-object breakdown.


Nothing writes to the live model by default


It's always best practice to never overwrite without testing thoroughly, so this tool doesn't write anything to the live model. Every operation pulls the current TMDL, works on a staging copy, takes a timestamped backup, and checks the result. You see it first, and nothing goes live until you choose to promote it.


The Fabric workspace list showing the live SM_UKT_Import model alongside the auto-created STAGING copy that the tool writes to first.


The two halves work differently, on purpose. Adding descriptions and synonyms is the safe one: it only adds to objects that already exist and leaves anything hand-written alone, so it can't break the structure. Renaming is the riskier one: it touches DAX, relationships, security roles, and every report, so it gets its own impact check and its own validation before anything goes to production.


The next two posts take each half on its own. If your model is missing its descriptions, start with part two, it's the low-risk one. If your model works but the names are holding you back, part three is the one to read.

Comments


bottom of page