昨天把 Learning Card 的 Schema 拆開來看,終於比較清楚 properties、description、required 分別在做什麼。
目前我們已經可以用 Structured Output 定義「一張」Learning Card:
Learning Card
├── emoji
├── title
├── content
├── question
└── answer
但從 Day 05 開始,我原本的需求其實一直都是:
一次產生 5 張學習卡。
所以今天要解決的問題很單純:
一張 Learning Card 是一個 Object,那很多張 Learning Cards 要怎麼表示?
答案就是——Array。
原本一張 Learning Card 的 JSON 大概長這樣:
{
"emoji": "🐢",
"title": "海龜",
"content": "...",
"question": "...",
"answer": "..."
}
如果今天要一次取得多張卡片,就需要一個 Array 來裝這些 Learning Card Object。
最後我採用的資料結構是:
Response Object
│
└── cards: Array
│
├── Learning Card Object
├── Learning Card Object
├── Learning Card Object
├── Learning Card Object
└── Learning Card Object
也就是讓 Response 最外層維持 Object,再新增一個 cards 欄位。
而 cards 本身是一個 Array,裡面的每一筆資料都是一張 Learning Card。
這次的 Schema 就比昨天多了一層:
{
"type": "object",
"properties": {
"cards": {
"type": "array",
"items": {
"type": "object",
"properties": {
"emoji": {
"type": "string",
"description": "與學習主題相關的一個 Emoji"
},
"title": {
"type": "string",
"description": "簡短的學習卡標題"
},
"content": {
"type": "string",
"description": "使用適合學習對象理解的詞彙,只介紹一個主要知識點"
},
"question": {
"type": "string",
"description": "根據 content 提出一個可以直接回答的問題"
},
"answer": {
"type": "string",
"description": "question 的簡短參考答案"
}
},
"required": [
"emoji",
"title",
"content",
"question",
"answer"
],
"propertyOrdering": [
"emoji",
"title",
"content",
"question",
"answer"
]
}
}
},
"required": [
"cards"
],
"propertyOrdering": [
"cards"
]
}
看起來突然變長很多,但其實真正新增的核心只有:
"cards": {
"type": "array",
"items": {
"type": "object"
}
}
這裡我主要理解成:
cards
↓
是一個 Array
items
↓
定義 Array 裡的每一筆資料
每一個 item
↓
都是一個 Learning Card Object
所以昨天定義好的 Learning Card 並沒有消失,只是今天把它放進 Array 裡。


Schema 準備完成之後,Prompt 也可以繼續專注在「我要產生什麼內容」。
這次使用:
請製作一組適合 3~4 歲幼兒學習的「海洋動物學習卡」。
學習目標:
讓孩子認識常見的海洋動物,並了解每種動物一個簡單的特徵。
請產生 5 張學習卡,分別介紹:
海龜、鯨魚、章魚、螃蟹、小丑魚。
內容請使用繁體中文,
並使用適合 3~4 歲幼兒理解的詞彙。
這裡我沒有再告訴 Gemini:
請回傳 JSON
每張要有 emoji
每張要有 title
每張要有 content
...
因為這些已經交給 Schema 處理。
目前兩邊的工作變得更清楚:
Prompt
↓
3~4 歲幼兒
海洋動物
產生 5 張
指定 5 種動物
使用繁體中文
Schema
↓
回傳 cards
cards 是 Array
每個 item 是 Object
每張 Card 有固定的五個欄位
又再次回到前幾天整理出的概念:
Prompt 負責描述學習任務,Schema 負責定義資料結構。

