模組二|選題與素材庫(Day 6–11)
我做了一條把新聞素材整理成 podcast 講稿的自動化產線,素材庫裡目前有 438 則資料。為了讓每一則都能直接拿起來唸,我替它訂了欄位規格,也寫了驗證指令。
本篇是這份規格的體檢報告:438 則裡只有 35 則真的照規格寫,落實率 8.0%。
我定了兩套模板,通用版 13 個欄位、深化版 15 個。兩套都明訂了欄位順序:不只要有這些欄位,還要按這個順序排。
順序的意義不是潔癖。它是口播的順序:鉤子在最前面,故事鋪陳,然後要點條列,中段展開分析,查核在後段,參考資料收尾。照這個順序讀下來,就是一段可以直接唸的稿。
兩套模板的差別是後半段:深化版把通用版的幾個欄位換成議題分析類的欄位,用在需要多角度拆解的題目上。
這份規格定義在哪?
寫死在一支 Python 檔的兩個 list 裡。
TEMPLATE_A_FIELDS = ['hook', 'story', 'core', ...] # 13 欄
TEMPLATE_B_FIELDS = ['hook', 'story', 'core', ...] # 15 欄
不是 JSON Schema、不是任何標準格式,就是兩個 list。而判定一則條目屬於哪一套的演算法也很土:
# 只要含深化版專屬欄位的任何一個(且非空),就判為深化版
if any(entry.get(f) for f in DEEP_TEMPLATE_HINT_FIELDS):
return 'B'
return 'A'
這個判定方式後面會出事,先記著。
而「寫死在 Python list 裡」本身也有代價,我當時沒想到:這份規格只有這支腳本讀得懂。
如果它是 JSON Schema,編輯器可以即時提示、CI 有現成的驗證套件、文件可以自動生成、別的語言寫的工具也能用。而寫成 Python list 之後,唯一能檢查它的東西,就是我自己寫的那個子命令(也就是下面會講到那個從來沒被自動執行的東西)。
規格的格式決定了有多少工具能幫你執行它。 選一個沒人看得懂的格式,等於自己承擔全部的執行責任。

我把 438 則全部套進去驗了一遍。
完整符合任一套模板的:35 則,8.0%。
而這 35 則有個共同點:它們全部落在規格明訂適用的那 70 則區間裡。
也就是說:規格說「id 300 到 369 這 70 則要符合模板」,而區間外的 368 則,合規數是 0。
這其實比 8% 這個數字好理解一點:規格從來沒有被套用到全庫,它只是一次針對特定範圍的補件。
那個區間內部更有意思。69 則裡(少一則),34 則不合規。
而缺的欄位永遠是同一組五個:五個深化版專屬的議題分析欄位,各缺 34 次。
同時,另一個深化版專屬欄位卻是 69/69 全補齊。
把這兩件事放在一起,事情就清楚了:
當初補件的時候,補了容易補的那一個,五個難補的沒補。
而因為判定演算法是「含專屬欄位任一即判為深化版」,這 34 則全部被判成深化版,然後全部驗不過。它們被那個唯一補齊的欄位拖進了一套自己不符合的模板。
判定條件太寬鬆,會把「補了一半」誤判成「屬於這一類」。
如果判定改成「含專屬欄位過半」,這 34 則會被判成通用版,然後可能就過了。當然那只是把問題藏起來。真正的問題是補件補了一半就停了,而沒有任何東西提醒我還有一半沒補。
還有一件更難堪的。
另一份規格文件寫著「每則必須含 15 個段落」,並列出清單。而那份清單跟這兩套模板的欄位集互不相容。
具體來說,有三個欄位:
| 欄位性質 | 實際填了幾則 | 在模板裡嗎 |
|---|---|---|
| 花絮類 | 412 | ❌ |
| 影響推論類 | 264 | ❌ |
| 專業解讀類 | 228 | ❌ |
這三個欄位的填充率分別是 94%、60%、52%(全庫最活躍的欄位之一),而它們不在任何一套模板裡。
兩份規格沒有任何一句話說明它們的適用範圍怎麼切。是舊的被新的取代了?還是兩套並行?我自己現在也答不出來。
而這件事沒有造成任何錯誤訊息,因為沒有東西在同時檢查這兩份規格。它們各自躺在自己的檔案裡,互相矛盾了很久。

最關鍵的一點在這裡。
這套模板有驗證工具。CLI 裡就有一個 validate-templates 子命令,跑下去會列出所有不合規的條目與缺的欄位。
它從來沒有被掛進任何自動流程。
不在 pre-commit、不在 CI(Day 1 講過:兩個 repo 加起來 0 個 ci: commit)、不在任何一支會被自動觸發的地方。它是一個要人記得去跑的指令。
而我不記得。
所以這條規則的完整狀態是:
中間差的那一步,不是技術,是一行設定。
昨天那兩個 100% 的欄位,沒有規格、沒有驗證器,卻是滿的。
今天這套模板,有規格、有驗證器,8% 合規。
差別是什麼?
昨天那兩個欄位,不填就完不成工作。今天這套模板,不合規也照樣能播。
模板的價值是「條目之間一致,未來好處理」,那是延後的收益。而人在填第 300 則的時候,感受不到第 400 則的好處。
這給了一條判準,我覺得比「要不要寫規格」有用得多:
一條規則如果它的收益是延後的,它就必須被自動執行。 因為沒有人會為了延後的收益,在當下多做一件事。
而收益是即時的規則(不填就播不了),你不用管它,它會自己被遵守。
這一篇的代價是我到現在還沒把那支驗證器掛上去。
寫這篇的時候我又跑了一次,數字還是 8%。要修有兩條路:把驗證掛進 pre-commit,或者承認全庫模板化這件事已經沒有意義、把規格範圍縮到那 70 則然後把剩下 34 則補完。
兩條路都是十分鐘的事,而我從那次補件到現在,一次都沒做。 這件事本身比 8% 這個數字更能說明問題。
第二個代價:那三個不在模板裡卻填了幾百則的欄位,代表規格跟實際用法已經分岔很久了。它們不是被違規使用,是它們就是實際的工作方式,而規格沒跟上。這種時候該改的是規格,不是資料,但我也還沒改。
規格的落實率,是規格本身的品質指標。
如果你的 schema 只有 8% 的資料符合,問題通常不在資料。回頭問三件事:
第二條,關於判定條件:
判定「這筆資料屬於哪一類」的條件太寬鬆,會把「做了一半」誤判成「屬於這一類」,然後產生一堆假的違規。 我那 34 則就是被一個「含任一即算」的條件拖下水的。
如果分類條件會影響後續驗證,寧可嚴一點:寧可漏判成「不屬於」,也不要把半成品收進來然後判它不合格。
明天講這套 schema 裡最成功的一個部分:一條編輯倫理,被壓成兩個 in 判斷。