跳到主要內容

【2026 最新】State Tracking 是什麼?用 StateBench 四種更新檢查長 Context(新手白話篇)

最後更新: ·
State Tracking 教學首圖

你請 AI 讀完一串倉庫紀錄:紅箱原有三件貨,後來加兩件,再把藍箱當時的數量抄過來。它找到了每一段文字,最後數量卻答錯。這就是 State Tracking(狀態追蹤)要檢查的問題:讀過更新之後,能不能算出「現在是多少」?

這篇專為第一次接觸模型評測、願意複製一段 Python 的讀者寫。你會用 StateBench 的四種更新認識難度,再建立有答案本的小考卷,分開檢查變數與整題正確率。只想懂概念,可以先跟著手算;要動手,準備 Python 3 與空白練習資料夾。

依 2026 年 11 月 6 日查閱的原始論文、程式與資料卡整理。AlphaLab 執行了本文 CPU 題目產生器,並用固定版本的官方 evaluator 核對十二組語意題的真值;未執行模型推論,因此下方沒有模型成績或架構排名。

先說結論:現在的值=起點+依序生效的更新

State Tracking=沿著更新順序,維護每個對象的當前值。像櫃台一本庫存簿:找到舊頁是檢索,依序對完入庫、改單和轉抄才是追蹤。長 Context(一次交給模型的文字範圍)容得下多少字,與能追對多少次更新,是兩張成績單。

  • 先分清固定、覆寫、累加、跨變數複製,再比較同一種題目的長短。
  • 先由程式算真值,答案本留在本機;送給模型的只有題目。
  • 程式式與試算表式題面分開記分;小題通過後,再擴充題數與長度。

一、State Tracking 是什麼?四個抽屜、四種改法

變數就是貼名字的小抽屜,值是裡面的數字。Ai2 在 2026 年 11 月 3 日介紹 StateBench,用四個理論層級區分更新。下面的日常例子幫你理解操作;正式分類還涉及有限狀態與代數結構,不能光看一行指令便替所有任務定級。

①「寫好就固定」:r-trivial

痛點是長文件中的固定資訊被忘掉。先測找回原值:例如抽屜 a 一直裝著 3,後續對它的寫入也仍是 3。驗收問的是最後能否找回 3,並不需要把歷次變動累積起來。

②「後寫蓋前寫」:aperiodic

痛點是 AI 把舊設定當現況。改查最後有效寫入:a ← 3,後來 a ← 8,現在就是 8。像冷氣設定,最後一次調整決定目前目標;遇到資料撤銷或例外條件,則要另外定義規則,本練習只處理明確賦值。

③「用自己的舊值再算」:soluble/程式名 solvable

痛點是最後一筆只寫「加幾個」,單看它得不到總數。沿途累加:a ← (a + 5) mod 10 是把目前值加 5,再取除以 10 的餘數。原來 8 就變 3,像十格循環計數器。這是固定有限值域,與無上限的整數帳本有不同邊界;Python 用 % 表示餘數,見官方數字操作說明。

④「抄另一格現在的值」:general finite/程式名 periodic

痛點是你得先追好另一個抽屜,才能處理這次更新。讀取來源當下的值:a ← b 會把當時的 b 複製給 a;後來 b 改變,a 不會因此一起變。官方 evaluator明確採這種立即複製語意。它不是試算表裡持續重算的 =B1 公式。

State Tracking 四種更新:固定、覆寫、累加與跨變數複製
AlphaLab 概念示意:依更新讀取的資訊拆題;例子不表示每個單一小題都具有該層級的最壞難度。

二、先手算一次:為什麼交換需要暫存格?

先看兩格的教學例子:a=3、b=8、TMP=0。依序做 TMP ← a、a ← b、b ← TMP。第一步得到 TMP=3;第二步 a=8;第三步 b=3。最後是 a=8、b=3、TMP=3。

