iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
ChatGPT & Codex

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

Day 16|昨天讓公式可以玩,今天我讓「時間」真的開始流動

  • 分享至 

  • xImage
  •  

Day 15 做完 Interactive Learning Lab 之後,我第一次覺得 Visual Learning Lab 不只是「解釋教材」。

像正弦波 v(t)=V_m cos(ωt+θ),AI 不只會告訴我 V_m 是振幅、ω 是角頻率、θ 是相位,而是會直接替這份教材生成 slider、即時曲線和衍生數值。改變參數之後,圖形在本機重新計算,不需要一直呼叫 OpenAI API。

後來我又拿阻尼振動、拋體運動、Logistic Growth 去測,確認它不是只會做正弦波。

但 Day 15 做完之後,我馬上又開始嫌棄自己的功能。

因為有些東西雖然可以「拉參數看圖」,但它本質上其實是一個會隨時間變化的系統。

拋體不是一條拋物線而已。

它應該真的從地面飛出去、上升、到最高點,再掉回來。

阻尼振動也不是一張 x(t) 曲線而已。

它應該真的震,而且每一次震盪的幅度都比前一次小。

所以 Day 16 我決定把昨天的 Interactive Lab 再往前推一步。

這次的目標叫做:

Dynamic Simulation Studio。

從「改參數」變成「看系統真的動起來」

昨天的 Interactive Lab 大概是:

教材中的數學模型
↓
AI 產生安全的實驗規格
↓
Slider
↓
重新計算
↓
即時圖形

Day 16 則在這條線上再多一層:

Interactive Lab
↓
建立動態模擬
↓
AI 產生 declarative simulation spec
↓
本機產生所有時間 frame
↓
Play / Pause / Replay
↓
時間軸可以拖動

這裡我還是維持 Day 15 的原則:

AI 不可以產生一段 Python 然後直接執行。

它只能描述這個模擬應該有哪些物件、這些物件的位置怎麼由公式計算、時間範圍是多少,以及哪些數值值得顯示。

真正的數學運算還是走昨天做好的 restricted expression evaluator。

也就是說,AI 負責「描述模擬」,程式負責「安全地算出模擬」。

動畫不是每一幀都去問 AI

這次我最不想做出的東西,就是一個「看起來會動,但其實一直在燒 API」的動畫。

所以建立 Dynamic Simulation 時,可以有一次額外的 API request,讓模型根據目前教材和 Interactive Lab 產生 simulation specification。

但是一旦 spec 建好之後,Play、Pause、Replay、拖時間軸、改播放速度,以及每一幀的位置計算,全部都在本機完成。

目前大概是這樣:

操作 OpenAI API
第一次分析教材 是
建立 Interactive Lab 跟主分析一起
建立 Dynamic Simulation 是,使用者主動觸發
Play / Pause 否
Replay 否
拖時間軸 否
改播放速度 否
改參數後重新計算動畫 否

這一點對我來說滿重要。

因為如果播放一段 120 frame 的動畫,就送 120 次 request,那這功能基本上不能用。

現在 AI 只負責「把規則建立起來」,後面時間怎麼跑,是程式自己的事情。

第一個測試:讓正弦波真的沿時間前進

第一個還是先拿最熟悉的 Sinusoids 測。

這次建立的動態模擬會沿著時間軸計算目前的 v(t),畫面上可以看到目前位置、已經走過的軌跡,以及完整路徑。

https://ithelp.ithome.com.tw/upload/images/20260929/20184158FdauV0dZae.png
上面還會同步顯示像目前電壓、目前相位角、週期 T=2π/ω 這些 frame-specific metrics。

比較有感的是時間軸。

以前我如果想知道「現在走到哪個 phase」,其實只能自己看公式。

現在直接拖 timeline,就可以跳到某個時間點,看當下波形的位置。

播放之後,也不是 Streamlit 每一幀重新 rerun 整個 app,而是把 frame data 先準備好,再交給 Plotly 在瀏覽器端播放。

這樣至少不會發生:

播一下 → 整頁閃一下 → 再播一下 → 整頁再閃一下

這種很可怕的動畫。

阻尼振動這次真的開始有「時間感」

接著我拿昨天已經測成功的阻尼振動:

x(t)=Ae^{-bt}cos(ωt+φ)

這一題其實是我 Day 16 最想看的。

因為 Day 15 已經可以畫出它的曲線,但「振幅逐漸衰減」這件事,本來就很適合用時間看。

https://ithelp.ithome.com.tw/upload/images/20260929/20184158tuAASCu7wH.png
這次畫面上會看到現在的位置沿著 x(t) 前進,而上下兩條 envelope 也會一起顯示出 Ae^{-bt} 的衰減範圍。

所以一眼就可以看出:

一開始振幅很大,之後逐漸縮小,最後靠近 0。

而且這個畫面還是跟 Day 15 的參數 state 接在一起。

例如把阻尼係數 b 拉大之後,不需要重新叫 AI 建一個模擬。

程式直接用同一份 simulation spec 和新的 b 值,把 frame 重新算一次。

我實際測試時,b 拉大之後振動真的會更快衰減;改 ω 則會改變震盪速度。

這就開始有一點「模擬器」的感覺了。

不是 AI 告訴我:

阻尼係數越大,振幅衰減越快。

而是我真的可以把它拉大,看它更快停下來。

拋體運動終於不是只有一條拋物線

接著是我覺得這次最適合 Demo 的拋體運動。

Day 15 已經可以根據:

y(x)=x tanθ - gx²/(2v₀² cos²θ)

自動做出 v₀、θ、g 三個 slider,再畫出一條 trajectory。

