iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
AI Engineering

AI Guardrails 實戰:用合成資料與評估,打造可驗證的 LLM 應用防護流程系列 第 8 篇

[Day 8]:不要叫模型一次生成:合成 PII 測試資料時拆成可追蹤的階段任務(Stage)

  • 分享至 

  • xImage
  •  

昨天 Day 7 的文章先把一筆 Guardrails 測試案例寫成種子資料(Seed Contract),分清楚哪些條件要固定、哪些內容可以變化,以及哪些資訊不能交給模型自行生成而產生幻覺(Hallucination)。

有了種子資料(Seed Data)下一個直覺做法(又是直覺)通常是把所有要求塞進同一個 Prompt:然後請模型生成含 PII 的客服對話、再產出去識別化版本、列出偵測到的實體、一起回傳標註結果,最後一次拿到完整 JSON,看起來省事、也很像已經有一筆可以拿去測 Guardrails 的資料。

問題是:如果輸出錯了,要從哪裡查起?是 LLM 生成有問題、去除 PII 有問題?還是出在哪裡?

假設原文漏掉 Seed 指定的電話,去識別化版本當然也不會出現電話,實體清單更不會把它標出來;三份結果看起彼此完全一致,卻一起偏離了測試目的。更進一步說╴模型也可能在去識別化時順手改寫句意,再依改寫後的內容產生一份看似合理的標註;如果只看最後輸出,很難判斷問題出在原文生成、去識別化,還是標註。

所以今天先不增加 Prompt 細節,而是把一筆 PII 測試資料拆成幾個可追蹤的生成階段(Stage)。

https://ithelp.ithome.com.tw/upload/images/20260921/201418857GlXjrnJOW.png

