三語都發布成功了,英文程式碼區塊卻不見了:翻譯輸出的結構漂移沒被察覺

週日晚上八點跑完流程,發布腳本記錄三語全部成功,封面圖也正確關聯。隔天早上讀者留言說英文版裡那段 curl 範例是一整塊純文字,沒有換行也沒有語法突顯,複製貼上後根本無法執行。回到 CMS 檢查原文,發現英文的 content_md 欄位中, 圍欄符號完全消失——翻譯步驟將程式碼區塊拆解成一般段落,並混入上下文中。

專屬插圖
三語都發布成功了,英文程式碼區塊卻不見了:翻譯輸出的結構漂移沒被察覺

三語都發布成功了,英文程式碼區塊卻不見了:翻譯輸出的結構漂移沒被察覺

週日晚上八點跑完流程,發布腳本記錄三語全部成功,封面圖也正確關聯。隔天早上讀者留言說英文版裡那段 curl 範例是一整塊純文字,沒有換行也沒有語法突顯,複製貼上後根本無法執行。回到 CMS 檢查原文,發現英文的 content_md 欄位中,``` 圍欄符號完全消失——翻譯步驟將程式碼區塊拆解成一般段落,並混入上下文中。

現場還原

我們的三語流程是:以 zh-CN 為原始稿件,router 呼叫模型翻譯出 zh-TW 和 en,再使用同一個 slug 向 CMS 發送三筆資料。出事當天,中文原稿中包含一段 yaml 設定與兩行 curl 指令,這在交付文件中極為常見。這個普通內容恰好暴露了兩個薄弱環節:

- 翻譯 prompt 僅寫著「保留 markdown 格式」,後續沒有任何驗證機制

- 發布腳本只檢查 HTTP 200,但 200 仅代表「我已接收並寫入」,不代表「結構正確」

對模型而言,將圍欄區塊融入段落是一種「低風險改動」:語意未變,token 數量也相近,在 temperature 0.3 的設定下,完全可能產生這種變體。更糟糕的是,前端渲染出的 HTML 看起來尚可閱讀,若不逐字對照原文,根本無法發現問題。

補上的這道關卡

我們在三語資料進入 CMS 之前,增加了一個結構指紋比對機制,指紋由三個清單組成:

1. 標題層級序列(h1/h2/h3 的順序與數量)

2. ``` 圍欄區塊的數量,以及每個區塊的第一行和最後一行

3. 表格數量及每張表的列數

先從 zh-CN 提取基準值,再分別從各譯文中提取一次,逐項比對。若不符則自動重新翻譯一次;若重翻後仍不符,則攔截該語言版本並發出警報,不強制發布——寧可缺少一個語言版本並提醒人工補件,也不能發布結構損壞的版本。實作非常輕量:指紋提取僅是一個逐行掃描的函式,diff 則是比較三個元組,總計不到一百行程式碼。它防範的不是罕見的邊緣案例,而是「同一個 prompt 在長尾情況下仍差一步」這類變化。

這裡有個容易踩到的坑,分享我們自身的經驗:最初只比對「圍欄區塊數量」,結果連續兩天出現誤報——一次是譯文將圍欄外的一行說明文字併入區塊內,另一次是區塊內少了一行結尾。僅比對數量無法捕捉「多出一對圍欄」或「區塊內容被移走」的情況,因此每個區塊的錨點必須包含首尾內容。閾值也不宜一開始就設得太嚴格:建議先平行運行一週,僅記錄日誌而不攔截,根據實際的漂移分布制定規則後,再升級為強制門禁。

數據

平行模式運行十天的記錄顯示:13 筆翻譯產出中,9 筆一次通過,4 筆出現結構漂移。漂移類型全部落在同一類別——標題數量正確,但圍欄內容被合併、列表被改寫成段落文字。將門禁機制從「整單攔截」調整為「單一語言自動重試一次 + 保留 diff 日誌」後,第二次通過率達到百分之百,人工介入次數為零。初期通過率看似不低,但失敗模式高度集中,顯示這道關卡攔截的是真實問題,而非雜訊。

給同行者的建議

如果你的管线中也使用 LLM 進行翻譯或改寫,別把「模型聲稱它保留了格式」當作驗收標準。只需十分鐘即可搭建結構 diff 機制:從原稿和每份譯文中分別提取標題序列、圍欄區塊、表格這三個指紋,並逐項比對。好處在於問題能在進入生產環境前被攔截,而且你手中掌握上下文資訊——哪個語言、哪一個步驟、具體的 diff 位於何處。內容管线的成本與工程維運相同,難點不在於單一步驟有多困難,而在於每一步「看起來都還行」,但「看起來」不等於「經過驗證」。

留言區

歡迎分享你的想法!

發表留言

0/500

載入留言中…