但那時候它還是一張圖。

Day 16 之後,模型可以把同一個物理關係轉成時間形式:

x(t)=v₀ cosθ · t

y(t)=v₀ sinθ · t - 1/2 gt²

然後真的讓一個點沿著軌跡移動。

https://ithelp.ithome.com.tw/upload/images/20260929/20184158fpBhm3btSs.png
畫面上可以同時看到完整的理論軌跡、目前已經走過的位置,以及移動中的 projectile。

上方還有目前水平位置、目前高度、理論飛行時間、理論最大高度。

這次我甚至把播放速度切到 2× 測試。

Play、Pause、Replay、時間軸都正常。

最重要的是,我再回去改 v₀ 或 θ,整條軌跡和動畫也會跟著重新計算,而且沒有再次出現 AI spinner。

這就證明參數修改真的留在本地。

我開始覺得「動畫」不應該只是裝飾

一開始想到 Day 16 時,其實很容易掉進一個坑:

我要做動畫,因為動畫很炫。

但真的做完幾個例子之後,我覺得比較合理的標準應該是:

這個概念如果動起來,會不會更容易理解?

阻尼振動會。

拋體運動會。

相位隨時間前進也會。

但不是每一個公式都需要硬做成動畫。

例如我後來又拿 Laplace Transform 的常數函數 F(s)=c/s 去跑。

系統可以做 Interactive Lab,讓我改變 c,觀察 F(s) 的形狀如何改變。

https://ithelp.ithome.com.tw/upload/images/20260929/20184158c70SPtW18n.png
但這種內容如果硬要做成「一個點在 c/s 曲線上跑來跑去」,學習價值其實沒有比較高。

所以我反而希望未來系統更敢回答:

這個內容適合互動圖,但不需要動畫。

而不是看到 formula 就一定要放一個 Play 按鈕。

這也是我現在越來越在意的事情:

Visual Learning Lab 不應該追求「每份教材都生成最多功能」。

而是要選擇:

哪一種呈現方式最適合這份內容。

Day 15 的安全運算引擎這次直接被重用了

Day 16 有一個地方我滿慶幸昨天有先做好,就是 safe expression evaluator。

如果 Day 15 是直接用 eval() 執行 AI 回傳的數學式,今天要開始生成動態 scene,風險只會變得更大。

現在 simulation 裡面的物件只能使用有限的 primitive,例如 moving point、vector、line、trajectory 等,再搭配經過白名單驗證的 mathematical expression。

模型不能突然回傳:

open(...)

或 __import__(...)

然後期待程式去執行。

它能做的事情被限制在:

用已經宣告的參數和時間變數,計算這個物件現在應該在哪裡。

我覺得這個架構慢慢變得滿有意思。

現在 AI 其實不是在「寫程式」。

它更像是在寫一份很受限制的 learning scene description。

而 Visual Learning Lab 是負責解讀這份描述的 runtime。

Slider、動畫、學習流程開始用同一份 state

Day 16 另一個比較工程面的重點,是我不希望 Day 15 Interactive Lab 和 Day 16 Simulation 各自有一組完全獨立的參數。

假設 Interactive Lab 裡現在是:

A=1

b=0.25

ω=3.4

φ=-1.44

那打開阻尼振動動畫時,就應該用同一組數字。

不應該進到動畫後,又突然變回另一套 default。

所以兩邊現在盡量共用同一份 parameter state。

這個改動看起來不像新功能,但實際使用差很多。

因為「Interactive Lab」和「Dynamic Simulation」開始不像兩個工具,而比較像同一份模型的兩種觀察方式:

一個適合看整體曲線。

一個適合看時間如何推進。

這次真正讓我有感的是「公式裡的 t 開始有意義」

做到 Day 15 時,t 對系統來說其實只是 x 軸。

Day 16 做完之後,t 第一次真的變成「時間」。

現在可以按 Play。

可以 Pause。

可以把時間拉回去。

可以看某一刻的位置。

可以把播放速度改成 2×。

也可以觀察同一組參數在不同時間到底發生什麼。

所以如果要用一句話講 Day 15 和 Day 16 的差別,我會寫:

Day 15 讓我改變模型。

Day 16 讓我看著模型活起來。

Day 16:從互動圖走向真正的 simulation

現在 Visual Learning Lab 對數學教材的處理大概已經變成:

看到公式
↓
理解參數與關係
↓
產生 Interactive Lab
↓
安全地操作參數
↓
如果時間演化有學習價值
↓
產生 Dynamic Simulation
↓
本機播放、暫停、拖曳、重新計算

我滿喜歡這條線的一個原因是:

AI 最重要的工作其實停在前面。

它負責理解教材、判斷什麼值得呈現、建立安全的結構。

真正開始操作之後,使用者不用一直跟模型來回對話。

拉 slider 不需要問 AI。

播放動畫不需要問 AI。

時間往前走也不需要問 AI。

這些互動都只是數學模型自己在運作。

做到 Day 16,我覺得 Visual Learning Lab 已經越來越不像「把 GPT 包在 Streamlit 裡」。

它現在開始有自己的 runtime、自己的資料結構、自己的學習流程,也開始能把 AI 的理解轉換成真正可以操作的東西。

昨天我寫:

AI 開始替教材做工具。

今天可以再往前一句:

它開始替教材做模擬器。

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


上一篇
Day 15|AI 看懂公式還不夠:我讓它直接生出「可以玩的實驗」
下一篇
Day 17|讓教材變成會互相連動的學習場景
系列文
AI Visual Learning Lab: 30 天用 ChatGPT × Codex 打造 AI 視覺化學習工具 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言