筆者認為生成資料這件事情很容易發生「差之毫釐,謬以千里」的問題(血和淚的教訓啊

拆開 Stage,不只是把一個 Prompt 切成三段

NVIDIA NeMo Data Designer 的設計原則把合成資料生成視一個又一個的工程步驟與階段、而不是一個包辦所有工作的任務;每個階段只處理一項明確工作,留下對應的輸出作為檢查,在品質無虞後續才繼續進行下一步驟的工項。

筆者認為一個 Stage 至少要說清楚四件事:

  • 它接收什麼輸入 —> 使用甚麼甚麼資料作為生成的輸入
  • 它只負責完成哪一項工作 —> 具體處理的步驟是什麼? (生成、後處理、改寫、遮罩、etc.)
  • 它必須留下什麼輸出與版本資訊 —> 生成的格式是什麼?有哪些 schema 或 contract 需要檢核?
  • 哪些判斷不屬於它,不能順手一起做掉 —> 應該叫反向案例;生成的資料有沒有不能觸碰的原則?

https://ithelp.ithome.com.tw/upload/images/20260921/201418853fMh0WIZ0U.png

這個分法跟「呼叫幾次 LLM」不是同一件事;某個 Stage 可以使用 LLM,也可以只做確定性的字串轉換;同一次模型呼叫若同時生成原文、遮罩、標註又替自己評分,責任仍然混在一起。Stage 的重點是資料責任與可檢查的產物(Artifact),不是 LLM API 呼叫次 / 執行了多少次。

用合成 PII 資料拆出三個 Stage

沿用前文的地址變更客服案例,Seed 已經固定任務、目的端、允許使用的虛構資料與預期處置。今天把資料生成拆成三個 Stage:含 PII 原文、去識別化版本,以及候選實體標註。

Stage 輸入 只負責什麼 主要輸出 不應順手做什麼
1. PII 原文生成 Seed Contract、允許使用的虛構實體、表達變化條件 依任務生成一份含指定 PII 的原始客服內容 source_text、實際使用的虛構值、生成設定版本 不要遮罩、不要替 Guardrail 下 BLOCK/ALLOW 判斷,也不要宣稱標註已完成
2. 遮罩/去識別化(Redaction) 第一階段留下的原文、遮罩規則 移除或替換不應保留的敏感內容,同時保住原本任務語意 redacted_text、使用的占位符(placeholder)/轉換方式、設定版本 不要重新生成另一段客服情境,也不要用改寫後文字取代原文的標註基準
3. 候選實體標註 原始 source_text、實體類型定義、Seed 中已知的虛構值 找出原文中的實體類型、文字與位置 entity_candidates,包含 type、text、start/end 與來源依據 不要因為輸出格式正確,就直接把模型標註命名為最終 Ground Truth

https://ithelp.ithome.com.tw/upload/images/20260921/20141885tQTPyG3Wxb.png

第一階段若漏用 Seed 指定的地址,問題就停在原文生成;

第二階段若仍留下完整電話,先回頭看去識別化;

第三階段若文字找對、位置卻標錯,就檢查標註規則與索引方式。

每個 Stage 都留下自己的資料,才有辦法把「結果不對」縮小成可處理的問題

看到錯誤時,先回到負責的 Stage

觀察到的問題 先檢查哪個 Stage 第一個要問的問題
原文沒有出現 Seed 指定的地址或電話 PII 原文生成 第一階段是否收到正確 Seed,或把 must_use 當成可選條件?
去識別化版本仍保留完整 PII 去識別化 Redaction 規則是否涵蓋該實體與格式?
去識別化後已無法理解原本的客服任務 去識別化 第二階段是否把「移除敏感資訊」做成了「重寫或刪除整段內容」?
實體文字正確,但 start/end 指到錯誤位置 候選實體標註 第三階段是否對原文標註,且使用同一套索引規格?
原文、去識別化與標註各自合理,卻不是同一筆內容 無法只歸給單一 Stage 三個 Stage 是否真的引用同一個 record_id 與上游輸出?這是 Dependency 要解決的問題。

迷思:拆開生成之後是會比較快或成本比較低嗎?

通常在說這個階段的內容時,客戶很常會提問的地方是:「為什麼要分開生成?明明一口氣隨便用一個 prompt 就可以生成的內容,為什麼要分成那麼多步驟、那麼複雜?你是不是想要把簡單的事情複雜化? 」

umm 對,任何事物在分階段規劃 / 執行時通常意味著更多中間產物 (intermediate、或是叫副產物)、更多版本資訊(Metadata),也可能增加模型呼叫與儲存成本中;在你要生成的資料只有五筆案例、而且你本身 / 或是有領域專家能逐筆檢查時,一個 Prompt 加人工審閱可能更快,分階段生成(Stage )的確不是要考量的事。

https://ithelp.ithome.com.tw/upload/images/20260921/20141885xlWOxEYK7s.png

小結:拆開生成真正意義是工程面的複用性和相依性

筆者用 Pre-Train Model 時常用的 Chinchilla-style 來粗略估算「從零開始 Pre-training 一個 LLM,大概要準備多少資料」;

Training Tokens ≈ 模型參數量 × 20

一個 1B 的 Model 要 20B Token 的資料、以 500 字資料約 600 tokens 為例子,

大概等於 3,333 萬筆

如果換成 SFT(Supervised Fine-Tuning、監督式微調)約要 10M tokens

大約是 1.7 萬筆

當資料要累積到數百筆、拿來做回歸比較,或需要說明某筆資料為何合格時,只保存最後一份 JSON 的代價會開始浮現:錯誤無法定位、修正會連帶重跑全部工作,舊輸出也很難和新版本比較。

https://ithelp.ithome.com.tw/upload/images/20260921/20141885IkbIFlddgm.png

接下來真正棘手的問題是:如何保證 Redaction 與 Entity Candidate 都引用同一份 PII 原文,而不是三個 Stage 各自重新生成一份「看起來合理」的內容。Stage 先把工作拆開;Dependency 才會把這些工作接成同一條可重跑的資料路徑。

參考資料


上一篇
[Day 7]:先別寫 Prompt:先設計出資料種子(Data Seeding)來定義案例、邊界與資料分布
下一篇
[Day 9]:三份資料都合理,為什麼彼此對不起來?用 Dependency 把生成流程接成 DAG
系列文
AI Guardrails 實戰:用合成資料與評估,打造可驗證的 LLM 應用防護流程 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言