iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0
ChatGPT & Codex

AI Visual Learning Lab: 30 天用 ChatGPT × Codex 打造 AI 視覺化學習工具系列 第 23 篇

Day 23|我不想再靠 Demo 證明自己了:拿陌生教材攻擊 Universal Learning World Compiler

  • 分享至 

  • xImage
  •  

Day 22 做完之後,Visual Learning Lab 已經可以把不同知識送進不同的 Learning World。

拋體運動可以進 Spatial World,Phase 可以進動態數學世界,Probability 可以進集合與機率世界,Ohm’s Law 可以生成 Analogy World,Queue 也開始能走進 generic Process Runtime。

做到這裡其實很容易產生一種錯覺:

好像已經很通用了。

但問題是,前面很多案例都是我們開發過程中一直拿來測的東西。

我們知道 Queue 長什麼樣、知道 Projectile 怎麼跑,也知道 Ohm’s Law 適合用水流來做類比。如果最後一直拿這些熟悉的題目證明系統很強,很容易變成:

我做了一個系統,再挑一堆它本來就會的題目測它。

所以 Day 23 我決定先不急著塞新的大功能。

而是反過來做一件比較殘忍的事:

準備一批之前沒有拿來開發的教材,先把預期答案凍結,再讓目前的 Universal Learning World Compiler 去撞牆。

GitHub Repo:
https://github.com/f24131128-lgtm/visual-learning-lab


先把題目和答案鎖起來,再讓系統上場

這次一開始我就特別要求 Codex:

不准先跑系統,再回頭改標準答案。

不然這個 benchmark 就沒什麼意義了。

所以 Day 23 先準備了一批 frozen materials,一共 12 份,涵蓋:

  • 動態方程
  • 向量
  • 電路
  • 函數
  • 集合與機率
  • 程式狀態
  • 遞迴
  • 控制
  • 經濟
  • 生物
  • 定義型知識

其中 3 份根據官方文件的事實重新撰寫,另外 9 份則是原創測試材料。

而且在執行之前就先標記好:

  • 這份教材的知識結構是什麼
  • 哪些 representation 合理
  • 哪些 representation 明顯不適合
  • 是否值得互動
  • 是否有來源 grounding 要保留

也就是先建立 gold,再讓系統跑。

這個步驟我覺得甚至比「測試數量」本身還重要。


Phase A:目前的系統到底有多會選?

第一輪完全使用 Day 22 當時的 architecture。

結果沒有想像中漂亮。

指標 Phase A
Planner 選擇可接受 8
Planner 明顯選錯 1
沒有成功進入 Planner 3
成功編譯成 Learning World 5
本地互動正常 4
Formal ID / page 檢查通過 5
失敗後仍保留正常學習內容 8 / 8
編譯後額外 API 呼叫 0

乍看之下 8 個 Planner 選對好像還可以,但更大的問題其實在後面:

選對 representation,不代表真的編譯得出來。

真正「Planner 選擇合理,而且最後成功變成 runtime artifact」的只有:

4 / 8

這次也讓我第一次很明確地把錯誤拆開。

以前可能只會看到:

Learning World 建立失敗。

但現在可以繼續問:

AI 是不是一開始就看錯教材?

還是:

AI 選對了,但 Compiler 接不住?

還是:

Compiler 接住了,但 Runtime 根本不能照語意執行?

這三種問題其實完全不同。


不再只有「成功 / 失敗」

Day 23 後,我不想再用一個布林值把所有問題混在一起。

所以整條流程開始被拆成:

Representation Selection
↓
Compilation
↓
Runtime Interaction
↓
Grounding
↓
Fallback

例如 Planner 判斷某個教材適合 interactive process。

這個判斷可能是對的。

但如果它產生的 spec 裡有一個 optional 欄位沒有通過 Validator,那其實是 Compiler 的問題,不應該算 Planner 看錯。

反過來,如果一份純定義教材被硬塞進物理模擬,那才是真的 representation selection 失敗。

這個拆法後面幫了非常大的忙。


Phase B:先修共同問題,不准一題一 patch

Phase A 跑完後,我沒有叫 Codex:

把這 12 題全部修到會。

因為這樣最後很容易變成十二個 hard-coded patch。

這次的要求是找「重複出現的系統性問題」。

最後主要找到三個。

第一個是部分 Comparison 物件沒有完整 semantic ID。

