技術面完成了,今天處理制度面——也是這個系列裡最容易被工程師跳過、卻最可能決定專案生死的一天。
昨天談的是「怎麼做得又快又便宜」,今天談的是「怎麼確保這件事做得下去」。
三個時間點都可能發生的對話:
專案啟動時——法務:「這個系統會處理客戶個資嗎?資料會送到境外嗎?」
上線前——稽核:「如果模型做出錯誤判斷,你們怎麼追溯是哪個版本、什麼依據?」
出事後——主管:「為什麼業務部門的人可以看到人資的薪資文件?」
這三個問題答不出來,技術做得再好都上不了線——尤其在金融、醫療、公部門與大型製造業。
📊 職缺訊號
「治理、安全與權限」出現在 13.8% 的 MLOps 職缺中,是六項任務中倒數第二。但這個數字有個特性:它幾乎只出現在資深職缺。原因很直接——初階做被交辦的事,資深要對「這件事能不能做」負責。
治理的第一步不是讀法規,是盤點你到底面對哪些風險。用一張風險矩陣(可能性 × 衝擊):

圖 27-1:生成式 AI 系統十項典型風險的可能性 × 衝擊落點(依風險分數精算的示意評估)。分數 ≥ 15 的紅區項目不得以「已知悉」結案。
這張圖最重要的觀察,是落在紅區的三項:
這三項都不在傳統資安清單上。 你的公司可能已通過 ISO 27001、做過滲透測試、有完整的存取控制——但這三個風險,傳統資安框架完全沒有涵蓋。
這就是「AI 治理」必須獨立存在的理由。
很多台灣工程師覺得「歐盟法規關我什麼事」。有兩種情況它會直接關你的事:你的產品在歐盟提供服務,或你的客戶要求你符合(供應鏈傳導,這在台灣製造業特別常見)。

