跳到內容

對話紀錄

一段長時間的對話終究會撞上一堵硬牆:模型的情境視窗。本頁的一切都是因為這堵牆而存在,而真正有意思的部分在於:什麼會被丟掉、什麼會被留下,以及什麼還找得回來。

它們不完全是彼此替代的選項,更像是一架梯子,從最便宜的那一階開始。

機制 代價 保留 丟失
省略 無 敘述中的每一個字 平淡無奇的舊工具結果
影像捨棄 無 它們周圍的文字 舊截圖
快照 無 每一個字,以像素形式 無視覺模型的可讀性
摘要 一次模型呼叫 一段敘述 它沒有挑選的細節

省略與影像捨棄會先執行,因為它們免費,而且在真正要緊的意義上是無損的:它們丟掉的是本來就沒有人會再讀一遍的大量內容。

摘要是這四種之中唯一要花掉一次模型呼叫的,也是唯一會替你決定什麼才重要的。兩者都是實實在在的代價,而更有意思的是那次呼叫,因為它發生的時機。

壓縮通常在撞牆之前依閾值觸發。但它也會被動執行:在供應商自己以請求過大為由拒絕之後——啟發式估算低估了供應商實際量到的數量。在這種情況下,採用摘要的壓縮器必須再發一次請求來縮小情境,而它發出的那次請求,正是剛剛溢出的那一次。

快照式壓縮會把被丟棄的紀錄描繪成密集的像素字形頁面,再以影像的形式交回來。

前提在於一個計費上的怪癖:視覺模型對影像的收費是固定費率或按面積比例,和影像裡有多少字元毫無關係。一萬二千個字元的丟棄對話,要付出相當於一萬二千個字元的文字 token。同樣這些字元描繪成一頁,只花一張影像的錢。

它值得擁有、而不只是聰明的地方在於:它不需要模型呼叫、不需要金鑰,也不需要網路。它是溢位復原期間永遠可用的唯一一種策略。

重建後的形狀是:逐字保留的開頭、轉為影像的中段、逐字保留的結尾。開頭是任務以及下游一切都要回頭參照的限制條件;結尾是目前工作所在之處。中段則是最少被重讀、卻最花成本的部分。

快照每一輪都會從保留的來源文字重新描繪,絕不是從上一輪的像素而來。把影像再影像化,會使字形每壓縮一次就劣化一個世代,直到沒有東西讀得出來。

以往,執行環境的每一次執行都是從空的紀錄開始,再從提示中的 <context> 區塊重建連續性——那是對話的摘要,而不是對話本身。由此衍生出三件事:

  • 接續只是重新講述一遍。 模型從未看見自己先前的推理,也沒看見工具實際回傳的位元組,只看見對它們的描述。
  • 倒帶隨著行程一起消失。 checkpoint 是即時訊息清單裡的索引,因此重新啟動就會弄丟模型設過的每一個標籤。
  • 重試分不出「沒東西可重試」與「什麼都沒載入」。 重新啟動之後,失敗的那一輪無論如何都已從即時狀態中消失。

這三件事都靠保存逐字稿來解決。它會在每一個回合邊界儲存,絕不在回合中途儲存:在工具呼叫與其結果之間捕捉到的紀錄,是沒有任何供應商會接受的,因此在那個瞬間當機,還原的是前一個回合,而不是無法重播的半個回合。

接續的執行會被裁剪到只留最新的訊息,並在不是孤立工具結果的邊界上切斷——呼叫已被裁掉的結果,是供應商會直接拒絕的請求,而一份送不出去的逐字稿,比短一點的逐字稿更糟。

每一則訊息都會記錄自己是從哪一則接續而來,而每個對話都會指名自己目前的分支頂端。就這一個決定,撐起了整個功能。

分支不寫入任何東西。 它只是移動指標。你離開的那條路徑仍在原處,所以切換回去也只是再移動一次指標,而不是還原——而為了重跑而編輯提示,也不再會讓你失去原本拿來對照的那個答案。

少了它,每一種往回走的方式都必須隱藏或刪除訊息,而隱藏是下一個讀取者看不穿的謊言。

分支 分叉
會發生什麼事 指標移動 路徑被複製
去向 同一個對話 一個新對話
代價 無 分支的一份複本

分叉會以全新的 id 複製,而不是共用資料列。兩個共用資料列的對話會互相顯示對方後來的訊息,而這正是分叉絕不能做的事。

執行中的 checkpoint / rewind 配對會標記一個乾淨的回合邊界,並在探索之後回到該處,同時保留一份摘要。因為檢查點會與逐字稿一起保存,模型在重新啟動前設下的標籤,依然會落在當初設定的位置。目標沒能在裁剪中存活的檢查點會被丟棄,而不是夾到最近的位置——倒帶「到那個標籤」卻落在別的地方,正是標籤存在的目的要防止的那種失敗。