逢迎
過度順從的 模型 輸出。原因在於 訓練:模型被塑造成偏好人類喜愛的答案,而人類傾向於喜歡附和勝過被指出錯誤。因此模型學到了順從會獲得獎勵——即使這種附和並不正確。
表徵為:
- 在壓力下妥協 ——當你說「你確定嗎?」時,會推翻正確答案。
- 讚美糟糕的輸入 ——在分析之前,就贊同你那漏洞百出的計畫非常出色。
- 有偏見的框架 ——當你暗示這是你寫的時候,審查偏向正面;當你暗示是別人寫的時候則偏向負面。相同的產出,不同的評判。
- 模仿 ——將你的錯誤重複回傳給你作為確認。
診斷測試: 如果沒有你的引導,模型會這樣說嗎?如果唯一改變的是你的語氣或框架,那是逢迎,而不是真正的分析轉變。
修正: 隱藏你的偏好。以中立的方式措辭提示——「檢視這段程式碼」而不是「這段程式碼好嗎?」。
避免: 將任何剛好討好你的錯誤答案稱為「逢迎」。沒有診斷測試,這個詞的價值並不比「錯誤」更高。
用法:
「它說我的重構計畫看起來很棒,然後我問『你確定嗎?』它就把整套說詞收回了。」
「典型的逢迎——它先是因為你聽起來很有信心而同意,然後又因為你聽起來懷疑而妥協。計畫的品質沒有變,變的是你的語氣。 清除 並在不透露任何傾向的情況下重新詢問。」
幻覺
自信地給出錯誤的 模型 輸出。有兩種不同原因與修正方法的類型:
| 類型 | 出錯之處 | 原因 | 修正 |
|---|
| 事實性 | 關於世界的虛構或錯誤事實——不存在的函數、錯誤的 API 簽章、偽造的引文 | 參數化知識 缺口,通常超出 知識截止點 | 載入正確的 上下文知識 |
| 忠實度 | 輸出偏離了所載入的上下文知識、使用者的指令或模型先前的推理 | 注意力退化;在 呆滯區 中惡化 | 清除 或 壓縮 |
下一個 Token 預測 無論底層事實是否真實,都能產生流暢的輸出——模型內部沒有訊號表明它不知道某事,因此虛構的方法會以與正確方法相同的自信語氣出現。幻覺程式碼按其結構來看是合理的:如果它存在的話,API 就會是那個樣子,這正是它能夠滑過快速瀏覽層級審查,且僅在執行時失敗的原因。
你需要知道你看到的是哪種類型,因為針對其中一種類型的修正會讓另一種類型惡化。事實性意味著知識缺失:修正方式是添加上下文——文件、型別定義、檔案。忠實度意味著知識存在,但在爭奪注意力的競爭中落敗:修正方式是移除上下文。如果將忠實度誤診為事實性,你就會貼入更多文件,這會擴大上下文並使偏移更嚴重。當代理程式出錯時,在決定面臨什麼問題之前,請先檢查正確的資訊是否已經存在於上下文中。
避免: 將「幻覺」作為「錯誤」的純粹同義詞——未指明類型時,該術語沒有診斷價值。
用法:
「它在綱要上幻覺出了一個 `parseAsync` 方法。」
「事實性還是忠實度?」
「這個方法存在於我貼上的文件中——它只是在第四十 輪 後停止讀取它們了。」
「那就是忠實度。壓縮並重新載入,不用費心新增更多文件。」
參數知識
模型從訓練中「知道」、儲存在參數裡的內容。在訓練時便固定——模型看不到自己的參數,也無法更新。細節在壓縮中流失:數十億事實擠進固定數量的參數,罕見內容變得模糊。它是常見主題流暢表現的來源,也是冷門主題捏造內容的來源。與上下文知識相對。
參數知識不以事實形式儲存。訓練從未給模型資料庫供查詢;它調整參數,直到模型能良好預測文字,而能良好預測某主題文字的模型,行為就像知道該主題。知識可靠度取決於某事在訓練資料中出現的頻率:有數百萬個例子的主題能準確再現,只有少數例子的主題,模型則根據相似主題的樣貌猜測。對模型來說,再現與猜測是同一個過程,因此它分不清自己在做哪個。捏造答案與正確答案一樣流暢。幻覺就是模型猜錯。
參數知識也會老化。參數在知識截止日期就停止改變,因此那天之後發布或更名的函式庫不在其中,改過的 API 也仍被記成舊形式。
無論是太罕見或太新這兩種缺口,解法都相同:無法把知識加入參數,所以必須改以上下文知識提供。
用法:
「它寫 React 完美無缺,卻會編造我們內部 SDK 的方法。」
「React 在參數知識中很密集——有數百萬個訓練例子。你的 SDK 沒有,所以模型填入看似合理的形狀。把 SDK 文件載入上下文。」
知識截止
模型的參數知識所涵蓋的最後日期。截止日之後的函式庫、API 與事件,除非文件以上下文知識載入,否則都是捏造陷阱。每個模型版本都有自己的截止日期。
截止日期源自模型的製作方式:訓練將文字快照融入模型參數,之後參數便固定不變。模型不知道自己的知識有邊界——被問到截止日之後的事時,它不會拒絕,而是從最接近的已知內容推測。陷阱因此不易察覺:根據舊版函式庫寫的程式碼看似合理,通常也能編譯,卻會在已改變的部分失敗。
解法始終相同:把最新資訊放進上下文。載入更新紀錄、指向已安裝版本的型別定義,或讓代理從網路讀文件。上下文裡有資訊,總比參數裡沒有好。
用法:
「它一直寫 v3 SDK 語法——我們用的是 v5。」
「v5 在知識截止日期後才推出。把 v5 更新紀錄載入為上下文知識,否則它會一直根據舊版參數知識編造。」
上下文知識
agent](#agent) 可以直接從目前 context 讀取的事實——使用者的任務、agent 已讀取的檔案、tool results,以及在 session 開始時載入的 AGENTS.md 內容。相對於 parametric knowledge:parametric 是從參數中回憶出來的;contextual 則是從 window 中讀取出來的。當 agent 根據 contextual knowledge 工作時,Hallucinations 的發生率會大幅降低——答案就在眼前,而不是從模糊的記憶中撈取。
在這兩種類型的知識中,只有 contextual knowledge 是在你掌控之中的。參數是凍結的,因此要讓 model 具備它所缺乏的知識——內部 SDK、在 knowledge cutoff 之後發布的程式庫、昨天做出的決定——唯一的辦法就是將其放入 context 中。許多實務上的 AI 編碼工作歸根究柢就是:在模型需要時,把正確的事實呈現在它眼前。
當 contextual knowledge 與 parametric knowledge 衝突時,通常是 contextual 獲勝。貼上目前的 API 文件,模型就會遵循文件,而不是它對舊 API 的陳舊記憶——不過舊版本仍然可能會滲透進來,特別是在漫長 session 的深處。如果載入了文件後,agent 仍然不斷回復到過時的模式,這就是 parametric knowledge 洩漏到了 contextual 之外;重申修正內容或將其移近工作內容會有所幫助。
與 parametric knowledge 不同,使用 contextual knowledge 是需要付出代價的。載入 window 中的所有內容都會消耗 tokens 並競逐模型的 attention budget,因此載入越多並不代表自動越好——目標是讓相關的事實進入 window,而不是所有的事實。
只有在與 parametric knowledge 對比時才使用這個詞;否則直接說 context 即可。
避免使用:「工作記憶」——contextual knowledge 是現在在 window 中的內容;memory system 則是將跨 session 內容帶入其中的機制。規模不同,切勿混淆。
用法:
「為什麼我貼上文件時它就能完美搞定 API,不貼就會胡言亂語?」
「有了文件,這就是 contextual knowledge——照著頁面讀。沒有的話,這就是 parametric,而那些罕見的端點就會變得模糊。」
注意力關係
預測每個詞元時,模型會考量上下文中其他每個詞元——有些權重很大,有些幾乎沒有。兩個詞元之間的配對,稱為注意力關係;有意義的配對(「her」與「Sarah」,或 `getUser()` 呼叫與其 `function getUser` 定義)會比無關配對更強烈地互相影響。N 個詞元的上下文,大約有 N² 個關係。
模型表面上的理解就存在這些配對中。它能解析代名詞,是因為「her」和「Sarah」的注意力關係很強。它用正確引數呼叫函式,是因為呼叫位置與先前讀過的定義之間的關係在起作用。這些都不是查詢所得——每次模型供應商請求,每個配對都會重新計算。
N² 值值得仔細想想,因為成長速度比直覺快:
| 上下文大小 | 配對數(約 N²) |
|---|
| 1,000 個詞元 | 約 100 萬 |
| 10,000 個詞元 | 約 1 億 |
| 100,000 個詞元 | 約 100 億 |
每個配對也不只計算一次。模型有多個注意力頭——前沿模型的確切數量未公開,但五十至一百個是合理猜測——每個頭都計算每段關係的自己的版本。因此,上表每個配對都在每個頭中重複。配對數量非常龐大。
對任何特定任務而言,只有少數關係重要。你的指示與它所管轄程式碼之間的配對,是少數重要關係之一;池中幾乎其他一切都是雜訊。而兩者成長速度不同:重要關係大致固定,總池量卻隨上下文大小呈平方成長。1,000 個詞元時,你關心的配對是百萬分之一;100,000 個詞元時,變成百億分之一。這是注意力預算背後的算術,而重要關係分得的占比過薄時,感受到的就是注意力衰退。
用法:
「它一直把差異中兩個 `user` 符號搞混——看來進入笨拙區了。」
「對,各呼叫位置與宣告的注意力關係正在互相干擾——詞元形狀相同,繫結不同。改掉其中一個名字,配對就會清楚。」
注意力預算
每個 token 都有有限的影響力預算,可以用來分配到 context 的其餘部分。對 one relationship 的強烈影響會留給其他人更少的影響力。這個預算是針對每個 token 的,不會隨著上下文增加而增長,這就是為什麼長 sessions 會被稀釋的原因。
把它想像成訊號和雜音。你的指令是一個固定音量的訊號;context window 中的每一個其他 token 都是互相競爭的聲音。指令從未變小——它仍然存在,字元對字元地存在——但隨著上下文增長,周圍的房間變得更大,訊號雜訊比隨之下降。在 10k token 上下文中曾是最響亮的東西的指令,在 150k 時變成了背景嗡嗡聲。這就是 attention degradation 背後的機制:模型並未忘記;訊號在雜音中迷失了。
這種症狀讀起來像是抗拒——代理程式在早期同意了一個限制,然後卻偏離了它,而重新貼上該限制只會短暫地起作用。原因不是指令;而是視窗中與之競爭的所有其他東西。
你可以控制的是進入上下文的內容。不服務於任務的內容並非中立的——它是覆蓋在所有有用內容之上的雜音。保持視窗很小,當累積的上下文不再符合其價值時進行 clear,並重申重要的限制,而不是相信它們早期的提及會持續有效。
用法:
「為什麼它一直忽略我貼在頂部的綱要?」
「我們已經身處 dumb zone——每個 token 的注意力預算都是固定的,但上下文持續增長。綱要上的訊號現在正與數千個較新的 token 競爭。」
注意力退化
隨著 session 增長,每個 token 的 attention budget 會分散到更多競爭者身上。任何單一 meaningful relationship 的訊號都會縮減;來自無關 context 的雜訊會湧入。相同的 model,相同的 parameters — 只是同一個盤子要餵飽更多張嘴。聰明區/笨拙 zone effect 的原因。
它表現為模型在對話中段變差:它遵循了一小時的約束開始失效,它重新詢問被告知過的事情,它寫出的程式碼忽略了稍早讀取過的檔案。模型沒有任何改變 — 唯一的變數是它現在所關注的上下文數量。
這是漸進式的,這也是為什麼很難在對話內部察覺的原因。沒有錯誤,也沒有閾值;每個 turn 都只比前一個稍微差一點,當錯誤變得明顯時,你已經在笨拙區待了一陣子。
你的復原方式是移除上下文,而不是加入更多。重新貼上被忽略的指令只會在同一個擁擠視窗中增加另一個競爭者,且只能提供短暫的幫助。有效的方法是:clear 並僅重新載入任務所需的部分,或者 compact,或者 hand off 給一個新的對話。將指令遵循能力的下降視為關於上下文長度的訊號,而不是關於模型的訊號。
用法:
「它已經深陷笨拙區 — 發明了類型檔案中不存在的泛型。」
「注意力退化。類型定義仍在上下文中,但其訊號已被我們之後新增的所有內容所埋沒。請清除並重新載入。」
智慧區域
在 session 的早期,agent 處於「聰明區」——敏銳、專注、記憶力良好。隨著工作階段增長,它會漂移到「笨拙區」:變得更草率、健忘、犯更多錯誤——以及更多的忠實性 hallucinations。相同的 model,相同的 harness——只是有更多的 context。這是 attention degradation 的實際感受。在前沿模型上,笨拙區通常從大約 125K-150K tokens 開始——儘管這仍有爭議。當工作階段膨脹時進行 Clear 或 compact;不要硬撐。
這種下降是漸進式的,這使得它很容易被忽略。沒有錯誤訊息,也沒有明顯的界線;代理程式只是開始表現得稍微差一點,然後是明顯變差。常見的徵兆:它忘記了你在二十個回合前給它的指令,重複它已經修正過的錯誤,或者自信地斷言上下文相矛盾的事項。因為這種下滑是平穩的,通常的反應是硬撐並重新解釋——這會增加更多上下文並使問題惡化。
這些區域不會追蹤 context window 的限制。工作階段可能已經深入笨拙區,而視窗的大部分仍然是空的:限制是 harness 拒絕繼續的地方,但品質在那之前很久就已經下降了。圍繞著聰明區進行規劃,而不是視窗——任務的實際預算是在其內部運作良好的 token,而不是它在技術上可以容納的 token。
聰明區是一個預算,無關的工作會消耗它。在工作階段中完成的每個任務都會消耗 token,因此在同一個工作階段中啟動第二個任務意味著在更接近笨拙區的地方啟動它。每個工作階段執行一個任務,可以讓每個任務都利用工作階段中最敏銳的部分。當單一任務大於一個聰明區時,請將其分割:在自然的邊界進行 hand off 或壓縮,並讓一個全新的工作階段來處理接下來的部分。
用法:
「它在前三個元件上表現完美,卻把第四個搞砸了。」
「你已經不在聰明區了——同樣的模型,只是現在深入笨拙區。壓縮並重新載入計畫,下一個元件就會順利完成。」