圖 27-2:AI 治理法規與標準的示意時程。歐盟時程依 AI Act 公布的階段適用日整理;臺灣《人工智慧基本法》於 2026 年 1 月 14 日公布,並自公布日起施行。圖中僅列關鍵節點,實際法遵義務仍須查閱主管機關最新公告。
對台灣團隊最需要注意的三件事:
💡 一個務實的作法:把判斷寫進 ADR
在專案的架構決策紀錄(Day 28 會談)中,明確寫下「本系統的風險分級判斷、依據與判斷日期」。這樣做的價值是:當法規更新或稽核詢問時,你知道要回頭檢查哪些系統、以及當初是基於什麼資訊做的判斷。
這比「等到被問才開始查」有效太多,成本卻只有十分鐘。
"""governance/rbac.py —— 權限要能同時管「功能」與「資料」。"""
from dataclasses import dataclass
@dataclass
class Permission:
can_query: bool # 能不能問
doc_levels: set[str] # 能看哪些機密等級
departments: set[str] # 能看哪些部門的文件
tools: set[str] # 能用哪些工具(Day 22 的風險分級)
can_export: bool # 能不能匯出/對外傳送
ROLES = {
"一般員工": Permission(True, {"public", "internal"}, {"own_dept"},
{"search_kb"}, False),
"部門主管": Permission(True, {"public", "internal", "confidential"},
{"own_dept"}, {"search_kb", "create_ticket"}, True),
"稽核人員": Permission(True, {"public", "internal", "confidential"},
{"all"}, {"search_kb", "export_audit"}, True),
}
def build_retrieval_filter(user) -> dict:
"""把權限轉成向量庫的查詢過濾條件——在檢索階段就擋掉(Day 18)。"""
p = ROLES[user.role]
f = {"level": {"$in": list(p.doc_levels)}}
if "all" not in p.departments:
f["dept"] = {"$in": [user.dept]}
return f
⚠️ 權限必須在檢索階段執行,不能在生成後過濾
有些團隊的做法是「全部檢索出來,再請模型不要提到無權限的內容」。這是錯的——一旦無權限的內容進入脈絡,就等於已經外洩了:模型可能間接透露、可能被注入攻擊套出、而且它會被寫進日誌與 trace。
權限的執行點必須在資料進入模型之前。
"""governance/pii.py —— 個資保護的中介層。"""
import re
PATTERNS = {
"ID": (r"[A-Z][12]\d{8}", "【身分證】"),
"PHONE": (r"09\d{2}[- ]?\d{3}[- ]?\d{3}", "【電話】"),
"EMAIL": (r"[\w.+-]+@[\w-]+\.[\w.]+", "【電子郵件】"),
"CARD": (r"\b(?:\d{4}[- ]?){3}\d{4}\b", "【信用卡】"),
}
def mask(text: str) -> tuple[str, dict]:
"""遮罩並保留還原對照(僅存在記憶體中,不落地)。"""
mapping = {}
for name, (pattern, label) in PATTERNS.items():
for i, m in enumerate(re.finditer(pattern, text)):
token = f"{label}{i}"
mapping[token] = m.group()
text = text.replace(m.group(), token)
return text, mapping
# 使用時機(三個都要):
# 1. 送進模型之前 → 避免個資離開組織/進入供應商
# 2. 寫入日誌之前 → 避免個資留在日誌與 trace(Day 22 的 trace 資料量問題)
# 3. 對外傳送之前 → 最後一道關卡(Day 25 的出站掃描)
"""governance/supply_chain.py —— 你下載的模型檔安全嗎?"""
# ❌ 危險:pickle 格式在載入時會執行任意程式碼
# torch.load("model_from_internet.pt") ← 這一行可能就是一個 RCE
# ✅ 安全:safetensors 是純資料格式,不含可執行內容
from safetensors.torch import load_file
weights = load_file("model.safetensors")
# 供應鏈檢核清單:
# □ 模型來源可信(官方帳號、有簽章或雜湊可驗證)
# □ 優先使用 safetensors 而非 .pt / .bin / .pkl
# □ 記錄模型的來源、版本、授權(AI BOM/模型卡)
# □ 定期掃描相依套件漏洞
# □ 商用前確認模型授權允許(有些開放權重模型禁止商用或有使用者數上限)
授權那一項在台灣特別容易出事:很多團隊直接拿知名的開放權重模型商用,卻沒讀授權條款——有些禁止商用、有些有月活躍使用者上限、有些要求標示。這是法務風險,不是技術風險,但由工程師的選型決定。
治理有成本,不是每個系統都要做到最高規格。用風險決定投入:
| 系統類型 | 治理投入 | 必做項目 |
|---|---|---|
| 內部工具、低風險(如程式碼助理) | 低 | 存取控制、基本日誌、模型授權確認 |
| 內部知識庫(含機密文件) | 中 | + 資料分級、檢索階段權限過濾、PII 遮罩、audit log |
| 對客戶服務的應用 | 中高 | + 內容安全、拒答機制、事件通報流程、對外揭露是 AI |
| 影響個人權益的決策(招募、信貸、醫療) | 高 | + 可解釋性、人工複核、定期公平性稽核、完整法遵評估 |
Audit log 該記什麼(最小集合):
時間、使用者身分、動作類型、輸入摘要(PII 已遮罩)、
使用的模型與版本、提示版本、檢索到的文件 ID、
工具呼叫與參數、模型的 reasoning、最終輸出摘要、
是否經人工審批、審批者
📌 給工程師的一句話
治理聽起來像是「別人的工作」,但它的執行點全部在你的程式碼裡:權限過濾在檢索函式裡、PII 遮罩在中介層裡、audit log 在你的服務裡、模型授權在你的選型決策裡。
法務可以告訴你「要做到什麼」,只有你能決定「怎麼做到」。 這也是為什麼這項任務出現在資深職缺——它需要同時理解制度與實作。
torch.load 可能是 RCE),並確認模型授權允許商用——這是由工程師選型決定的法務風險。