Skip to content
White's Tech Notes
Go back

Prompt 漏抓時先查「是不是被某條排除規則主動擋掉」,不要先調取捨強度

AI AgentsEdit page

問題

yuna 專案有一段抽取用的 prompt:讀一天的聊天記錄,把角色自己講過、而設定裡沒有的事實抽出來。

實測 2026-07-29 那天她講了兩件設定裡沒有的事:

  • 「我還好欸,不排斥但也不會特別想吃,我比較怕那種很重的中藥味」→ 抽到了
  • 「養身大叔就是你這種啊,中醫推拿完馬上喝補湯,跟我阿罵有得比」(阿嬤,設定裡家人只寫到爸媽跟姊姊)→ 漏了

Review 的診斷聽起來很合理:這個 prompt 的最後一句寫著「寧可少不要多」,而它兜底的上游那一層寫的是「不確定就記」——兜底層比它兜的那層還保守,是結構性問題。位置上「寧可少不要多」又是整段最後一句、緊貼輸出格式,權重額外高。

於是改了四處:把「寧可少不要多」反轉成「寧可多不要少」、在「家人親戚」後面補上「阿嬤、表姐都算」的明示提示、例子從 1 個增為 3 個橫跨類別、把去重規則從「換句話說也算重複」收窄成「只擋字面上真的寫過的」。

原因

改完之後重跑,07-29 的輸出一字不差。阿嬤照樣漏。

而且對照組退步了:另一天原本抽到 2 條正確的,改完只抽到 1 條,而那 1 條是

很少喝咖啡,喝了容易心悸睡不著,尤其拿鐵一杯下去整晚睡不著

角色設定裡本來就寫著「你不太會喝咖啡,喝了容易心悸睡不著,所以拿鐵能免則免」,另一個欄位還寫了一次「咖啡不能喝(會心悸睡不著)」。中段九個字逐字相同。這是誤收,而且是被「只擋字面上真的寫過的」那個收窄放進來的——諷刺的是它字面上真的寫過,模型在「寧可多不要少」的壓力下連自己剩下的規則都沒守住。

回頭看,漏抓的真正嫌疑犯在「不要收的」清單裡:

- 關於男友的事——那是另一個人的事實,不歸這裡管

「養身大叔就是你這種啊…跟我阿罵有得比」這句話,主語是男友的行為,阿嬤是比喻裡的第三方,字面上整句都在講他。模型很可能是把整句歸到排除清單去了。這不是「保守」的問題——是有一條規則在主動擋它。

(附帶一個更瑣碎的原因:原文是錯字「阿罵」,跟 prompt 裡寫的「阿嬤」字面對不上。)

解法

整組退回到驗證過的版本。四處改動:零 recall 收益、一條新的誤收、外加一個自我矛盾——「寧可多不要少」的理由寫著「重複的下次會被既有事實那份清單擋掉」,但擋那份清單的語意去重,正是同一批改動拿掉的。

正確的方向是加一條規則去覆蓋那個排除,而不是調整取捨強度:

- 順帶提到的、句子主語不是她但講的是她的人事物(我阿嬤、我表姐、我以前的學校)也算,
  這條凌駕「關於男友的事」那一條

關鍵洞察

  • 漏抓有兩種完全不同的成因:模型「沒想到要收」,跟模型「有一條規則叫它不要收」。 前者才是靠提示、例子、取捨語氣解決的;後者不管把「寧可多不要少」寫得多用力都沒用,因為排除規則是明確指令,比語氣強。動手之前先把 prompt 裡每一條「不要收的」逐條套到漏掉的那個案例上,問「這句話會不會中?」
  • 把明示提示加到極致還是漏,本身就是證據。 這次已經把「阿嬤、表姐都算」寫進類型清單、把「有阿嬤,會燉補湯」幾乎逐字放進範例,輸出一字不差——那就反證了問題不在 recall 傾向上。這是個便宜的判別實驗,可以先做。
  • 放寬去重規則的代價是永久的。 這條路徑只新增不修改,而 facts 每輪全量注入 context,所以一條改寫版的重複會一直留著、每天餵回去。收緊 recall 的每一步都要先問「誤收的東西誰會清掉」。
  • 一次只改一個變數,並且留住改動前的量測。 這次四處一起改,結果一個沒效、一個有害,但因為 n=1 對 n=1,連「哪一處造成退步」都只能靠推理。幸好改動前跑過兩天當基準,否則連退步都看不出來。
  • 流程上的教訓:review 給的診斷(「兜底層比上游還保守」)邏輯上完全成立,實測就是不成立。prompt 的因果不能靠讀出來,只能靠跑。


Previous Post
Python sqlite3 的 with conn: 拿不到原子性——當 repo 函式自己 commit
Next Post
加了保護但保護不存在的三種形狀