AI News HubLIVE
站內改寫5 分鐘閱讀

代理開發的合理規格程度

本文探討了在代理開發中規格説明的必要性,指出零規格和過度規格都有成本,最佳平衡點取決於任務類型,並強調了規格驗證和可執行測試的重要性。

來源O'Reilly AI & ML Radar作者: Markus Eisele

在關於代理的討論中,我不斷看到同一個觀點:詳細的規格説明已經是舊世界的開銷了。給模型一個粗略的目標,讓它探索,修復返回的結果,然後繼續前進。這聽起來很高效,但它也隱藏了成本。

簡單的提示看起來便宜且誘人,因為它能立即開始實現。然後修正循環開始了。你審查輸出、澄清意圖、要求修改、重新運行測試、發現下一個差距,然後再次重複。仍然需要有人決定結果是否符合真正的目標。那個人成為了預言機。

在另一個極端,完整的正式規格説明顯然前期成本很高。編寫驗收標準、契約測試或行為驅動開發(BDD)場景需要真正的努力。但下游成本不同,因為更多的預言機是可執行的。測試每次檢查相同的條件。它不會在午餐前五分鐘感到疲倦、匆忙或樂觀。

這才是真正的權衡。問題不在於規格是好是壞。而在於最小總成本在哪裏。對於大多數代理工作,它處於中間位置:足夠的結構來約束工作,足夠的例子使意圖具體,以及足夠的可執行檢查,使得審查不會變成猜測。

零規格不是智能和精益的;它只是成本高昂的“氛圍編碼”。

瓶頸轉移了,但沒有消失

軟件工程從來不僅僅是打字甚至生成代碼。它關乎決定應該存在什麼、永遠不應該發生什麼、哪些權衡重要、以及一旦問題觸及現實世界,“完成”意味着什麼。

多年來,團隊通過人類摩擦發現了缺失的規格。審查者注意到邊緣情況,QA發現了沒有被描述的路徑,高級工程師在頭腦中承載了一半的真實需求,並一次會議地翻譯它們。這些都不優雅,但它確實迫使模糊性暴露出來。

代理從根本上改變了這一點。它們使實現變得更便宜、更快。這也意味着一個未充分説明的想法可以在任何人真正同意系統應該意味着什麼之前變成一個看似合理的系統。

在舊世界中,模糊的需求遇到了人類的緩慢。在代理世界中,模糊的需求遇到了機器的速度。

這就是為什麼規格突然又感覺重要了。它一直很重要。我們只是用實現成本作為粗略的強制函數,並稱結果為流程。

隨着實現變得更便宜,更多的困難轉移到決定什麼是對的並可靠地檢查它。

編寫規格是不夠的

這是我認為人們最常跳過的部分。他們談論時似乎順序很簡單:編寫規格,然後讓代理實現它。缺失的步驟是昂貴的部分。

規格本身需要審查。

即使是精心編寫的規格也可能以熟悉的方式失敗。它可能自相矛盾,或者只覆蓋快樂路徑而對重試、速率限制或部分失敗毫無幫助。它可能描述聽起來精確但實際無法驗證的行為。有時它在完全錯誤的方向上精確:它説了你寫的東西,而不是你的意圖。

當代理忠實地執行有缺陷的規格時,故障更難以診斷。實現可能看起來連貫。它甚至可能通過你提供的檢查。但真正的問題在上游,在規格中,所以修復它意味着同時解開代碼和推理。

這就是為什麼我認為規格驗證應該有自己的項目。在實現開始之前,需要有人問幾個簡單的問題。這內部一致嗎?對於這個任務足夠完整嗎?哪些部分是可測試的?我們還在哪些地方依賴人類判斷?哪些失敗模式因為每個人都默默假設而缺失?

代理可以在這裏幫忙,但只有當我們用它們來做比“編寫需求”更有用的事情時。那個提示通常會產生打磨過的迷霧。更好的提示要具體得多:

起草最小的規格,使得另一個代理能夠安全地實現它。包括假設、非目標、驗收標準、邊緣情況、可觀察結果和開放問題。標記哪些聲明可以變成自動化測試,哪些仍需要人工審查。

之後,將草稿交給另一個代理,並告訴它攻擊結果:

找出矛盾、模糊術語、隱藏依賴、不可測試的聲明、缺失的失敗模式,以及實現可能通過書面標準但違反意圖的地方。

即使這個簡單的工作流程也降低了達到值得人類判斷的規格的成本。

代理並沒有消除對規格的需求。它們使達到實際上有用的詳細程度變得更便宜。

為什麼多代理系統需要更強的合約

一個在小的、有界任務上工作的單個代理通常可以從寬鬆的指令中恢復。循環緊密,爆炸半徑局部化,人類通常可以在它偏離時將其引導回來。人類甚至可以很容易地發現偏離。

多代理系統是一個非常不同的問題。一旦一個代理的輸出成為另一個代理的輸入,解釋性偏差開始累積。代理B不知道代理A誤解了需求的10%。它只是將輸出視為基本事實並繼續前進。到人類看到結果時,原始錯誤可能已經埋藏在幾層看起來很能幹的工作之下。

此時,規格不再只是指導,而更像是一個合約。

