iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
Build on Google AI

今天學什麼?30 天用 Google AI 打造智慧學習卡系列 第 17 篇

Day 17|不想每次都改 Prompt:做一個 Learning Card 產生表單

  • 分享至 

  • xImage
  •  

昨天終於把 Day 12 透過 Structured Output 產生的五張海洋動物學習卡,成功放進 React UI。

現在資料是真的了,畫面也可以正常顯示。

不過馬上又遇到下一個問題。

目前想換學習內容,還是得自己去修改程式。

假設今天不想學海洋動物,而是想改成:

7~8 歲兒童
浩瀚太空
3 張學習卡

難道每次都要重新修改 learningCards.ts 嗎?

這樣好像還不能算是一個真正的「智慧學習卡產生器」。

所以今天先不急著串 Gemini API,而是先解決前端的第一個問題:

讓使用者自己告訴 App:「今天想學什麼?」


先決定使用者可以設定什麼

回頭看前面幾天使用的 Prompt,其實一直都有幾個重要條件:

學習對象:3~4 歲幼兒
學習主題:海洋動物
卡片數量:5 張

以前這些條件都是直接寫在 Prompt 裡。

既然現在要慢慢把它做成 Web App,那第一步就是把這些條件搬到畫面上。

這次我先留下三個最基本的設定:

學習對象
學習主題
卡片數量

預期最後可以得到類似:

{
  "ageGroup": "3~4 歲幼兒",
  "topic": "海洋動物",
  "cardCount": 5
}

不過今天先做到這裡就好。

先不串 Gemini API。

按下「產生學習卡」後,只要能把這三個值正確取得並輸出到 Console,就算成功。


這次除了「要做什麼」,也告訴 Gemini「不要做什麼」

經過 Day 15 和 Day 16,我已經稍微認識 Gemini 的熱心程度了(笑)。

Day 15 原本只是希望它建立 Learning Card UI,結果 Make this an app 不只建立了完整 Prototype,還自己加入:

語音朗讀
星星獎勵
挑戰模式
多種學習主題
parentTip
soundName
pinyin

甚至連原本的 LearningCard Data Contract 都一起擴充了。

所以這次除了描述功能,我也特別限制修改範圍。

我給 Gemini 的 Prompt 是:

目前 Learning Card App 已經可以顯示學習卡。

其中海洋動物的 oceanCards 已經替換成前面透過 Structured Output 產生的 5 張 Learning Card,請保留目前既有的資料與功能,不要修改 oceanCards。

現在我希望新增一個「產生學習卡」表單,讓使用者可以設定學習條件。

表單需要包含:

1. 學習對象
   - 3~4 歲幼兒
   - 5~6 歲幼兒
   - 7~8 歲兒童

2. 學習主題
   - 使用文字輸入
   - 預設值為「海洋動物」

3. 卡片數量
   - 可以選擇 3、5、7 張
   - 預設為 5 張

4. 一個「產生學習卡」按鈕

這一版先不要串接 Gemini API。

按下「產生學習卡」後,只需要使用 console.log 輸出:

{
  ageGroup,
  topic,
  cardCount
}

請保留目前 Learning Card App 原本的功能。

不要修改:
- oceanCards
- LearningCard 資料結構
- 其他既有學習卡資料
- 現有學習卡功能

只新增這次需要的表單功能。

跟之前相比,這次 Prompt 不只是 Requirement,也開始加入 Scope。

簡單來說就是:

告訴 AI 要做什麼,也告訴它這次先不要做什麼。


Gemini 花了 80 秒,修改兩個檔案

這次使用 Gemini 3.8 Flash 執行,大約花了 80 秒。

Action history 顯示只修改了兩個檔案:

src/components/CardGeneratorForm.tsx
src/LearningCardApp.tsx

其中新增的:

CardGeneratorForm.tsx

就是今天主要的表單 Component。

比較重要的是,這次 Gemini 有遵守前面設定的範圍:

oceanCards              沒有修改
LearningCard Type       沒有修改
其他學習卡資料           沒有修改
Gemini API              沒有串接
既有 Learning Card 功能  保留

至少這次沒有又突然多出一個新的 Data Contract。

Day17 prompt add new Card Generator Form


表單比我要求的還完整一點

雖然 Gemini 這次有守住功能範圍,但在 UI 上還是忍不住多做了一點。

原本我只要求「學習對象」可以選擇三種年齡,它最後做成了三個選項:

🐣 3~4 歲幼兒
🐥 5~6 歲幼兒
🦅 7~8 歲兒童

「學習主題」除了文字輸入框之外,還自己增加了快速選擇:

海洋動物
森林恐龍
交通工具
美味水果
浩瀚太空
日常好習慣

卡片數量則做成:

3 張        5 張        7 張
輕巧探索    標準推薦     深度體驗

也就是說,Gemini 有遵守「不要串 API、不要改資料」這些功能邊界,但 UI 要怎麼呈現,它還是做了自己的設計決策。