第二個則是:

只要有數值參數,就被誤認成一定需要時間動畫。

但「可以調一個值」和「這是一個動態系統」根本是兩件不同的事。

第三個則是某些 representation 根本不使用 process 欄位,但只要那個 process 欄位不符合規則,整份結果還是可能一起被擋掉。

這又回到前幾天 Analogy World 曾經遇到的問題:

Optional 的東西壞掉,不應該殺死正確的核心語意。

所以 Phase B 加入了一個比較小的 capability contract。

不是建立超大 plugin system,而是讓 Planner 在選 representation 的時候知道目前 Runtime 真正支援什麼能力。

例如:

continuous numeric
ordered state
finite transition
spatial dynamics
analogy
static structure

Planner 不應該承諾一個 Runtime 根本做不到的互動形式。

這一輪也重新參考 JSXGraph、XState、Cytoscape 等既有工具,但沒有因為看到新輪子就全部裝進來。

Day 23 Phase B 沒有新增 dependency。


同一批題目,再跑一次

最重要的是:

Phase B 沒有換題目。

還是完全相同的 frozen materials。

結果變成:

指標 Phase A Phase B
Planner 選擇可接受 8 12
成功編譯產物 5 11
本地操作通過 4 11
Formal ID / page 檢查通過 5 12
Safe fallback 8 / 8 1 / 1
編譯後額外 API 呼叫 0 0

如果只看「合理 proposal 最後有沒有真的編譯成功」:

4 / 8 → 11 / 12

這個提升我覺得比再增加兩個漂亮 Demo 有意義很多。

因為這次不是:

又多做了一個 renderer。

而是:

原本已存在的 runtime,開始比較能接住模型產生的語意。

但測到這裡,新的問題又冒出來了。


看起來對,不代表語意真的對

Phase B 之後有幾個 case 讓我發現,目前系統雖然比較會「選」了,但還不能保證:

它真的按照概念本身的規則執行。

第一個是相似 label。

兩個不同概念可能都叫做 Ready。

如果 Runtime 只是拿畫面上的 label 當 identity:

Ready
Ready

那它們很容易被錯當成同一個 entity。

第二個是 Recursion。

畫一張:

S(4)
↓
S(3)
↓
S(2)
↓
S(1)

非常容易。

但這不代表系統真的知道:

  • caller 要等待 child
  • child 完成後才能 return
  • return 必須回到正確 caller
  • 不能提前 return
  • 不能把結果送到錯的 stack frame

第三個則是 Numeric Parameter。

如果教材只說:

amplitude = 4
decay = 0.25

這兩個其實就是固定值。

如果系統硬生一個:

min = max

的 slider,畫面可能還是 render 得出來,但語意其實已經怪掉了。

所以 Day 23 本來差點在這裡收工,最後我決定:

再往下一層挖。


Phase C:Semantic Execution Contract

Phase C 的目標只有一句:

Learning World 不只要「看起來像這個概念」,還要真的 obey 這個概念的規則。

這次開始更明確區分:

Semantic ID
Runtime ID
Display Label
Source Locator

Display Label 只是顯示給人看的。

Identity 不可以靠文字名稱猜。

例如:

Assembly Ready = {p,q}
Inspection Ready = {q,r}

兩個都有 Ready,但它們是兩個不同 semantic entity。

最後真人測試時,點選這兩個項目,Learning Inspector 可以正確切換成不同概念。

所以:

Label 相似,不再代表 Identity 相同。


Recursion 不只是畫 Stack

這是 Phase C 我最喜歡的一部分。

之前 generic Process Runtime 已經可以處理:

  • enqueue
  • dequeue
  • finite-state transition

但 recursion 比較麻煩,因為它真的有 call frame。

所以這次新增的是一個受限的 call / return execution contract。

注意,它不是在執行 AI 生出來的 Python。

也不是把內容丟進 eval() 或 exec()。

它是一個 bounded declarative runtime。

概念大概像:

Caller
↓ Call child
Caller = waiting
Child = active
↓
Child completes
↓ Return
Result → exact caller
↓
Caller resumes

真正負責規則的是可信任的 Runtime。

它自己管理:

  • frame identity
  • stack order
  • caller reference
  • lifecycle
  • legal transition
  • return routing
  • maximum depth
  • bounded history

AI 只描述:

