# 第 2 階段：下載文字模型，跑出第一句回答

> 這是「AI Agent 實戰工作坊」的階段頁，給 AI Agent 讀的版本。給人看的頁面在 https://class.madebypan.com/stage/2
> 你是學員電腦上的 AI Agent。先看學員要你做什麼：要你「照這個網址把這個階段做好」→ 走 A；說卡住了 → 走 B。

## A. 學員要你「照這個網址把◯◯做好」：先裝成 Skill

不要在這個對話裡直接做這個階段的步驟。先照下面把這個階段裝成 Skill，再請學員開新對話跑它。（你如果已經是在跑裝好的 `ai-class-stage-2` skill，跳過這段，不用重裝。）

1. **課程資料夾**：桌面上的 `AI課程` 資料夾（macOS 是 `~/Desktop/AI課程`；Windows 是桌面的 `AI課程`，桌面被 OneDrive 接管時以 PowerShell `[Environment]::GetFolderPath('Desktop')` 查到的位置為準）。沒有就建立。學員之後都在這個資料夾開 Agent。
2. **要下載的檔只有一個**：`https://class.madebypan.com/stage/2/SKILL.md`。把同一份存到下面三個位置，三個都放，不用判斷你自己是哪一家：

   | macOS／Linux | Windows | 誰會讀 |
   | --- | --- | --- |
   | `~/Desktop/AI課程/.agents/skills/ai-class-stage-2/SKILL.md` | `桌面\AI課程\.agents\skills\ai-class-stage-2\SKILL.md` | Codex、Gemini CLI、Antigravity |
   | `~/Desktop/AI課程/.claude/skills/ai-class-stage-2/SKILL.md` | `桌面\AI課程\.claude\skills\ai-class-stage-2\SKILL.md` | Claude Code |
   | `~/.codex/skills/ai-class-stage-2/SKILL.md` | `%USERPROFILE%\.codex\skills\ai-class-stage-2\SKILL.md` | Codex |

   用下面這行就能一次放好（只下載檔案，不執行任何下載來的東西）。要寫入家目錄的 `.codex` 資料夾，先跟學員說一聲：

   - macOS／Linux（終端機）：
     ```
     D="$HOME/Desktop/AI課程"; for p in "$D/.agents/skills" "$D/.claude/skills" "$HOME/.codex/skills"; do mkdir -p "$p/ai-class-stage-2" && curl -fsSL https://class.madebypan.com/stage/2/SKILL.md -o "$p/ai-class-stage-2/SKILL.md"; done; ls "$D/.agents/skills" "$D/.claude/skills" "$HOME/.codex/skills" | grep ai-class-stage-2
     ```
   - Windows（PowerShell）：
     ```
     $D = Join-Path ([Environment]::GetFolderPath('Desktop')) 'AI課程'; foreach ($p in "$D\.agents\skills", "$D\.claude\skills", "$HOME\.codex\skills") { New-Item -ItemType Directory -Force "$p\ai-class-stage-2" | Out-Null; curl.exe -fsSL https://class.madebypan.com/stage/2/SKILL.md -o "$p\ai-class-stage-2\SKILL.md" }
     ```
3. **確認**：三個檔都在，第一行是 `---`、第二行是 `name: ai-class-stage-2`。
4. **跟學員說**：「裝好了。請在桌面的 AI課程 資料夾開一個新的對話，說『跑第 2 階段』。」再附上他用的那一家的叫法（不知道他用哪一家就四句都給）：
   - Claude Code：在 AI課程 資料夾開 Claude Code，打 /ai-class-stage-2，或直接說「跑第 2 階段」。
   - Codex：在 AI課程 資料夾開 Codex，打 $ai-class-stage-2（或輸入 /skills 從清單選），或直接說「跑第 2 階段」。
   - Gemini CLI：在 AI課程 資料夾開 gemini，第一次問要不要信任這個資料夾時選信任，再說「跑第 2 階段」；它要啟用 skill 時會問你，選同意。
   - Antigravity：用 Antigravity 打開 AI課程 資料夾（終端機版就是在這個資料夾跑 agy），打 /ai-class-stage-2，或直接說「跑第 2 階段」。