如果直接做 a ← b 再做 b ← a,第二步讀到的 a 已經是 8,兩格都變成 8。這個錯誤很適合教人理解相依性,但兩格交換不等於研究中五個以上變數可呈現的非可解群難度。下面的考卷使用五個普通變數,再加一格 TMP,仍只是一個小型教具。

StateBench 的設計重點還有「同一條來源」。官方衍生邏輯把跨格複製改寫成常數或自我累加,保留對應更新位置。覆寫、累加與複製版本可在每一步得到相同狀態;固定版本則回到各格最初的值。考卷難度的差別在於你必須讀取什麼資訊,並非答案數字比較大。

三、State Tracking 小考卷:先讓 CPU 寫好答案本

痛點是拿 AI 的答案反過來當標準答案。先建立可獨立核對的真值。把下方存成 mini_statebench.py,在空白資料夾執行 python3 mini_statebench.py。程式使用標準函式庫,會建立或覆寫目前目錄的 state-lab 同名檔案;重跑前先保存舊紀錄。

這是 AlphaLab 自製的教學產生器,借用四種更新與配對原則;不是官方完整資料生成流程。它把 2、20、200 次交換展開成 12、66、606 筆賦值,再以兩種題面產生 24 份題目。這三檔只是短、中、長的入門練習,尚不代表數萬 Token 的長 Context 壓力測試。

import json, random
from pathlib import Path

out = Path('state-lab'); out.mkdir(exist_ok=True)
names = ['a', 'b', 'c', 'd', 'e', 'TMP']
answer = {}; checks = []
for swaps in (2, 20, 200):
    rng = random.Random(7)
    source = [('set', i, v) for i, v in enumerate([1, 2, 3, 4, 5, 0])]
    for _ in range(swaps):
        a, b = rng.sample(range(5), 2)
        source += [('copy', 5, a), ('copy', a, b), ('copy', b, 5)]
    state = {}; first = {}; traces = {k: [] for k in ('fixed', 'overwrite', 'add', 'copy')}
    for op, t, x in source:
        old = state.get(t, 0)
        value = x if op == 'set' else state[x]
        first.setdefault(t, value)
        traces['fixed'].append(('set', t, first[t]))
        traces['overwrite'].append(('set', t, value))
        traces['add'].append(('set', t, value) if op == 'set' else ('add', t, (value-old) % 10))
        traces['copy'].append((op, t, x))
        state[t] = value
    for family, ops in traces.items():
        truth = {}; steps = []; code = []; sheet = []
        for op, t, x in ops:
            key = names[t]
            if op == 'set':
                truth[key] = x; c = f'{key} <- {x};'; s = f'Enter {x} in cell {key}.'
            elif op == 'copy':
                truth[key] = truth[names[x]]; c = f'{key} <- {names[x]};'
                s = f'Copy the CURRENT VALUE of cell {names[x]} into cell {key}.'
            else:
                truth[key] = (truth[key]+x) % 10; c = f'{key} <- ({key} + {x}) mod 10;'
                s = f'Add {x} to cell {key}, keeping the result modulo 10.'
            code.append(c); sheet.append(s); steps.append(dict(truth))
        for form, lines in [('code', code), ('sheet', sheet)]:
            case = f'{swaps}-{family}-{form}'
            prompt = ('Execute these edits in order. Copy means a value snapshot, never a live formula. '
                      'Return ONLY a JSON object with integer values for a,b,c,d,e,TMP.\n'
                      + '\n'.join(lines))
            (out/f'{case}.txt').write_text(prompt, encoding='utf-8')
            answer[case] = {'truth': truth, 'steps': steps, 'assignments': len(ops), 'characters': len(prompt)}
        checks.append((family, swaps, truth))
(out/'answers.json').write_text(json.dumps(answer, indent=2), encoding='utf-8')
print('Created 24 prompts and answers.json; model calls: 0')

看到 Created 24 prompts and answers.json; model calls: 0,代表材料已產生。answers.json 同時保存最後狀態、逐步狀態、賦值筆數與文字長度。不要把答案本貼給模型。本文在 CPU 核對的最短複製題,依 a、b、c、d、e、TMP 順序,真值為 4,3,2,1,5,4;這是程式計算結果,並非模型作答結果。