這跟 Day 15 的結果有點像,只是這次 Scope 已經收斂很多。

Day17 Final result


表單資料先用 React State 接住

回到程式本身,今天真正需要的事情其實不複雜。

表單需要記住三個值:

ageGroup
topic
cardCount

也就是:

使用者選了誰要學?
使用者今天想學什麼?
使用者想產生幾張?

當使用者修改表單時,React State 會跟著更新。

最後按下「產生學習卡」,再把目前的資料整理成:

const outputData = {
  ageGroup,
  topic: topic.trim() || '海洋動物',
  cardCount,
};

目前還沒有 API,所以接下來只做:

console.log(outputData);

整個流程其實就是:

Form
 ↓
React State
 ↓
handleSubmit()
 ↓
outputData
 ↓
console.log()

今天的目標不是產生卡片,而是先確認 App 能不能正確知道使用者的需求。


實際換一組條件測試

只測預設值還不太夠。

如果畫面預設就是:

3~4 歲幼兒
海洋動物
5 張

最後 Console 也印出相同內容,還不能完全確認表單互動是不是正常。

所以這次我刻意把三個條件都換掉。

1. 學習對象

改成:

7~8 歲兒童

2. 學習主題

改成:

浩瀚太空

3. 卡片數量

改成:

3 張

最後按下:

✨ 產生學習卡

Console 成功得到:

{
  "ageGroup": "7~8 歲兒童",
  "topic": "浩瀚太空",
  "cardCount": 3
}

三個值都和畫面上的選擇一致。

Day17 form output data console

也就是說,目前的資料流程已經可以做到:

使用者操作 Form
        ↓
React State 更新
        ↓
按下「產生學習卡」
        ↓
取得目前設定
        ↓
{
  ageGroup: "7~8 歲兒童",
  topic: "浩瀚太空",
  cardCount: 3
}

到這裡,Day 17 的目標就完成了。


不過現在還沒有真的產生學習卡

這裡要特別說明一下。

雖然按鈕上已經很有氣勢地寫著:

✨ 產生學習卡

但它現在其實還不會產生任何新的 Learning Card。

因為今天刻意沒有串 Gemini API。

目前按下按鈕後,資料只走到:

console.log(outputData);

所以即使我選:

7~8 歲兒童
浩瀚太空
3 張

App 也不會突然生成三張太空學習卡。

這一版真正完成的是:

把使用者的學習需求,從 UI 轉換成程式可以使用的資料。

而這三個值,正好就是接下來要交給 Gemini 的原料。


Prompt 不只是需求,也可以控制修改範圍

今天除了完成 Form,我覺得另一個比較有意思的地方,是跟 Gemini 協作方式的改變。

Day 15 比較像:

我要 Learning Card UI
↓
Gemini 自由發揮
↓
得到一個比預期大很多的 Prototype

Day 17 則變成:

我要新增 Form

要做:
ageGroup
topic
cardCount
console.log

不要做:
Gemini API
修改 oceanCards
修改 LearningCard
修改其他既有功能

最後 Gemini 雖然還是在 UI 上加入快速選項、成功提示等自己的設計,但至少沒有再次修改核心資料結構,也沒有提前把下一天的 Gemini API 一起做掉。

對我來說,這也是使用 AI 寫程式時開始慢慢學到的一件事:

Prompt 不只是描述想要什麼,也可以拿來界定這一次工作的邊界。

尤其當專案開始有既有程式碼之後,「哪些東西不要動」有時候跟「要新增什麼」一樣重要。


今天的小結

昨天我們把真正的 Learning Card Data 接進 React。

今天則往前走了一步,把原本寫死在 Prompt 裡的:

學習對象
學習主題
卡片數量

搬到 UI 上。

現在使用者已經可以自己決定:

「今天想學什麼?」

而 React 也可以取得:

{
  "ageGroup": "7~8 歲兒童",
  "topic": "浩瀚太空",
  "cardCount": 3
}

如果把目前進度接起來,大概變成:

使用者
  ↓
Learning Card Form
  ↓
ageGroup
topic
cardCount
  ↓
console.log()

不過問題也很明顯。

資料都準備好了,結果最後只是印在 Console。

那接下來呢?

當然就是把它真的送出去。


明天預告

Day 18|按下產生之後呢?從 React 呼叫 Gemini API

明天準備把今天取得的:

ageGroup
topic
cardCount

真正交給 Gemini。

讓目前的:

React Form
    ↓
console.log()

開始變成:

React Form
    ↓
使用者學習條件
    ↓
Gemini API
    ↓
Learning Card Response

前面十幾天一直都在 Google AI Studio 裡手動按 Run。

接下來,終於要讓自己的 React App 開始跟 Gemini 說話了。


上一篇
Day 16|UI 有了,但資料還是假的:把 Learning Card JSON 接進 React
系列文
今天學什麼?30 天用 Google AI 打造智慧學習卡 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言