Andre

Originally published at olund.dev.

我使用的工具之一會根據設定好的語音生成長篇書面內容:這是一種編輯身份,描述受眾、語域、詞彙,以及作者的表達方式。這個身份設定是一段配置中的散文。而語氣的散文配置有一個令人困擾的特性:它們是單向的。你描述想要的語音(「不慌不忙、充滿好奇、從第一原則解釋、絕不誇張」),生成器加以使用,然後你只在支付完整生成執行費用並閱讀結果後,才知道描述是否有效。如果語域不對,你就修改形容詞,再付一次費。

回饋迴路就是問題所在。透過完整生成來調整人格,就像每次都要承辦婚禮才能調整食譜。我想要的是嘗試:給定這個身份,馬上用這個語音說兩句話,費用幾乎為零。

最小的可能代理程式

解決方法是預覽代理程式,設計目標是讓它盡可能接近免費的 LLM 呼叫,因為猶豫是否執行的預覽就不會被執行。它的一切都是減法:

  • 沒有工具。 這個代理程式無法讀取檔案、瀏覽或搜尋。它需要的一切——身份文字和可選主題——都以內嵌方式傳遞在發送中。這不僅是成本控制:沒有工具且完全內嵌上下文的代理程式是可重現的。相同輸入、相同類別的輸出,沒有環境因素會造成偏差。
  • 快速的本地模型。 試聽語域是狹窄的工作;它需要對風格描述的忠實度,而非推理深度。呼叫會路由到我工作執行階段中最便宜的層級——在自己機器上執行的小型模型。一次測量過的試聽端到端約 500 個 token,在本地硬體上成本趨近於零。
  • 嚴格的輸出結構。 代理程式必須回傳兩到六行範例,每行是一兩句語音實際會說的話,且僅此而已——沒有標題、沒有舞台指示、沒有關於語音的評論。結構在呼叫層強制執行,因此格式錯誤的回應會重試,而非到達使用者介面。預覽是一份合約,而非聊天。
  • 本質上是短暫的。 提供此服務的路由不寫入任何東西:沒有資料庫列、沒有成品、沒有歷史記錄。持久化的預覽輸出會變成狀態——需要列出、遷移和清理的東西。預覽的全部價值在於它會消失。
  • 超時與一次重試。 九十秒,一次恢復嘗試,然後明顯失敗。卡住的預覽比出錯的預覽更糟。

提示詞端是一條規則以三種方式重複:精確匹配身份的語氣、語域和詞彙;每行必須是獨立的、可說出的散文行;不要進行元評論。描述語音而非成為語音的範例行是失敗模式,而指示直接針對此進行攻擊。

它所創造的迴路

在設定使用者介面中,身份編輯器旁邊有一個範例按鈕。輸入可選主題,點擊,片刻之後:配置語音中的幾行文字。編輯身份,再次取樣。調整迴路從「生成完整文章、閱讀、皺眉」縮短為每次迭代只需數秒。

有兩個使用者介面決策的重要性超出它們看起來的程度:

預覽不會使任何內容失效。 它是一個普通的即發即回呼叫,沒有快取更新,因為它不改變任何狀態。將預覽作為變更連接到應用程式的資料層是一種分類錯誤,會使每次預覽都造成重新擷取的成本。

空白狀態具有教學功能。 在未設定身份的情況下,按鈕不會靜默停用;端點會以「身份未設定」拒絕,而使用者介面會說明這一點。前提條件不可見的預覽功能會被視為故障。

下方還有一個接縫決策:路由會同步等待工作者,限制在兩分鐘,而不是回傳客戶端輪詢的工作 ID。預覽是互動式的——使用者正坐在那裡。當預覽需要進度條時,它就已經失敗了作為預覽的職責,因此 API 形狀編碼了延遲預算:如果這無法在使用者觀看時回答,它就應該出錯,而不是串流狀態更新。

為什麼這是一個模式而非功能

一般形狀是:當系統消耗人類撰寫的描述並產生昂貴的東西時,在兩者之間插入最便宜的取樣器。 描述到輸出的差距是信心悄悄消逝之處——你撰寫了配置,你認為它表達了你的意思,而提供的唯一驗證方式卻需要完整執行。

取樣器在以下情況下值得存在:

  1. 即時到足以成為反射動作。 數秒,而非數分鐘。當取樣需要決定是否值得時,迭代就會停止。
  2. 免費到足以無罪惡感。 本地模型或最便宜的 API 層級。任務本質上是狹窄的;使用能完成它的最狹窄工作者。
  3. 受限到足以誠實。 在目標格式中以結構強制輸出。回傳關於它會做什麼的文章的取樣器是表演。
  4. 無狀態到足以被忽略。 沒有持久性、沒有歷史記錄、沒有清理。執行四十次;什麼都不會累積。

我現在每當散文配置驅動生成時就會採用這種形狀:在文章之前取樣人格、在批次之前取樣摘要風格、在審查執行之前取樣審查者的嚴厲程度。每個取樣器都是一下午的工作,因為減法建置起來很快——整個代理程式定義適合一個畫面,而它所依賴的工作者執行階段已經存在。

潛在的安靜教訓與模型路由有關。本能是將每個任務發送到可用的最強模型。但預覽的工作是具代表性且即時的,而非最大化——而具有嚴格結構和內嵌上下文的小型本地模型,比具有更多自由度的前沿模型即興發揮,更能代表「配置的語音聽起來會是什麼樣子」。將工作者匹配到任務的狹窄度,有些任務就會變得近乎免費。