iT邦幫忙

2026 iThome 鐵人賽

DAY 9
0
AI Engineering

它說得頭頭是道系列 第 9 篇

# Day 9 — 第三類錯誤:每個零件都是真的,只是組錯了位置

  • 分享至 

  • xImage
  •  

昨天那 8 處錯誤,有一個共同點,而我昨天只點到一句:

它們全部都被抓到了。

今天要講的是另一類錯。它沒有出現在那 8 處裡面——因為我的方法根本抓不到它。


先看兩個例子

Day 1 講過這兩處,但當時它只是一個故事。今天要把它變成一個類型。

例一:

原本在 A 頁面的甲功能,被寫進了 B 頁面。

例二:

原票卡寫的是「當數量 < 2」,統整之後變成「< 6」。

現在請用昨天那套方法來查查看。


拿我自己的驗證方法來測它

Day 7 的做法是:把文件拆成一條一條可查證的宣稱,然後去程式碼裡比對。判準必須二元。

好,拆:

宣稱:「B 頁面有甲功能。」

  • 甲功能存在嗎? → 存在。 它是一個真的功能,程式碼裡找得到。✅
  • B 頁面存在嗎? → 存在。 那是一個真的頁面。✅
  • 那……錯在哪?

宣稱:「這個門檻是 6。」

  • 「6」這個數字在資料裡出現過嗎? → 出現過。 某一張卡上真的寫著 6。✅
  • 這是編造的數字嗎? → 不是。 ✅
  • 那……錯在哪?

錯的地方是:甲功能不在 B 頁面,而那個 6 不屬於這條規則。

錯的不是任何一個零件,而是零件之間的關係。

而這就是我那套方法的盲點,講得精確一點是這樣:

我的查核查的是「零件」,而這一類錯誤發生在「接線」。

grep 可以告訴你某個符號在不在。它沒有辦法告訴你,這個符號被放在對的句子裡。


而其實我已經抓到過一次了,只是沒認出來

這件事是我後來回頭看才發現的,而且它讓我背脊有點涼。

昨天的第三類錯誤——編號存在,但主旨不符——記得嗎?

卡片說 #2108 做了 carrier 相關的事。#2108 確實存在,但它做的是另一件事;真正做那件事的是 #2002。

你看它的結構:

  • PR 存在 ✅
  • 編號格式正確 ✅
  • 它跟這張卡的主題也真的沾得上邊 ✅
  • 只有「這個編號對應到這件事」這個連結是錯的 ❌

那就是同一種病。

一個真的零件,被接到了錯的地方。

而我當時為什麼抓到它?不是因為我的方法涵蓋了這一類——是因為我在指令裡多寫了一句「點進去,讀它到底做了什麼」。

換句話說:第三類錯誤,我其實抓到過一個。但我當時把它歸類成「主旨不符」,而不是「這是一整個我沒有防線的類別」。

一個被當成個案處理的系統性問題,會一直發生。


為什麼這一類特別危險

我整理出三層,越往後越麻煩。

第一層:它通過查證

前兩類錯誤——狀態過時、憑空生成的編號——去查一下就破功了。日期對不上、編號是空的,證據很硬。

第三類不會破功。你查一項,它對;再查一項,它也對。你查完所有零件,全部通過,然後得到一份「驗證完畢」的報告。

而錯誤還在裡面。

第二層:它讀起來完全正常

一個放錯位置的真實資訊,讀起來跟放對位置的一模一樣。

「B 頁面有甲功能」這句話,沒有任何語感上的破綻。它不像「PR #1305」那樣是一個可以被指認的物件——它是一句通順、具體、有主詞有受詞的陳述。

你不會在讀的時候皺眉。

第三層:它把成本轉嫁給別人

這是 Day 1 那件事真正的重量。

那份說明書被拿去當成新人的測試依據。照著文件去 B 頁面找甲功能,找不到,於是回報:測試失敗。

而那個 FAIL 是假的。

更麻煩的是——真的失敗和假的失敗,混在同一份回報裡。 從外面看,它們長得一模一樣。

如果沒有人回頭去對原始票卡,接下來會發生的事情很具體:有人會去查一個不存在的 bug、開一張不需要的卡、佔用一個工程師半天,最後得到結論「無法重現」。

一個文件裡的錯位,變成了另一個人的一整天。


對新人來說,這一類是無解的

這一節是我認為整個系列最重要的一段。

要抓到「甲功能被寫到 B 頁面」這種錯,你需要具備一個條件:

你得先知道甲功能原本在 A 頁面。

一個做過這塊的人,讀到那句話會有半秒的遲疑——「咦,這個不是在另一頁嗎?」那半秒不是聰明,是腦袋裡有一張對照表。

而新人沒有那張表。