那個合約需要的不止一段意圖。它需要模式、不變量、允許的歧義、驗證規則和明確的失敗行為。在許多情況下,還需要契約測試、類型化接口和機器可檢查的交接格式。交接是產品的一部分,這不如人們希望的那麼光鮮,但更接近現實。

這也是BDD和可執行驗收測試所屬的地方。它們的價值不僅僅是方法論,而是它們將部分人類預言機變成了可重複的東西。當行為足夠穩定可以精確指定時,可執行規格通常比另一輪審查更便宜。

一旦代理開始將工作交給其他代理,交接本身就需要像真實接口一樣被指定和驗證。

規格應該有有效期

團隊在這裏犯的另一個錯誤是:當他們繼續在規格曲線上推進時,彷彿更多文本總是更安全。事實並非如此。至少對於當前的模型不是。

Chroma關於上下文腐爛的工作揭示了問題的第一部分:模型性能隨着輸入增長而變得不太可靠,即使在簡單任務上也是如此。在編碼項目中,還有第二個問題。你放入上下文的設計散文、示例、計劃、註釋、工單和舊驗收標準越多,哪些部分是指令、哪些部分是工件就越不明顯。

我不會稱其為安全意義上的提示注入。沒有人試圖攻擊模型。它更接近於自我造成的指令漂移。上下文中包含舊的設計意圖、當前實現、一半有效的示例、三個會話前生成的計劃,以及可能仍然描述已不存在類的過時軟件設計文檔。此時,模型不是在讀一個規格,而是在多個相互競爭的真相來源之間取平均。

這就是過度規格停止幫助並開始混淆模型的時候。代理無法判斷一個段落是活躍的需求、歷史記錄,還是代碼已經替換的東西。

設計文檔在早期很有用,因為代碼還不存在。後來,它需要縮小。一旦接口、測試和不變量成為現實,詳細的構建計劃應該開始消失。“保留代碼本身難以表達的部分:業務原理、非目標、安全約束、外部合約,以及你不想通過試錯重新發現的少數不變量。刪除那些只是重複類和方法已經做的事情的散文。

否則,你最終會有兩個規格。人類會在審查中抱怨這一點。代理通常會試圖同時服從兩者。

API可以讓代碼表現得像規格

這個故事也有一個更樂觀的版本。一些代碼庫比其他的更快達到“代碼即規格”的程度,而API設計是一個重要原因。

如果內部API通過約定、弱類型參數、設置魔法和通用錯誤隱藏行為,代理無法將代碼視為規格。它必須從分散的散文和試錯中重建規則。這對人類很慢,對模型更糟。

反之亦然。一個具有顯式名稱、任務級方法、強類型、可讀驗證、有用示例和可操作錯誤的API給代理提供了具體的基礎。如果代理可以檢查表面區域,看到方法的作用,理解什麼輸入是合法的,並從錯誤中恢復而無需猜測,那麼代碼自己承擔了更多的規格負載。

這就是AI友好的API設計思想在實踐中重要的地方。顯式的可發現性優於約定。方法應該與實際任務對齊,而不是迫使代理通過十幾個脆弱的步驟。類型和驗證應該顯示合法輸入的樣子。錯誤消息應該指向下一步修復,而不僅僅是宣佈失敗。內省和示例幫助模型從已有的代碼庫中學習API的形狀。性能透明度也很重要,因為如果API沒有給出線索,代理會愉快地圍繞昂貴調用編寫正確但糟糕的循環。

這不僅關乎公共SDK。它適用於內部服務邊界、庫客户端、倉庫抽象,甚至大型單體倉庫中的輔助類。API越容易發現和檢查,代理就越容易將代碼視為權威規格,而不是將更多散文拖入上下文。我之前更深入地寫過所有這些,如果你感興趣的話。

投資方向

我堅信的是,沒有單一的合適規格程度。答案取決於你正在做的工作類型。對於小的、有界的任務,最佳點通常是結構化意圖:目標、幾個例子、非目標和清晰的驗收標準。這通常足以讓代理保持高效,而不會使設置比任務本身更重。

對於確定性工作,如CRUD流程、API集成和數據轉換,最優值向右移動。這些領域容易約束且容易測試。更多規格很快就能自償,因為它減少了重複審查和返工。這是BDD、契約測試和可執行驗收標準最有幫助的地方。

對於探索性工作,如架構選項、研究綜合或新穎產品想法,最優值向左移動。過度規格可能會扼殺使代理有用的靈活性。在這種情況下,我寧願指定邊界而不是結果:必須為真的事情、絕不能發生的事情、需要哪些證據,以及哪些決策仍然需要人類。

對於多代理管道,最優值再次向右移動。每個代理之間的邊界需要一個合約。沒有這個,你不是在協調一個系統。你是在堆疊解釋,並希望它們互相抵消。

沒有普遍的最優值。合適的規格程度取決於工作是探索性的、有界的、確定性的還是多代理的。

所有四種情況下的共同規則很簡單:在擴展實現之前驗證規格。

從敏捷和極限編程中倖存下來的部分

我不認為代理使敏捷或極限編程變得無關緊要。它們使有用的部分更容易與人們已經容忍的部分分離。

第一個犧牲品是那些主要是為了協調人類努力而存在的儀式。