這裡有什麼 call 關係,以及每個步驟的教學意義。


真人測試:真的把 nested_sum 跑完

Phase C 最後有一個 nested_sum 驗收案例。

我實際一路按:

Call child
Call child
Call child
Call child

建立 nested frame。

到了底層之後:

Complete current call

接著逐層:

Return to caller
Complete current call

最後最外層真的得到:

Result = 10

而且完成後,不合法的:

  • Call child
  • Complete current call
  • Return to caller

都會被停用。

Reset 仍然可以回到初始狀態。

這跟前幾天的「畫一個像 recursion 的東西」差很多。

現在比較接近:

模型宣告遞迴語意,Runtime 真正執行 call → wait → complete → return。


不是所有數值都應該有 Slider

另一個我很在意的小地方,是 fixed parameter。

例如來源只有:

amplitude = 4
decay = 0.25

以前很容易因為想讓畫面更「互動」,就替它生出一個滑桿。

但那等於系統自己偷偷創造探索範圍。

所以現在開始更明確區分:

fixed
adjustable
derived

如果來源只給固定值,它就是固定值。

除非明確標記為:

generated pedagogical exploration range

否則不能假裝教材本來提供了一整段可調範圍。

最後 fixed_decay 真人測試中:

amplitude = 4
decay = 0.25

保持固定。

只改 Time 到:

t = 6 seconds

得到:

magnitude ≈ 0.8925
rate ≈ -0.2231

符合預期結果。

而播放、時間軸和數值更新全部都在本地 Runtime 完成。


Phase C 再開一批新的 Holdout

修完之後,也沒有直接拿 regression fixture 自己宣布成功。

Phase C 又建立一批新的 holdout,專門測:

  • 相同 label / 不同 identity
  • nested execution
  • numeric edge case
  • process semantics
  • fallback

最後:

7 / 7 representation 選擇正確

其中:

6 / 7 成功編譯

這 6 個成功編譯的案例也都通過 bounded semantic check。

而且:

postcompile API delta = 0

也就是世界一旦編譯完成,之後的互動還是在本地執行。

Phase C 這一輪用了:

  • 模型請求:16 / 18 次
  • Input tokens:47,888
  • Output tokens:23,481
  • Total:71,369 tokens

我也特別限制 Codex 不准一直用 API 抽卡修 deterministic bug。

Schema、Validator、Reducer、Runtime 的錯誤,應該用 deterministic test 解掉。


最後測試結果

Day 23 Phase C 完成後:

48 個 focused tests 通過

20 個 Phase C tests 通過

最後完整 regression:

388 passed

而且沒有加入:

  • topic-name routing
  • generated Python execution
  • generated JavaScript execution
  • eval
  • exec

這天最重要的改變,其實不是測試數量。

而是問題變了。

一開始我們問的是:

這份教材能不能產生 Learning World?

現在開始問:

這個 Learning World 有沒有真的 obey 這個知識本身的 semantic rules?

這兩個標準差很多。


Day 23 最後留下的架構

今天最後整條路線比較像:

SOURCE
  ↕
FORMAL SEMANTIC ENTITY
  ↕
REPRESENTATION PLAN
  ↕
VALIDATED EXECUTION CONTRACT
  ↕
LEARNING WORLD
  ↕
LOCAL LEARNER ACTION

以前 Visual Learning Lab 比較像:

AI 看懂教材,再生成一張很像的東西。

現在我希望它慢慢變成:

AI 看懂教材並宣告語意,再交給可信任的 Runtime 執行。

因為如果每個 Learning World 都只是漂亮的圖,那這條路很快就會撞牆。

但如果底下開始有:

  • stable semantic identity
  • source grounding
  • legal transitions
  • parameter contract
  • call / return semantics
  • bounded execution
  • local runtime

那新的教材不一定需要新的 App。

它可能只需要:

新的 semantic declaration。

Day 23 沒有做出最炫的新畫面。

但它讓我比較敢相信,前幾天一直講的 Universal Learning World Compiler,開始不只是名字而已。


上一篇
Day 22|我開始做 Universal Learning World Compiler
下一篇
Day 24|不想再拉 Slider 了:我讓使用者直接「抓住」公式本身
系列文
AI Visual Learning Lab: 30 天用 ChatGPT × Codex 打造 AI 視覺化學習工具 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言