這次執行後,Gemini 回傳:
{
"cards": [
{
"emoji": "🐢",
"title": "認識海龜",
"content": "海龜住在美麗的大海裡。牠的背上背著一個又圓又硬的大殼,就像隨身帶著堅固的小房子一樣喔!",
"question": "海龜背上背著什麼呢?",
"answer": "硬硬的大殼。"
},
{
"emoji": "🐋",
"title": "認識鯨魚",
"content": "鯨魚是世界上體型最大的動物,牠在水面上呼氣的時候,頭頂會噴出高高的水花喔!",
"question": "鯨魚呼氣時,頭頂會噴出什麼呢?",
"answer": "高高的水花。"
},
{
"emoji": "🐙",
"title": "認識章魚",
"content": "章魚的身體軟綿綿的,牠有八隻長長的腳,遇到危險時還會噴出黑黑的墨汁逃跑喔!",
"question": "章魚有幾隻長長的腳呢?",
"answer": "八隻腳。"
},
{
"emoji": "🦀",
"title": "認識螃蟹",
"content": "螃蟹有硬硬的外殼和一對像剪刀的大鉗子,而且牠們走路時都是橫著走的喔!",
"question": "螃蟹走路是向前走還是橫著走呢?",
"answer": "橫著走。"
},
{
"emoji": "🐠",
"title": "認識小丑魚",
"content": "小丑魚身上有漂亮橘色和白色的條紋,最喜歡躲在軟綿綿的海葵家裡面玩捉迷藏喔!",
"question": "小丑魚最喜歡躲在哪裡呢?",
"answer": "軟綿綿的海葵家裡。"
}
]
}

這次終於不是只有一隻海龜了(笑)。
而且從資料結構來看,剛好得到:
cards
├── 🐢 海龜
├── 🐋 鯨魚
├── 🐙 章魚
├── 🦀 螃蟹
└── 🐠 小丑魚
五張卡片都在同一個 cards Array 裡,每一筆也都有:
emoji
title
content
question
answer
這正是我之後希望交給程式使用的資料形式。
做到今天,我覺得 Structured Output 的輪廓又更清楚了一點。
Day 10 解決的是:
怎麼讓 Gemini 不要只回傳一大段文字,而是固定的 JSON?
Day 11 解決的是:
一張 Learning Card 的 Schema 到底要怎麼定義?
今天則是:
怎麼從「一張 Card」擴充成「一組 Cards」?
現在的資料結構也從:
Learning Card Object
變成:
Response Object
└── cards: Learning Card[]
這一步看起來只是多了一個 Array,但對後面的程式來說很重要。
因為之後不需要再從一大段 Response 裡猜:
「第一張卡在哪裡?第二張又從哪裡開始?」
而是可以直接取得 cards,再一張一張處理。
終於不用再跟 split("---") 奮鬥了(笑)。
不過今天也再次提醒自己一件事。
即使 JSON 結構完全符合 Schema:
5 張 Card ✓
固定欄位 ✓
Array 結構 ✓
Question / Answer ✓
也不代表裡面的學習內容就一定完全正確。
例如用詞是否精確、知識點是否適合學習對象,仍然需要 Review。
所以目前整個流程依然是:
Learning Requirement
↓
Gemini
↓
Structured Learning Cards
↓
Draft
↓
Human Review
Structured Output 解決的是:
「資料要怎麼回來?」
而不是:
「AI 說的內容一定是真的嗎?」
後面的文章再來處理這個問題。
今天終於從一張 Learning Card,前進到一次產生一組 Learning Cards。
目前的資料結構已經變成:
Response
│
└── cards[]
│
├── emoji
├── title
├── content
├── question
└── answer
Gemini 也成功按照這個結構,一次回傳海龜、鯨魚、章魚、螃蟹和小丑魚五張學習卡。
從 Day 09 還在想辦法解析文字,到現在終於有一份相對穩定、程式比較容易使用的資料格式了。
不過 JSON 有了,下一個問題也跟著出現:
Gemini 知道 Learning Card 長什麼樣子了,但我的程式知道嗎?
身為一個平常寫 TypeScript 的前端工程師,看到這份 JSON,手已經有點想開始幫它加型別了(笑)。
明天終於輪到 TypeScript 上場。
Day 13|JSON 有了,TypeScript 呢?建立 LearningCard 型別