後端有一個 MCP server,上面掛了上千個內部 API。老闆要的不是「資料」,是一頁點開就看到重點的儀表板。中間這段——讓 AI agent 把上千個 API 收斂成語意模型、再自動「畫」成 Power BI 報表——聽起來理所當然,實作起來卻卡在一道很多人沒注意到的牆上。這篇是我把它走通後留下的東西:方法論、繞牆的思路,和一整批靜默失敗的踩雷。
官方 Power BI MCP 只能建/改語意模型(表、度量值、關聯),碰不到報表畫布;Copilot 能生報表頁但要 Fabric 容量、不能改樣式。可行的第三條路:讓 agent 手寫 .pbip 專案——TMDL 定義語意模型、PBIR 定義每個視覺,本地 Desktop 直連活資料,雙擊一鍵開。
- 硬分界:語意模型層(官方 MCP 可改)vs 報表視覺層(官方 MCP 完全碰不到)。
- 不靠 Fabric、不靠 MCP 也能自動產報表:直接生 PBIR + TMDL,本地 Desktop 直連。
- 兩種交付:貼 Power Query(臨時)vs 手寫 .pbip(老闆一鍵開)。
- 坑幾乎全是靜默失敗:不報錯、只是空白或被略過 → 自驗機制比多試重要。
- 報表要有用:數據佐證 → 根因 → 可行動,別把原始欄位丟給老闆自己數。
「老闆要一頁儀表板」背後的真實工程
先說結論:瓶頸不在畫圖,在中間層。老闆看到的是一頁儀表板,agent 真正要幹的活是——把上千個異質 API 的欄位、代碼、單位收斂成一個穩定的語意模型,BI 那端反而是下游。
這個「上千 API 的後端」就是我先前寫的資料市集 MCP。怎麼在成百上千個資料集裡找到對的那幾個,見〈用 MCP 讓 AI 在 1288 個資料集裡找出我不知道的資料〉;這篇是續集:資料找到了,怎麼變成老闆看得懂的儀表板。
內部 API 後端(上千 API,MCP)
│ agent 探數、挑欄位、決定口徑
▼
語意模型層(TMDL:表 / 度量值 / 關聯)
▼
報表視覺層(PBIR:每個圖表一個檔)
▼
本地 Power BI Desktop(直連活資料,一鍵開)
官方 MCP、Copilot、第三方到底能不能建報表
動手前先查一輪:市面上號稱「AI 自動產 Power BI 報表」的方案,到底哪些真能建出報表視覺,哪些只是問答。關鍵欄位是「能不能建視覺」,不是「能不能碰資料」。
| 方案 | 能建報表視覺? | 成熟度 / 限制 |
|---|---|---|
| 官方 Modeling MCP | 只能建語意模型 ❌ | Public Preview;碰不到畫布 |
| 官方 Remote MCP | 只讀查詢 ❌ | 不能改任何東西 |
| Power BI Copilot | 能生報表頁 ✅ 但受限 | 需 Fabric 容量、不能改樣式、定位是助手 |
| Fabric agentic skills | 能端到端 ✅ | Preview;仍依賴 Desktop |
| 第三方 report MCP | 能生視覺 ✅ | 年輕、僅本地、已知 render bug |
| 手寫 PBIR / TMDL | 可行 ✅(本文走這條) | 免 Fabric、可版控、Pro 即可跑 |
最需要打假的是 Copilot:它確實能從自然語言生報表頁(不只問答),但需要 Fabric 容量、不支援自訂視覺、不能做樣式,定位是「kick-start 助手」。公司若沒有 Fabric 容量(按鈕根本不亮),這條直接斷——同樣的地端/成本現實,見〈企業 AI Agent 治理〉。
方法論:五條可遷移的思考框架
這篇如果只帶走一段,帶這段。以下五條不只適用 Power BI——任何「讓 AI agent 操作某個工具、產出東西」的任務都套得上。
- 先定位分層,再選工具:先找出工具的能力分層(Power BI = 語意模型層 vs 報表視覺層),再問「我要碰哪層、官方給不給」。這步省掉大半瞎試。
- 研究先打假:每個「AI 自動做 X」的宣稱都分三類——已驗證可行 / 還在 preview / 行銷話術。Copilot 能建報表但要 Fabric、不能改樣式 = 半行銷。
- 繞牆,不要撞牆:官方碰不到視覺層,就別硬等官方——直接生它的公開檔案格式(PBIR/TMDL 有公開 schema)。
- 交付分模式:臨時探索 vs 老闆一鍵固定,是兩種交付,別一招硬套。
- 分析要有口徑:佐證 → 根因 → 可行動;視覺標題下結論;別把子集當全體。
靜默失敗的領域,自驗比多試重要
這是我從一堆坑裡提煉、最想留下的一條。手寫 PBIR/TMDL 踩的坑幾乎全是靜默失敗:預覽開關沒開→存檔刪掉報表夾、schema 版本太新→略過整夾、綁定名拼錯→空白,沒有一個會報錯。
在這種領域「多試幾次」沒用——你根本不知道哪裡錯了。真正救命的是自驗機制:
- 產生器結尾把每個檔重新讀一次,全部讀得過才算成功;
- 生成前把「要綁的名字」跟語意模型的實際名字對一遍(拼錯不報錯只空白);
- 讀 Desktop 存過的檔案反推這台的版本上限,手寫版本別超過它。
這條通則不限 Power BI:凡是「AI 生成 → 丟給另一個系統吃」的工作,失敗常是靜默的,驗證機制要跟生成機制一起設計。
關鍵分界:語意模型層 vs 報表視覺層
Power BI 內部分成兩層,分界非常硬,幾乎所有工具只做其中一層。看懂這張表,上面那堆方案的能力邊界就全解釋得通了。
| 層 | 內容 | 官方 MCP 能做? |
|---|---|---|
| 語意模型層 | 表、欄位、度量值、關聯 | 可以建/改 ✅ |
| 報表視覺層 | 頁面、圖表、卡片、slicer、儀表板 | 完全碰不到 ❌ |
所以「讓 agent 自動產報表」的難點,就是官方 MCP 給不了的那一層。
第三條路:手寫 .pbip(PBIR + TMDL)
.pbip 是 Power BI 的「純文字專案格式」。它把一份報表拆成兩組可版控的文字檔:TMDL 定義語意模型,PBIR 把每一個視覺拆成獨立檔——裡面宣告視覺類型、欄位綁定、排序。代表 agent 不必開 Desktop,就能用結構化檔案生出指定圖表。
部署走本地:雙擊 `.pbip`,Desktop 直連內部 API 抓活資料,刷新即現。無 Fabric 容量也沒關係,Power BI Pro 就能跑,只是 Copilot 按鈕不亮。
Desktop → 選項 → 預覽功能,開兩個獨立開關:① TMDL 格式、② PBIR enhanced metadata,開完完全關閉再重開才生效。第②個沒開是頭號雷——它會刪掉你的報表,後面踩雷全集會講。
兩種交付模式:貼 Power Query vs 手寫 .pbip
依「老闆要不要一開就看到」分兩種交付:
| 模式 A:貼 Power Query | 模式 B:手寫 .pbip | |
|---|---|---|
| 使用者操作 | 開 Desktop → 貼查詢 → 填金鑰 | 雙擊 .pbip → 填金鑰 → 刷新 |
| 圖表 | 使用者自己拖 | 預先排好整頁,一開就見 |
| 交付物 | 一段查詢 + 操作指引 | 一個完整專案資料夾 |
| 適用 | 快、臨時、單表探索 | 老闆要「一開就知道」的固定儀表板 |
第一步:從內部 API 拉活資料
重點不是 code,是形狀。多數企業 API 閘道長同一個樣:
- POST + 巢狀 body:身分審計 / 分頁 / 查詢條件三段,不是 query string;
- 先探總數再分頁:先要一小頁拿總筆數,算出頁數再逐頁抓、每次節流;
- 金鑰放 HTTP header,Power BI 資料來源認證選「匿名」;
- 日期用斜線格式,dash 會被當查無資料。
看懂這個形狀,換任何 dataset 都一樣。每個檔要做什麼,文末附錄用 pseudocode 一條條列。
三個實測血淚(寫任何衍生欄前務必對齊):
| 雷 | 症狀 | 修法 |
|---|---|---|
| 日期格式 | 用 dash → 查無資料 → 後續運算報 Null 錯 | 務必斜線 `YYYY/MM/DD` |
| 把「查無資料」當錯誤 | 回查無資料,其實金鑰/認證都對 | 那是條件回空,調日期區間,別動金鑰 |
| 認證方式 | 閘道回 401 顯示成「認證無效」 | 資料來源選匿名,金鑰走 header |
第二步:語意模型與度量值口徑
度量值 = 老闆能問、能看的「指標語言」。名字取好,老闆問「不良率」它直接回一個數,而不是把整欄丟出來讓他自己數。設計原則:先建基底(計數)→ 再疊比率 → 再用條件細分,別重複寫邏輯。
在 DAX 查詢檢視批量建立後,要逐條點每條下方浮出的「更新模型:新增量值」;別點頂部「使用變更更新模型 (0)」——那是改既有度量值用的,新增時永遠是 (0)。
① 累計欄(遞增值)要用「每個維度取最大再加總」,別直接 SUM。
② 瞬時值對時間軸要用平均,不是加總——加總會被每格樣本數灌大 N 倍(能源案真的被灌 ~30 倍)。
第三步:用產生器生報表視覺(PBIR)
不要手刻十幾個檔——用一支產生器把「視覺清單」轉成一堆視覺檔。綁定規則要釘死,拼錯會靜默空白:
| 視覺 | 類型 | 欄位角色綁定 |
|---|---|---|
| KPI 卡 | card | 用 Values(別用較新的 cardVisual,舊版靜默不畫) |
| 切片器 | slicer | Values |
| 長條/折線 | barChart / lineChart | Category(+Series)+ Y |
| 環圈 | donutChart | Category(圖例)+ Y(值) |
產生器邏輯很單純:定義視覺清單(座標 + 綁定名 + 標題)→ 迴圈產檔 → 結尾自驗。完整 pseudocode 見附錄 E。
手寫 PBIR/TMDL 的踩雷全集
這是整篇最值錢的一段——每一條都是開檔失敗、圖不見、或靜默空白換來的:
| 雷 | 症狀 | 原因 / 修法 |
|---|---|---|
| PBIR 開關沒開 | 存檔後報表夾不見、只剩空白頁,但模型照常載入 | 前置②沒開 → Desktop 存檔刪掉報表夾。先開開關再存 |
| schema 版本太新 | 整個視覺夾被靜默略過、開空白頁、無錯誤 | 讀 Desktop 存過的檔反推這台版本上限,手寫版本要 ≤ 它 |
| 版本號格式 | 版本寫兩段驗證失敗;寫太新被略過 | 用已驗證可用的版本號,別自行調高 |
| 卡片綁定用錯 | KPI 卡靜默不畫 | 用舊版 card,別用較新的 cardVisual |
| 新舊格式併存 | 頂層冒出多餘的報表檔 | 新舊格式互斥,把多餘的頂層檔刪掉 |
| 金鑰含控制字元 | HTTP 報「無效 Control 字元」 | 貼上的金鑰夾了換行 → 清成純可列印 ASCII 再進 header |
| TMDL 縮排 | 解析失敗 | 純 tab 縮排,禁 tab/space 混用 |
| qnaVisual | 微軟 2026/12 淘汰 | 新報表別當主力,改用篩選器互動 |
退路:某個視覺檔壞掉會讓整份報表開不了——刪掉那個視覺的資料夾重開即可,其餘視覺仍在。最脆的是 donut,最穩的是 KPI 卡 + 切片器,優先保。
MCP 能做與不能做的邊界
若想用官方 modeling MCP 讓 agent 改模型,先記住三條邊界:
- 只碰模型層:能建度量值/表/關聯,碰不到報表畫布(所以才要手寫 PBIR)。
- 橋接會斷:徵兆是工具整組消失。在同一對話重試無效——開新對話才會重載 MCP。
- 吃 context:掛上去約吃掉 agent 三成 context window。
- 要手動存檔:MCP 的變更寫在記憶體模型,要在 Desktop Ctrl+S 才進檔。
兩台 MCP 分工:一台探數、一台改模型;視覺層兩台都做不到,才需要手寫 PBIR 補最後一塊。MCP 分層取捨見〈Agent 版 MVC:A2A、MCP、Hub 的分層與取捨〉。
分析要有口徑:佐證 → 根因 → 可行動
報表能生出來,不代表有用。每個視覺都要能走完「數據佐證 → 根因 → 可行動」,別只把原始欄位丟上畫布讓老闆自己看。
最具體的落地:視覺標題要下結論,不要只描述。
| 寫法 | 範例 |
|---|---|
| ❌ 描述句 | 「某指標 依據 某維度」 |
| ✅ 結論句 | 「某工站是主要問題源:異常率 49.8%,全廠 6.5 倍」 |
三段口徑套在儀表板上:①佐證先用整體數字把問題定住 → ②根因切維度找出集中在哪(某工站異常率飆高、少數幾種問題占八成)→ ③可行動對集中點開改善案、對嚴重少數逐筆追。
決策樹:雲端、本地、Copilot 還是手寫
該走哪條路,三個問題就分完:
沒有 → 往下
只是臨時探索 → 模式 A:貼 Power Query
Power BI vs Tableau:誰對 agent 更友善
兩邊的官方 MCP 都只能唯讀查詢,不能建視覺;差別在檔案格式路徑:
| Power BI | Tableau | |
|---|---|---|
| 官方 MCP | 唯讀查詢 | 唯讀查詢 |
| agent 建視覺路徑 | 官方文件化 PBIR + Fabric agentic skills | 第三方生 .twb XML |
| 對 agent 友善度 | 略勝:官方在鋪路 | 可行但無官方加持 |
結論:兩邊都不算成熟,但 Power BI 因為有官方文件化的 PBIR schema 和官方 agentic skills,對「agent 自動產報表」略友善——這也是我選手寫 PBIR 的原因。
常見問題 FAQ
官方 Power BI MCP 可以讓 AI 自動建報表嗎?
不行。官方 Modeling MCP 只能建/改語意模型,Remote MCP 只能唯讀查詢,兩者都碰不到報表視覺層。要 agent 產出報表視覺,得走手寫 PBIR 或 Copilot/Fabric agentic skills。
沒有 Fabric 容量還能用 AI 產 Power BI 報表嗎?
可以。手寫 `.pbip`(PBIR + TMDL)由本地 Power BI Desktop 開啟,直連 API 活資料,Power BI Pro 就能跑,不需要 Fabric 容量——只是 Copilot 按鈕不會亮。
PBIR 手寫最容易踩的坑是什麼?
兩個:① PBIR 預覽開關沒開,Desktop 存檔會刪掉手寫的報表夾;② schema 版本寫太新,整個視覺夾被靜默略過開出空白頁。
為什麼度量值放在明細表會出現 100% 這種怪值?
率只在彙總層級有意義。放在逐列明細時每列樣本太小、分子分母篩選層級不同,就會冒出 100% 甚至更離譜的值。率交給 KPI 卡或彙總視覺,明細表只留計數。
附錄 A:兩台 MCP 的角色 + API 存取形狀
這份附錄是給「想自己做」的人的 —— 只講要做什麼和每個檔的 pseudocode,不放可跑的真 code、不放端點與欄位。
探數 MCP : find / describe / query dataset —— 看有哪些資料、schema、值域
建模 MCP : 建表 / 度量值 / 關聯 —— 碰不到報表畫布
API 存取形狀(每家閘道細節不同,重點是形狀):
方法 = POST,參數放 body 巢狀 JSON(不是 query string)
body = { 身分審計, 分頁資訊, 查詢條件 } 三段
認證 = 訂閱金鑰放 HTTP header;資料來源選「匿名」
回傳 = 總筆數 + 資料陣列 + 本頁筆數
節流 = 逐頁請求間隔數秒;日期用斜線格式(dash 會查無資料)
附錄 B:資料層(Power Query)pseudocode
1. 參數化 : 端點、金鑰、身分、日期區間、每頁筆數(金鑰=機密 → 做成參數)
2. 金鑰清洗 : 只留可列印 ASCII(去換行/控制字元,否則 header 被拒)
3. 探總數 : 送最小一頁 → 讀總筆數 → 算頁數
4. 分頁抓 : for 每一頁 → POST → 取資料陣列 → 合併(每次節流)
5. 展開 : 巢狀 record 陣列 → 正常表格
6. 衍生語意欄 : 原始碼 → 分析欄
· 代碼對照(狀態碼 → 中文)
· 布林分類(多值 → 是/否,方便算比率)
· 計算欄(欄A - 欄B)
· 前綴分群(細粒度 → 大類當維度)
· 日期正規化(轉成日期型)
附錄 C:度量值(DAX)pseudocode
· 在 DAX 查詢檢視批量宣告度量值,一次建多條
· 執行後【逐條】點「更新模型:新增量值」
✗ 別點頂部「使用變更更新模型 (0)」(那是改既有的,新增永遠 0)
· 設計順序 : 基底計數 → 疊比率(分子/分母)→ 條件細分
· 口徑雷 : 累計欄 = 每個維度取最大再加總(別 SUM);瞬時值對時間軸 = 平均(別 SUM)
附錄 D:語意模型層(TMDL)—— 每個檔做什麼
<名>.pbip 進入點;宣告格式版本;指向 .Report 資料夾
.platform 項目中繼(標記這是語意模型)
definition.pbism 語意模型定義屬性
database.tmdl 相容性層級
model.tmdl 語系;引用每張表與參數
expressions.tmdl 金鑰/身分 → 宣告成「參數」(值 = placeholder,絕不寫真實金鑰)
tables/<表>.tmdl ① 度量值定義 ② 欄位型別 ③ 資料來源分割(直連 API)
⚠ 純 tab 縮排,禁 tab/space 混用
附錄 E:報表層(PBIR)—— 每個檔做什麼 + 產生器邏輯
.Report 檔案樹(每個檔的職責):
報表定義檔 報表指回語意模型
版本檔 版本號(釘死在 Desktop 實測可用值;太新會被靜默略過)
報表設定檔 主題、設定
頁清單 頁順序
頁定義 頁尺寸 / 名稱
視覺檔 xN 每個視覺一個檔
視覺檔要放什麼(知道要什麼,不是照抄):
· 視覺類型:card / barChart / donutChart / slicer
· 欄位角色綁定:card‧slicer→Values;bar‧line→Category(+Series)+Y;donut→Category+Y
· 標題 = 一句「結論句」
產生器 pseudocode:
1. 定義視覺清單:每個視覺 = 座標 + 綁定的度量/欄名 + 標題
2. for 每個視覺 → 產出一個視覺檔
3. 寫進入點檔(報表定義 / 中繼 / 版本 / 設定 / 頁)
4. 自驗:把每個檔重新讀一次,全部讀得過才算成功
⚠ 綁定名必須在語意模型真的存在(拼錯靜默空白)→ 生成前對名
附錄 F:RUNBOOK 六階段
- 前置:Desktop 開兩個預覽開關(TMDL + PBIR),完全關閉再重開。缺 PBIR 開關 → 存檔刪報表夾。
- 探資料:用探數 MCP 看值域、代碼、累計欄、總筆數,決定衍生欄與口徑。
- 建語意模型:寫 TMDL(附錄 D),金鑰/身分參數化(placeholder)。
- 建報表:用產生器(附錄 E),綁定名先對過語意模型。
- 進入點:寫 `.pbip` + `.gitignore`(排除快取、本機認證、真實金鑰)。
- 開檔驗收:雙擊 → 填金鑰 → 刷新;成功判斷 = 報表仍是資料夾格式、沒冒出多餘頂層檔。
- 走穩:存檔→關→重開→刷新;綁定 vs 語意模型逐一稽核;push 前金鑰還原 placeholder。
附錄 G:一頁互動與 Q&A
· 加視覺前【先點空白畫布】取消選取,否則新欄位被塞進當前視覺(篩選器變兩欄、圖吃錯維度)
· 老闆兩種用法:用點的(篩選器)+ 用打字的(Q&A 視覺)
· 為每個度量值/維度加【同義詞】與【描述】,Q&A 才聽得懂人話
· 無 Fabric → Copilot 不可用;Q&A 免容量但微軟 2026/12 淘汰 → 新報表以篩選器互動為主
發佈留言