top of page

How I add descriptions and synonyms to a model

  • Jul 1
  • 4 min read

First part of the tool. All it does is add descriptions and synonyms to objects that are already there. Copilot and Q&A are only as good as the metadata behind them, and most models have almost none. Not because anyone decided against it, it's a boring long process, especially when the model is big with many attributes. So it mostly doesn't happen, and the model has nothing for Copilot to work with other than assuming things.


What the model already tells you


The first thing I realised, writing the generator, is that a model tells you far more about itself than people use. I just had to read four things and turn them into a sentence.


The names tell you a lot. country_name is a country name, is_eu_member is a true/false flag, a dim_ prefix says this is a dimension. The data types add more: a decimal is different from a date or a boolean. For measures, the DAX tells you what the measure does, SUM(...) is a total, DATESYTD(...) is year-to-date. And the relationships place each table: a key gets described as one, a dimension by what it links to.


Put together, a dimension table comes out as "The Country dimension stores descriptive attributes for country. It is related to: Trade, Services, FDI." A measure comes out as "Total Exports calculates the sum total of exports value in GBP billions." It's not pretty, but it's accurate, consistent, and much better than a blank field.


The Power BI model view with a column selected, its generated description shown in the Properties pane alongside the renamed tables listed in the data pane.

One rule I was firm about: it never overwrites a description someone wrote by hand. It fills in what's missing and leaves the rest alone.


Synonyms


I added synonyms almost as an afterthought, and they turned out to be the most useful part for models I couldn't restructure.


A column called country_code_iso2 is never going to read well. You might not want to rename it today, renaming is its own project, and it's the whole of part three. But you can give it the words people use. The toolkit generates aliases so that "country", "iso code", and "country code" all resolve to that field, without touching its actual name. It's the practical answer for a model you're not ready to restructure: keep the names, add the words, and let Copilot understand how people actually ask.


The business glossary


Rules can only work from what's in the model. Some meaning isn't in there at all, the names can't tell you what your team actually calls something. So I gave the toolkit a glossary: a YAML file of your own definitions that override the generated text.


tables:
  fact_orders: "Transactional order header records from the ERP system."
columns:
  "*.arr": "Annual Recurring Revenue in USD, from active subscription lines."
  "fact_orders.net_revenue": "Order revenue after discounts and refunds, excluding VAT."
measures:
  "Summary.Total ARR": "Sum of ARR across all active accounts at period end."
patterns:
  "(?i)_arr$": "Annual Recurring Revenue value."

It matches exact first, then wildcards, then regex, all case-insensitive. So you define ARR once and it lands on every column that has it, and you can still override one specific field when it needs its own wording. The glossary stays on your machine. It's your business's language, and it should be.


Scoring the model for readiness


I didn't want to go by "that looks better", so I made the toolkit score the model out of 100. It weighs description coverage, synonym coverage, and quality, then gives you an overall number, a per-table breakdown, and a list of the objects pulling it down.


It also gave me a list I could actually work through, and a before-and-after I could show a client.


Writing it back safely


Generating the text is the easy part. Writing it into a model people use is where I was careful, because I've broken a live model before and I don't intend to again. So this runs through the same path as everything else in the toolkit: pull the current TMDL, generate, write to a staging copy, back up, check it, and produce a before-and-after for review. Descriptions land as /// doc-comments, synonyms merge into the linguistic metadata behind Q&A, and nothing touches live until someone promotes it on purpose.


The before-and-after report lists every object with what it had, what it got, and whether the text was generated or kept. On a 20-table model with almost no descriptions, it wrote 168 and preserved the 35 that were already there:


The before-and-after descriptions report: 203 objects, 168 generated and 35 preserved at 100% coverage, with the before and after text for every table, column, and measure.

What the rules can't do


I want to be honest about the limit. "Total Exports calculates the sum total of exports value in GBP billions" is correct. "Total UK exports of goods and services, balance-of-payments basis, in GBP billions" is what an analyst would actually write, and a rule can't know your team calls it the balance-of-payments figure, because it doesn't know your domain. That's where the chat-agent version from part one comes in: it reads the whole model and writes something that sounds like your business. That one isn't in the repo, you do it with your own prompts.


The no-AI version in the repo gives you the generator, the glossary, the readiness score, and the safe write-back. For most models that's enough to take a model from no descriptions to genuinely useful in an afternoon.


If your model is missing its descriptions, this is the place to start. It's safe, it's reviewable, and Copilot is noticeably better the same day.

Comments


bottom of page