## B. 學員說卡住了：在學員電腦上排查

1. 先問學員卡在第幾步、畫面上看到什麼；錯誤訊息請學員整段貼給你。
2. 照下面的「步驟」和「卡住時先查」，在學員電腦上查。只看不改的指令（看版本、看空間、看檔案在不在）可以直接跑；會改東西的指令（安裝、下載、改檔案）先跟學員說要做什麼，學員同意才做。
3. 這些事不要做，遇到了就送單給講師：刪除檔案、用 sudo 或管理員密碼、改系統設定、關掉防毒或防火牆。
4. 解得了，就帶學員一路做到「檢查點」，確認過關。
5. 解不了，照最後一段「送單給講師」。

---

> 這堂課以 Mac 為主。這頁的 macOS 指令都在講師的 Mac（M1 Max、32GB）實測過；Windows 的指令沒有實測，用 Windows 的學員照做卡住就送單給講師。文字模型在課前準備就下載好了，`ollama list` 看得到 `gemma4:12b` 的話，第 1、2 步直接跳過。

## 做完會怎樣

你的電腦上有一個不用連網也能回答問題的文字模型，你問它一句，它用繁體中文回你，用完再把它從記憶體關掉。

## 資源

- 執行工具：Ollama。Mac 和 Windows 用同一套指令（Mac 上它走 Apple 的 MLX，Windows 上走 llama.cpp）。
- 預設模型：Gemma 4 12B（`gemma4:12b`，7.7 GB）。講師實測時它判斷人名和負責人比較穩，也不會自己編星期幾。
- 備案：Qwen3.5 9B（`qwen3.5:9b`，7.6 GB），快 30% 到 50%，但實測時會自己編星期、會把人判錯。
- 記憶體不到 16GB：改用小模型 `qwen3.5:4b`（沒實測）。

## 步驟

### 1. 裝 Ollama

- macOS：`brew install ollama`，裝完讓它在背景跑：`brew services start ollama`（之後想關掉：`brew services stop ollama`）。
- Windows（未實測）：`winget install --id Ollama.Ollama -e`。
- 檢查點：`ollama --version` 印出版本號（講師的 Mac 是 0.40.6）。

### 2. 下載模型

- 做什麼：`ollama pull gemma4:12b`
- 你會看到：下載進度，大約 7.7 GB，跑完出現 `success`。
- 如果看到 403、連線逾時或卡在 0%：可能是公司網路擋了，改用手機熱點再跑一次。
- 如果看到「No space left on device」：硬碟不夠，請學員自己清出空間；Agent 不替學員刪檔。
- 檢查點：`ollama list` 看得到 `gemma4:12b`。

### 3. 問它一句

- 做什麼：`ollama run gemma4:12b --think=false "請用繁體中文、一句話介紹你自己。"`
- 你會看到：一句繁體中文，例如「我是由 Google DeepMind 開發的開放權重大型語言模型，名為 Gemma 4。」（講師的 Mac 跑了 7.5 秒）
- 一定要加 `--think=false` 關掉思考：開著思考，模型會先寫一大段思考內容，實測時 Qwen 多花了三分多鐘，Gemma 有一次跑了 19 分鐘還沒停。
- 給模型的指令用繁體中文寫：實測時用英文下指令、又沒給固定的系統提示，兩個模型都整段回簡體。
- 檢查點：看到通順的繁體中文回答就過關。

### 4. 用完把模型關掉

- 做什麼：`ollama stop gemma4:12b`
- 為什麼：Ollama 會把模型留在記憶體 5 分鐘，大約佔 8 GB；接著要生圖的話，16GB 的電腦會不夠。
- 檢查點：`ollama ps` 看不到 `gemma4:12b`。

## 卡住時先查