想改用完整 StateBench,先查看固定版本的執行需求與官方資料卡。本次核對版本是 5b333b8d426638d8825f40efe8a508c20eb85730,官方套件要求 Python 3.12 以上;資料的格式、split 與 revision 也應逐項記下。先預覽樣本,再決定下載範圍,別直接啟動完整建庫或訓練。

四、兩張題面、一張記分單:怎樣測才公平?

  1. 固定考生與設定。寫下模型完整版本、日期、system prompt、推論預算、temperature、輸出上限、是否可用工具。介面未提供的設定記為「未提供」,不要猜值。
  2. 每題開新對話。先貼 state-lab/2-copy-code.txt;只接受六個整數欄位的 JSON。關閉額外工具測到的是文字推導;允許程式工具則另建組別,測的是模型與工具的組合。
  3. 按四層與三檔長度分組。保存原題與完整輸出。Token 是模型切分文字的單位,不能把賦值筆數或字元數當成 Token 數;實際呼叫時另記服務回報的輸入 Token 與是否截斷。
  4. 再換 sheet 題面。例如 2-copy-sheet.txt 與 code 版本共用答案。這裡的 cell 是文字題面,不必開試算表軟體;複製的是數值快照。換題面時不一起換模型或提示。

把模型回覆存為 response.json,再把以下程式存成 score_state.py。執行 python3 score_state.py 2-copy-code response.json,就能核對那一題。它故意不接受 Markdown 圍欄與額外說明,格式錯誤另列,避免解析器替模型偷偷修答案。

import json, sys
from pathlib import Path
case, filename = sys.argv[1:]
key = json.loads(Path('state-lab/answers.json').read_text())[case]['truth']
try:
    got = json.loads(Path(filename).read_text())
    valid = (isinstance(got, dict) and set(got) == set(key)
             and all(type(v) is int for v in got.values()))
except (ValueError, OSError):
    valid = False
if not valid:
    print('FORMAT_ERROR: expected exactly six integer fields')
    raise SystemExit(2)
hits = sum(got[k] == key[k] for k in key)
print(json.dumps({'case': case, 'correct_variables': hits,
                  'total_variables': len(key), 'exact_match': hits == len(key)}))

逐變數正確率=答對欄位數 ÷ 全部欄位數;整題正確率=六欄全對題數 ÷ 該組總題數。本練習六欄包含 TMP;若你另報五個普通變數,須改標分母。格式錯誤保留在全題成功率的分母,另報格式錯誤數,不可悄悄刪掉後只算容易解析的題。

工作表先開這些欄:case|seed|模型版本|設定|題面|賦值數|輸入 Token|正確欄位/6|整題對錯|格式/截斷|費用。未作答就留空。當每組只有一題,結果只能叫「這題通過/失敗」;多換幾個 seed、保留未調提示的測試題後,才比較各組比例,並同時報題數。

五、追第一個錯點,再讀研究結論

痛點是只知道最後錯,卻不知道哪裡出事。做前綴診斷。保留失敗題,在第 6、9、12 筆等邊界截斷更新,分別新開對話詢問當前六格,與答案本 steps 的對應位置核對。陣列從 0 開始,所以第 k 筆對應 steps[k-1]。

先粗查,再逐筆找出「第一個被觀察到答錯的前綴」。前綴正確性可能先錯後對,不能假設單調並直接二分搜尋。這個診斷也改變了輸入與提問方式,定位的是可觀察錯點,無法據此斷言完整作答時的內部推理正好在那一步壞掉。

研究結果則分三層讀:預訓練模型反映已有能力與題面敏感性;直接用任務資料訓練反映學習與長度外推;理論分析依指定精度、注意力與架構假設推導可表達範圍。原論文的預訓練評估觀察到長序列與題面會影響表現;針對任務訓練的循環/混合模型,在部分層級展現更好的長度外推。這些條件要跟著結論一起讀,不能縮成「某種架構全面獲勝」。

