本文作者是 AI 工程的初學者,正透過《AI Engineering from Scratch》課程自學,並全程搭配 AI 輔助:一步步照著課程開發者的進度動手執行,卡關時就向 AI 提問、請它引導。這篇文章,是把作者與 AI 互動的完整過程與學習歷程,先交由 AI 記錄、統整成初稿,再由作者親自逐段審視、修改、優化而成。AI 負責整理,最終判斷與文字由作者把關。
寫下它有兩個用意:替後來的讀者鋪一條能照著走的路徑,也幫作者自己複習、把學過的東西沉澱下來。
這篇怎麼讀
這篇跟系列其他文章一樣有三層:
- 作者說了什麼:課程的原始指令、步驟、練習
- 我問 AI 之後理解的背後道理:白話概念、類比、跟前面學過的東西怎麼接
- 走到這裡才會知道的事:課程沒明說但實際會遇到的補充
每一個指令,都要問到懂為止,才往下走。
這一課導覽框
- 課名:Phase 0 - Lesson 8 — Editor Setup
- 類型:Build(動手做的課)
- 目標:把編輯器從「打字的地方」調成「幫你抓錯、自動排版、能連遠端 GPU 的工作台」
- 時間:課程標約 20 分鐘,我邊裝邊排錯大概花了 40 分鐘
- Cursor 使用者:課程用 VS Code 示範,但 Cursor 是 VS Code 的 fork,擴充套件和設定格式相容。這篇會標出 Cursor 跟 VS Code 不一樣的地方
- 完課驗證:擴充套件全裝好 + settings.json 設好 + Black format on save 生效 + 型別檢查有波浪線
這一課要解決的問題
課程開頭的說法:
You’ll spend thousands of hours inside your editor writing Python, running notebooks, debugging training loops, and SSH-ing into GPU boxes. A misconfigured editor turns every session into friction.
你會在編輯器裡花上幾千個小時寫 Python、跑 notebook、debug 訓練迴圈、SSH 進 GPU 機器。一個沒調好的編輯器,讓每次工作都多一層阻力。
編輯器調好要 20 分鐘。不調的話,每天多浪費 20 分鐘。
先看懂作者的地圖
課程把編輯器的設定想成五層,由下往上疊:
底層裝好,上面才有東西掛。第一層是編輯器本體,最上面是遠端開發。
步驟 1:安裝編輯器
課程推薦 VS Code,免費、跨平台、Jupyter 原生支援、擴充套件生態系大。我用的是 Cursor,它是 VS Code 的 fork,內建 AI 程式碼輔助。擴充套件和 settings.json 格式跟 VS Code 完全一樣,課程教的東西直接通用。
驗證安裝(在終端機跑):
# VS Code 用這個
code --version
# Cursor 用這個
cursor --version
如果 code 或 cursor 指令找不到(Mac 上常見),打開編輯器 → Cmd+Shift+P → 搜尋 “Shell Command” → 選「Install ‘code’/‘cursor’ command in PATH」。
步驟 2:裝擴充套件
課程列了八個 AI 工程必要的擴充套件:
cursor --install-extension ms-python.python
cursor --install-extension ms-python.vscode-pylance
cursor --install-extension ms-toolsai.jupyter
cursor --install-extension eamodio.gitlens
cursor --install-extension ms-vscode-remote.remote-ssh
cursor --install-extension ms-python.debugpy
cursor --install-extension ms-python.black-formatter
cursor --install-extension charliermarsh.ruff
VS Code 使用者把 cursor 換成 code 就好。
這是全域安裝——裝一次,開任何專案都能用。跟前面學的 uv pip install(裝進特定 .venv)不同,擴充套件是裝進編輯器本體的。
每個擴充套件在做什麼:
| 擴充套件 | 做什麼 |
|---|---|
| Python | 讓編輯器認識 Python,偵測虛擬環境、跑程式、debug |
| Pylance | 自動補全、型別提示、抓 import 錯誤 |
| Jupyter | 在編輯器裡直接跑 notebook,不用另開瀏覽器 |
| GitLens | 看每一行是誰改的、什麼時候改的 |
| Remote SSH | 連遠端 GPU 機器,像在本機一樣編輯遠端檔案 |
| Debugpy | 一步一步追蹤 Python 程式碼 |
| Black Formatter | 存檔時自動排版,程式碼風格永遠一致 |
| Ruff | 快速 lint,幫你抓常見錯誤 |
實際跑的結果
八個裡面五個 Cursor 已經內建了(Python、Pylance、Jupyter、Remote SSH、Debugpy),只補裝了三個:GitLens、Black Formatter、Ruff。已經裝過的會顯示 is already installed,不會重複裝。
跑的時候會看到一堆 DeprecationWarning: The 'punycode' module is deprecated,這是 Cursor 內部用的 Node.js 模組版本比較舊,跟你無關,不用理它。
步驟 3:設定 settings.json
打開編輯器 → Cmd+Shift+P → 輸入 **“Open User Settings (JSON)”**(注意有 User 這個字,不要開成 defaultSettings.json,那個是唯讀的預設值)。
課程要你加的設定:
{
"python.analysis.typeCheckingMode": "basic",
"editor.formatOnSave": true,
"editor.rulers": [88, 120],
"notebook.output.scrolling": true,
"files.autoSave": "afterDelay"
}
每個設定為什麼這樣選
"python.analysis.typeCheckingMode": "basic" — 預設是 "off",開到 "basic" 之後,你如果把一個字串丟進一個只吃數字的函式,還沒跑程式,編輯器就會畫波浪線告訴你。AI 工程常常在處理 tensor 的 shape,維度傳錯是最常見的 bug 之一。不開到 "strict" 是因為太嚴格,第三方套件的型別標注不完整,會噴一堆假警告。
"editor.formatOnSave": true — 預設是 false。開了之後,按 Cmd+S 存檔的瞬間,Black 自動幫你把程式碼排整齊。冒號後面補空格、等號兩邊補空格、縮排統一。你不用花任何腦力在格式上面。
"editor.rulers": [88, 120] — 在編輯器裡畫兩條淡淡的垂直線。88 是 Black 自動換行的位置,120 提醒你註解或 docstring 寫太長了。不會強制你什麼,純粹是視覺參考。
"notebook.output.scrolling": true — 預設是 false,notebook 的 cell 輸出有多長就顯示多長。訓練模型的時候一個 cell 可能印出幾千行 loss 數字,不開這個整個畫面會被撐爆。開了之後輸出區變成固定高度、可捲動的小視窗。
"files.autoSave": "afterDelay" — 預設是 "off"。你改了程式碼,跑的時候忘記存,結果跑的是上一版,debug 半天發現根本沒跑到新的。這個設定讓編輯器在你停止打字幾秒後自動存檔。
走到這裡才會知道的事:formatOnSave 會改你的 settings.json
把 "editor.formatOnSave": true 加進去之後,第一次按 Cmd+S 存 settings.json 的時候,編輯器會自動把你的 JSON 重新排版。例如 [88, 120] 可能被拆成兩行。這不是壞掉了,正是 format on save 在做它該做的事。
步驟 4:終端機整合
再加這幾個設定(Mac 用 zsh):
{
"terminal.integrated.defaultProfile.osx": "zsh",
"terminal.integrated.fontSize": 13,
"terminal.integrated.scrollback": 10000
}
常用的終端機快捷鍵:
| 動作 | macOS |
|---|---|
| 開關終端機 | Ctrl+` |
| 新開一個終端機 | Ctrl+Shift+` |
| 分割終端機 | Cmd+\ |
分割終端機在 AI 工程很實用:一邊跑訓練腳本,一邊看 GPU 使用狀況。
步驟 5:遠端開發(Remote SSH)
這步的概念是:將來要訓練大模型,本機跑不動,你會需要 SSH 連進雲端的 GPU 機器。Remote SSH 這個擴充套件讓你在編輯器裡直接打開遠端機器的資料夾,編輯檔案、跑終端機、debug,體驗跟在本機完全一樣。不用另外開 SSH 視窗用 vim 改檔案。
操作流程:Cmd+Shift+P → “Remote-SSH: Connect to Host” → 輸入 user@遠端IP。
課程還教了怎麼設 SSH key 做免密碼登入,以及在 ~/.ssh/config 裡加設定讓連線只要選名字。
我目前用不到這步。 我的策略是 Cursor 在本機做開發和小實驗,需要 GPU 算力的時候上 Google Colab(免費的 T4 GPU)。Colab 是在瀏覽器裡操作,不走 SSH。等將來需要自己的 GPU 伺服器時再回來設。
替代編輯器
課程提了三個替代方案:
Cursor — 我在用的。VS Code 的 fork,內建 AI 程式碼生成。擴充套件和 settings.json 格式跟 VS Code 相容。
Windsurf — 另一個 AI-first 的 VS Code fork,同樣相容。
Vim/Neovim — 課程直接說:如果你現在還不會 Vim,不要現在學。學習曲線會跟學 AI 工程搶注意力。已經會的人才留在 Vim。
設定好之後的日常工作流
課程描述的 daily workflow:
- 打開專案資料夾(或 Remote SSH 連進遠端 GPU 機器)
- 寫 Python,有自動補全、型別提示、紅線即時抓錯
- 跑 Jupyter notebook,直接在編輯器裡跑
- 用內建終端機跑訓練腳本、
uv pip install、監控 GPU - 用 GitLens 看改了什麼,確認後再 commit
這裡的重點是:所有事情都在同一個視窗裡完成。不用在瀏覽器、終端機、編輯器之間切來切去。
關鍵術語
| 術語 | 一般人怎麼說 | 實際意思 |
|---|---|---|
| LSP | 「自動補全引擎」 | Language Server Protocol,一套標準協定,讓編輯器跟語言伺服器溝通,取得型別資訊、補全建議、錯誤提示 |
| Pylance | 「Python 外掛」 | 微軟做的 Python 語言伺服器,底層用 Pyright 做型別檢查和 IntelliSense |
| Remote SSH | 「在伺服器上工作」 | 擴充套件在遠端機器裝一個輕量伺服器,把畫面串流回本機的編輯器 |
| Format on save | 「自動排版」 | 每次存檔時跑 formatter(Black 或 Ruff),讓程式碼風格永遠一致 |
驗證設定
驗證 Black format on save
新建一個 .py 檔,貼一段故意寫得很醜的程式碼:
def add(a:int,b:int)->int:
return a+b
按 Cmd+S 存檔。如果 Black 生效,冒號和箭頭旁邊會自動補上空格,變成:
def add(a: int, b: int) -> int:
return a + b
驗證型別檢查
在同一個檔案加上:
result = add("hello", 3)
函式宣告要 int,你傳了 str。如果型別檢查生效,"hello" 底下會出現波浪線警告。
走到這裡才會知道的事
defaultSettings.json 不是你要的
Cmd+Shift+P 搜尋 settings 的時候,會看到兩個選項。**“Open User Settings (JSON)”** 才是你要改的那個。另一個 “Open Default Settings (JSON)” 是編輯器的出廠預設值,打開來有幾千行,而且是唯讀的,改不了。
Cursor 的型別檢查設定跟 VS Code 不一樣
課程教的 "python.analysis.typeCheckingMode": "basic" 在 Cursor 上不會生效。Cursor 內建的不是 Pylance,是 Basepyright(Pyright 的一個分支)。型別檢查的設定 key 要用:
"cursorpyright.analysis.typeCheckingMode": "basic"
原本的 python.analysis.typeCheckingMode 留著不影響(萬一以後用 VS Code 還能用),但 Cursor 認的是 cursorpyright. 開頭的版本。
Cursor 的 Black formatter 需要多一步
在 Cursor 裡,光開 "editor.formatOnSave": true 可能不會自動用 Black。要在 settings.json 裡明確指定 Python 的 formatter:
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
}
我最後的 settings.json 長這樣
{
"window.autoDetectColorScheme": true,
"python.analysis.typeCheckingMode": "basic",
"cursorpyright.analysis.typeCheckingMode": "basic",
"editor.formatOnSave": true,
"editor.rulers": [88, 120],
"notebook.output.scrolling": true,
"files.autoSave": "afterDelay",
"terminal.integrated.defaultProfile.osx": "zsh",
"terminal.integrated.fontSize": 13,
"terminal.integrated.scrollback": 10000,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
}
}