- Ollama 有沒有在跑：`ollama --version`、`ollama ps`；macOS 沒在背景跑的話 `brew services list | grep ollama`
- 模型下載了沒、多大：`ollama list`
- 記憶體：macOS `sysctl -n hw.memsize`；Windows `Get-CimInstance Win32_ComputerSystem | Select-Object TotalPhysicalMemory`
- 硬碟剩多少：macOS `df -h ~`；Windows `Get-PSDrive C`
- 網路通不通：`curl -sI https://ollama.com`（看第一行是不是 200）
- 錯誤紀錄：錯誤就在終端機輸出裡；把最後 30 行原文整段放進單裡。

---

## 送單給講師

照上面查過還是解不了，才走這段。

### 1. 先整理這張單，整份給學員看

把下面這些內容整理成 JSON，**把要送出的那份 JSON 原文整份貼給學員看（不是摘要），問他「要送出嗎？」，學員說好才送**。學員同意之後內容不要再改；要改，就把改好的整份重新給學員看、重新問一次。不要放密碼、金鑰、token 或個人檔案的內容；路徑裡的使用者名稱可以換成 `~`。

```json
{
  "class_code": "當堂碼：講師在台上公布（課前會寫在通知信裡），問學員",
  "name": "學員的名字（講師要過去找他時用），問學員",
  "stage": 2,
  "step": "卡在第幾步，例如 2",
  "did": "學員做了什麼，照順序寫",
  "saw": "看到什麼：錯誤訊息原文，整段照貼，不要改寫或摘要",
  "tried": "你和學員已經試過什麼、各自的結果",
  "system": "你在學員電腦上查到的：作業系統和版本、晶片、記憶體、硬碟剩多少、相關工具的版本、錯誤紀錄的重點",
  "agent": "claude-code、codex、gemini-cli 或 other"
}
```

### 2. 送出

把 JSON 存成檔案 `ticket.json`，然後送出：

- macOS／Linux：`curl -sS -X POST https://class.madebypan.com/api/tickets -H "Content-Type: application/json" --data-binary @ticket.json`
- Windows PowerShell（要打 `curl.exe`，不是 `curl`）：`curl.exe -sS -X POST https://class.madebypan.com/api/tickets -H "Content-Type: application/json" --data-binary "@ticket.json"`

回應是 JSON，裡面有 `id`、`poll_url`、`ticket_url`、`resolve_url`、`escalate_url`、`followup_url`。把單號和 `ticket_url` 告訴學員，學員可以用這個網址看進度、自己按「還是不行」。

- 回 403：當堂碼不對，再問學員一次。
- 回 429：送太快了，等回應裡 `retry_after` 的秒數再送。

### 3. 等講師的 AI 回覆

每 20 秒查一次：`curl -sS "<poll_url>"`，最多等 10 分鐘。看回應的 `status`：

- `waiting`：還在看，繼續等。
- `answered`：`reply.steps` 是建議的步驟。**先把步驟原文給學員看，學員同意才照做。** 步驟裡如果要刪檔、輸入管理員密碼、改系統設定或關防毒，不要做，直接到第 4 步轉給講師。
  - `reply.kind` 是 `need_info`：講師的 AI 要你補查一些東西。學員同意後查完，把結果寫成 `{"text": "查到的結果"}` 存成 `followup.json`，再送：`curl -sS -X POST "<followup_url>" -H "Content-Type: application/json" --data-binary @followup.json`，然後回到第 3 步等。
- `need_instructor`：跟學員說講師會過去找他，不用再查。
- `resolved`：結束。

### 4. 照做之後

- 解決了：`curl -sS -X POST "<resolve_url>"`，跟學員說完成。
- 還是不行：問學員要不要轉給講師，學員同意就把 `{"note": "照做了哪幾步、現在看到什麼"}` 存成 `note.json`，送 `curl -sS -X POST "<escalate_url>" -H "Content-Type: application/json" --data-binary @note.json`。學員也可以打開 `ticket_url` 自己按「還是不行」。這張單會變成講師巡場的待辦，講師會過去找他。