新人讀到「B 頁面有甲功能」,那就是學到的第一件事。它不會跟任何東西衝突,因為腦中還沒有任何東西。

所以:

抓到錯誤的前提,是你已經知道對的樣子。而新人,正是那個不知道的人。

這句話推到底,結論相當難堪:

這個知識庫最需要它的使用者,剛好是最沒有能力驗證它的人。

這也是為什麼我沒有辦法接受「反正它大部分是對的」這種說法。大部分正確,對一個老手來說是省時間;對一個新人來說,那少部分會變成對這間公司的第一批認知,而且會被複製到下一份文件裡。


那它到底怎麼被抓到的?

講到這裡有一件事很值得注意:

這一類錯,最後不是被「查」出來的。是被「用」出來的。

它通過了所有的靜態查核。真正讓它現形的,是有一個人拿著它去做事,然後撞牆。

這件事後來直接影響了我對驗收的想法——Day 4 我寫過,這個知識庫的驗收方式不是我自己讀一遍覺得清楚,而是找人或找 AI 扮新人,照著它從頭跑一遍。

當時我以為那只是一個比較嚴格的驗收方式。

現在我知道那是唯一能抓到第三類錯誤的方式:

零件可以用查的,接線只能用跑的。

這件事在我的實務裡,有一個完整到有點難堪的案例。

先講一個決定。發現那兩處錯位之後,我沒有把那份說明書逐張重新查一遍。

原因很誠實:有些功能,我上個月才測過,而我對它的記憶已經開始模糊。拿一份自己都不確定的記憶去當對照組,查了也不能算數。所以我換了一個更實際的作法:不查文件,查每一個被提出來的問題。

第一批交給新人去跑的卡片,一共 16 張。每一張的內容我都事先自己測過——所以理論上,它們不應該讓人卡住。

那 16 張跑完之後,新人回來提出了大約 6 個疑問,或是直接驗出了跟卡片上寫的不一樣的結果。

6 個問題,對 16 張卡。換算下來是 3/8。

這個比例對我來說很刺眼。因為這批卡片不是隨手發出去的——是我看過、我測過、我覺得可以拿出去給人用的。

而每一個被提出來的問題,最後都只會收斂到兩種可能:工單敘述錯了,或功能真的錯了(我自己理解錯的,也算敘述問題)。兩種我都得回頭確認。

Day 1 我說「有一部分失敗是真的」。現在可以給它一個比例了。

其中一條的完整帳單

那 6 個裡面,有一個值得整段寫出來。

某個「與前 7 天相比」的統計區塊,回報說少了前期的數字。

先講結論:原本的測試版面是對的。

但過程是完整的一條鏈:

新人提出問題 → 我被帶偏 → 靠 AI 查詢 → 被騙 → 開單修改 → 修改後的版本上了測試環境,我又起疑 → 深入調查 → 退單,請 RD 復原 → 回頭修改那張票卡的敘述

注意這條鏈上有三件事同時發生:

  1. 錯誤不在程式裡,在敘述裡。 但它一路被當成產品問題處理:被確認、被開單、被排進修改。RD 做了工,做出一個不該存在的改動。
  2. AI 在鏈的中段,而且它站錯邊。 我拿著一個已經被帶偏的問題去問它,它給了我一個支持錯誤方向的答案。被帶偏的問題,問出被帶偏的答案——然後兩個錯的東西互相背書。
  3. 攔下它的不是查核,是又一輪測試。 修改後的版本上了 Stg,是多看的那一眼、那個「又起疑」,把單退掉。

如果那個版本上了 Stg 我沒有起疑呢?一個描述正確的版面被改掉,一張不必要的單已經耗掉 RD 的時間,而原始票卡的敘述會繼續錯下去。

這就是「被用出來」的全部含義。


明天:那它為什麼會這樣錯?

最後留一個問題給明天。

發現這一類錯誤之後,我的第一個解釋是很自然的那一個:它讀得不夠仔細。

那時候我想的是——下次把規則寫得更嚴格一點、把要求講得更清楚一點,應該就會好一點。

但這個解釋有一個很大的問題。

因為 Day 1 我就寫過了:我當初給的規則已經很明確——以頁面為單位拆分,每一頁都要各自寫出那項功能,不准寫在其中一頁然後說「其他頁也有」。

我交代了。而它還是把甲功能放到了 B 頁面。

所以問題不在指令不夠嚴格。

明天那篇要證明的是:這不是「它拉錯了」,而是資料裡根本沒有那個答案。

而這兩件事的差別,決定了整個知識庫該怎麼蓋。


上一篇
# Day 8 — 8 處錯誤:包括三個根本不存在的 PR 編號
下一篇
# Day 10 — 它不是抓錯,是資料缺了一個維度
系列文
它說得頭頭是道 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言