ACL 2023 的 Entity Tracking 研究也以初始狀態與連續操作探測模型,提醒我們將狀態追蹤當成獨立能力來測。實務上,跨人員關係、無限新增物件、歧義描述與缺失事件,都比這份有限變數小考卷多出問題。

如果你的下一題是「把狀態交給外部程式會不會更好」,請另做同任務、同工具權限、同預算的對照,量完成率與修正成本。這是本文提出的工程假說,本篇 CPU 核對只確認答案產生器;原 StateBench 評估也不能替你的 Agent 部署做驗收。記憶來源問題可接著讀RAW-RAG 證據覆蓋診斷,程式決策分工則看確定性核心與機率邊緣。

六、常見問題:八個先講答案的判斷

長 Context 能放進去,就代表會追狀態嗎?

不代表。先檢查輸入是否完整,再依四種更新分開作答;收得下文字與算對結果各要證據。

找到最後一行就夠了嗎?

覆寫題常能這樣處理;累加與跨變數複製則要知道被引用的當前值。先辨認更新讀取誰。

這裡的 soluble 是「所有題都能解」嗎?

不是。這是代數分類用語;程式使用 solvable 名稱,本文用自我累加幫你建立直覺,不把名稱讀成能力保證。

兩格交換失敗,就證明模型架構的理論上限嗎?

不行。一次小題失敗也可能來自提示、解析或輸出限制。理論上限要對照論文的精確假設;五格教具通過也不能反推一般定理。

我只用聊天介面,可以測嗎?

可以做入門檢查。每題開新對話,記日期與介面顯示版本;可控設定較少時,把結果限定在該次介面測試。

讓模型用 Python,成績會比較公平嗎?

看問題。想評模型本身的文字追蹤,就分開工具組;想評交付任務,則把工具可用性、執行錯誤與成本一併評分。

這 24 份題目等於官方 benchmark 嗎?

不是。它們是同一 seed、三個長度的教具,配對題面也不是獨立樣本。正式研究需保留官方資料版本、抽樣方法與完整評估設定。

CPU 真值全通過,就能填模型正確率嗎?

不能。先取得實際模型輸出,再用獨立答案本核對。尚未呼叫的結果留空,避免把評分器通過誤當模型通過。

給新手的三個重點

  • 先辨認更新要讀初值、最後寫入、自身舊值,還是另一格的當前值。
  • 先算真值,再分長度與題面記分;別把字元、Token 與更新筆數混用。
  • 讓每個結論都帶著樣本與配置:這題算對了,下一步才是換題、加長和驗證外推。

下一步:先交出一題可對帳的狀態更新

現在先跑產生器,手算最短的交換,再只送一份 2-copy-code.txt 給模型。保存回覆、核對六格、把結果填進工作表。記住:現在的值=起點+依序生效的更新。想把這套評測方法用到自己的 AI 工作流程,可從AlphaLab AI 專區繼續學習,或透過AlphaLab 課程安排系統化練習。

ALPHALAB 社群

有問題?來 Telegram 聊

和 Terry、編輯、其他網友一起討論這篇文章。提問、分享觀點,回覆更即時。

加入 Telegram 討論

📩 訂閱 AlphaLab 電子報

週日 Weekly 週報+週二、週四 Alpha Signal,每週最多三封。

我們不會 spam,隨時可退訂。已訂閱?管理訂閱偏好(會寄登入連結到你的信箱)

主題篩選與退訂說明

寄送日期以台灣時間為準。主題偏好會篩選每期精選,並非每篇新文章的即時通知;當期符合主題的文章不足時會略過寄送。

未勾選任何主題會收到所有主題的精選,並不會停止寄信。

取消勾選 Alpha Signal 可停止週二、週四短報,仍保留週日週報。若要停止所有電子報,請使用信件底部的「取消訂閱」。