學習 / 實作
把答案放在上下文中間,模型就會漏掉嗎?一次提前停止的對照試驗
llm · 實驗回顧
用 Java 固定 6 組虛構資料,對照開頭、中間、末尾與無答案條件;公開 29 次請求、HTTP 429 和不能下的結論。
實驗結果
瀏覽統計暫不可用
本文目錄 7
把資料塞進請求,並不意味著模型一定能利用裡面的每一條事實。當模型沒找到答案時,怎樣區分資料位置、資料缺失與請求本身失敗?
這次先把問題收窄成一個可核對的任務:從一組虛構專案紀錄中,回傳指定專案的交接編號。對同一份資料,僅移動含答案的那一行,再加入完全沒有答案的對照。
結果先說清楚:計畫 48 次,實際嘗試 29 次。26 次正常回應均符合預期,接著連續 3 次 HTTP 429 觸發停止。剩下 19 次未執行。 這是一輪未完成的試驗;沒有觀察到已回傳樣本答錯,不等於已經證明位置無關。
1. 先排除一個混淆:快取不是證據
上一份 KV Cache 拆解討論了「請求提供什麼」與「推論怎樣重用計算」的區別。這裡不討論模型記住了上一次對話什麼:每次請求只有固定 system 和當前 user,沒有歷史問答。
服務回傳的 cached_tokens 也不能說明答案來自長期記憶。它不是本輪的自變數,更不能代替對完整請求內容的檢查。
本輪的靈感來自 Lost in the Middle:該論文在其所評測的任務與模型上報告,相關資訊所處位置可能影響表現。我們的任務、模型、材料長度與樣本規模均不同,不能把這輪小試驗稱為論文重現。
2. 建構一個答案可獨立核對的任務
範例事實為虛構專案「松塔试验项目」的交接編號 QX-7319。實際請求中的專案名稱與材料保留簡體中文原文,並未隨網頁語言變動。
六個專案名稱與編號全部是人為產生的實驗材料,不對應真實企業或設備。預期答案來自凍結的 cases.json,不由另一個模型評分。
每份上下文包含 60 行干擾紀錄,也帶有專案識別和形似 NX-4000 的編號。目標事實不能僅憑「全文唯一一個編號」被找出來,模型需要比對問題中的專案名稱。
三個含答案條件使用同一組 61 行資料,只移動目標行:
| 條件 | 目標行位置(從 0 開始) | 其他材料 |
|---|---|---|
| beginning | 0 | 相同的 60 行干擾紀錄 |
| middle | 30 | 相同的 60 行干擾紀錄 |
| end | 60 | 相同的 60 行干擾紀錄 |
| absent | 沒有目標事實 | 用一行無關紀錄代替目標事實 |
問題始終放在資料後面。因此實驗改變的不只是行號,也改變了目標事實與最終問題的距離;不能聲稱已經分離出某個注意力機制的作用。
absent 用來檢查沒有證據時是否拒答。替代句與事實句並非精確等長,因此它是缺失對照,不是另一組嚴格等長的位置條件。
3. 請求、評分和預算怎樣凍結
本輪設定為 Agnes 的 agnes-2.5-flash、temperature 0、max_tokens 512。請求約為 4298–4301 個 UTF-16 字元,統計的是序列化後的請求 JSON,包含提示、欄位與材料,絕不是上下文 token 長度。
程式碼和材料先提交,再發請求。執行清單記錄程式碼版本、JDK 版本及輸入 SHA256。完整 48 項順序儲存在 plan.json,使用固定 seed 20260928 打亂條件順序。
- 6 個事實 × 4 個條件 × 2 次重複,共 48 次上限。
- 依序呼叫,不自動重試。
- 連線逾時 10 秒,讀取逾時 90 秒。
- 連續 3 次請求或協定失敗即停止。
- 正常回應後,先檢查 assistant 和 finish_reason=stop,再評分正文。
讀取逾時限制單次阻塞讀取,不是整個請求的硬截止時間。temperature 0 也不能保證託管服務每次位元級一致。
| 正文 | 有答案條件 | absent 條件 |
|---|---|---|
| 精確預期編號 | correct | incorrect(無證據猜測) |
| UNKNOWN | abstention | correct_abstention |
| 另一個合法編號 | incorrect | incorrect |
| 解釋段落或其他格式 | format_error | format_error |
正文評分前只移除首尾空白,不自動擷取編號或修復回答。HTTP 429、協定異常、網路失敗走另一條路徑,不會計入模型答錯。紀錄中的 transport_error 是較廣泛的程式分類,要搭配 errorCode 讀;本輪三個錯誤均為 http_429。
4. 真正觀察到了什麼
執行時間為 2026-09-28 15:52:59 至 15:56:38 UTC。逐條重算後的結果如下:
| 條件 | 計畫 | 已嘗試 | 正常回應 | 其中正確答案/正確拒答 | HTTP 429 | 未執行 |
|---|---|---|---|---|---|---|
| beginning | 12 | 8 | 8 | 8 | 0 | 4 |
| middle | 12 | 8 | 6 | 6 | 2 | 4 |
| end | 12 | 7 | 6 | 6 | 1 | 5 |
| absent | 12 | 6 | 6 | 6 | 0 | 6 |
| 合計 | 48 | 29 | 26 | 26 | 3 | 19 |
前 26 次請求有有效輸出;第 27–29 次回傳 429,隨後程式停止。429 的具體限額原因未從紀錄確認,不推斷為餘額不足,也沒有換金鑰繞過限制。
有答案的 20 份回應均比對成功;6 份 absent 回應均為 UNKNOWN。它們是以正常回應為條件的觀察值。由於兩次重複屬於同一組材料,26 份回應也不是 26 個獨立難題。
回傳的 usage 累計為 prompt_tokens 74,476、completion_tokens 2,567、total_tokens 77,043。只涵蓋帶 usage 的回應,不是帳戶帳單,也不包含未回傳 usage 的請求之未知消耗。
5. 為什麼不能據此宣布「中間位置沒問題」
- 試驗沒有跑完。 組間樣本量不平衡,剩餘項不能補成成功或失敗。
- 任務可能太容易。 六組資料結構規則、答案短、要求精確比對;不等於多文件推理或長篇自然文字。
- 材料並不長。 請求字元數不是 token 數,更不代表涵蓋模型的長上下文能力邊界。
- 單次託管模型設定。 沒有比較其他模型、模型快照、不同服務負載或溫度。
- 不能歸因到內部機制。 最終答案不揭露模型如何尋找證據,不足以解釋注意力分配。
因此本輪可以說的是:在這份固定短材料、已正常回應的樣本中,三個位置都出現了正確檢索,缺失對照出現了正確拒答。目前沒有足夠證據比較位置差異大小。
實驗沒有出現預期中的錯誤,並不是白做。它幫助辨識下一輪需要提高的任務難度,以及請求可用性這個必須獨立記錄的因素。
6. 從程式碼到證據,怎樣自己核對
工程放在 Java 倉庫的 experiments/01-context-position,而不是混進部落格前端。它與 Demo 04 共用 Java 8 / Gson 基礎,但研究問題不同。
先執行不存取 API 的檢查:
mvn -q compile
mvn -q exec:java -Dexec.args=--self-test
mvn -q exec:java -Dexec.args=--dry-run92 項離線斷言涵蓋目標唯一性、位置、材料一致性、無答案洩漏、評分及預算。另一個選用的 Node.js 審計腳本獨立讀取已儲存紀錄:
node audit.mjs evidence/20260928-l1它重算每個請求 hash、實際字元數、條件組合、正文評分與停止條件,再核對 summary.json。Gson 將溫度儲存為 0.0,審計保留這個序列化差異,避免把「JSON 語意一樣」當成「請求位元組一樣」。
需要重新實測時,自行設定 AGNES_API_KEY 後,使用新的輸出目錄:
mvn -q exec:java "-Dexec.args=--run evidence/my-run"這條命令最多傳送 48 次計費請求。不要覆寫舊證據,也不要把新協定的結果拼回這一輪。金鑰只從處理序環境讀取;倉庫沒有保存請求標頭、金鑰或推理正文。
7. 下一輪先改什麼
下一輪需要先重新約定協定:加入合理的請求間隔與明確的 429 處理策略,再增加材料長度和自然文字干擾。保持同一案例的條件配對,並把「是否收到完整回應」與「完整回應是否正確」分開統計。
只有這些條件穩定後,比較開頭、中間、末尾才有解釋空間。本輪不繼續追加請求去追求更好看的完成數;現有 29 份紀錄已經足夠公開說明方法、觀察和邊界。
可以用三個問題檢查理解:答案到底有沒有進入請求?請求有沒有成功回應?回傳答案是否有證據支持? 這三個問題要分別回答。
寫給未來的自己合上文章前,留下一點自己的理解。
你的私人學習便箋,只存在目前瀏覽器,不會上傳或公開。清理瀏覽器資料會遺失,請匯出留存。三種語言共用這篇文章的便箋。
繼續探索
繼續探索
接下來,走哪條路?
- Java LLM 實踐(二):HTTP 200 之后,怎樣驗收模型的 JSON? →
從一次真實的代碼圍欄響應和三次超時出發,用 Java 8 實現嚴格結構校驗、受限格式適配與可追溯的失敗處理。
- KV Cache 拆解:多輪對話的歷史,為什麼還要再傳一遍? →
從因果注意力推導 K/V 復用,用一個可計算的記憶體例子區分推理快取、前綴快取與聊天記錄。
依據文章關聯與同主題已發布內容整理,不使用隨機推薦。