昨天讓 agent 幫忙寫設定檔了。今天要處理手冊的另一半:正文。
想要讓 AI Agent 憑空寫出正文其實不太容易,不過,由於我們已經有許多文件與截圖,因此是可以做到的。
目前有的資料 (i.e. 提供給 AI Agent 的素材) 包含:
TESTID.md、agent/UI-MAP.md、agent/QUIRKS.md (昨天的文章有提到)如果可以,最好再提供幾篇已經審核沒問題的正文當範例 (一開始沒有也沒關係,就只是人工審查要仔細一點)。
必要時,甚至可以讓 AI Agent 去參考原始碼,來提高它對產品的掌握度。
在要求 AI 寫出好的正文之前,得先講清楚「好的正文」長什麼樣。沒有這個基準,「請寫得專業一點」這種形容詞式的指示,對 AI 來說幾乎沒有意義,因為它沒有任何具體的、可以對照的標準。
一段好的手冊正文,大致有這些特徵:
用祈使句
寫「點擊『建立』」,不要寫「使用者可以點擊建立按鈕」。
一步一行
每個操作動作獨立成一行,不要把多個步驟擠在同一段落裡。
描述使用者看得到的行為
讀者需要知道畫面會怎麼變,不需要知道背後是哪個 Vue component 在更新狀態。 (歡迎自行替換成各位熟悉的前端框架)
不假設讀者懂內部術語
camera-dialog-source 是給 runner 用的 testid,不是給讀者看的欄位名稱。
明確說明完成條件
每個操作之後,讀者該期待畫面有什麼變化,這是確認自己有沒有做對的依據。
以新增攝影機為例,下面兩種寫法都不算語法錯誤,但品質差很多:
不好的寫法:
使用者可以在攝影機設定對話框中輸入相關資訊,然後按下按鈕完成新增。
好的寫法:
1. 在「顯示名稱」輸入「大門西側」。
2. 在「RTSP 位址」輸入攝影機的串流位址。
3. 點擊「建立」。
4. 畫面出現「已新增攝影機『大門西側』」的通知。
第二段不是因為文筆比較華麗,而是它讓讀者知道要填哪裡、要按什麼,以及成功時應該看到什麼。
agent/STYLE.md:把品質標準寫成檔案前面列的那幾條品質特徵,不應該每次都在 prompt 裡重打一遍。跟 UI-MAP.md、QUIRKS.md 一樣,把它們寫成 agent/STYLE.md。完整內容在範例專案裡,這裡只節錄一部分:
## 資料來源
- 只根據本章的 manifest、截圖,以及 agent/、TESTID.md、i18n 文案撰寫。
資料裡找不到證據的功能、步驟、限制,一律不寫;覺得「應該要有」的內容,回報給人,不要自己補。
- 如果發現 manifest、截圖、i18n 三者對不上,不要自己挑一個寫,
照 manifest 寫完後把差異回報給人。
## 用詞
- 有標號的元件,用 {{legend.<key>}} 引用,外面加「」。例如 點擊「{{legend.confirm}}」。
- 沒有標號的元件,名稱直接取自 zh-Hant.json,外面加「」。
- testid、component 名稱與 runner 行為只能用來理解上下文,不能出現在正文。
## 截圖
- 用 {{screenshot:<name>}} 放圖,獨立一行,放在對應的操作步驟之後。
- manifest 裡每一張截圖都要出現一次,不能漏、不能重複。
{{legend.<key>}} 是 Day 12 就定下來的設計:正文不寫標號數字,也不把 legend 文字抄進來,而是引用 legend 的語意 key,合併正文時再換成本章 legend 的文字。這樣標號順序調整、或是換語言時,正文都不用跟著改。
這份文件跟 Day 08 的 TESTID.md 有類似的定位:它同時是給人審稿用的檢查清單,也是餵給 agent 的上下文。之後如果團隊決定把「點擊」統一改成「選取」,只要改這一份檔案和範例,不需要到處修改 prompt。
另外,不要讓 AI 自由決定整篇 Markdown 的結構。STYLE.md 裡同時固定了正文骨架:
# <manifest 的 title>
<用途簡介,一到兩句>
## 操作步驟
1. <步驟>
2. <步驟>
{{screenshot:<id>-01}}
3. <步驟>
## 完成後
<讀者應該看到什麼,用來確認自己做對了>
> 注意:<真正會影響操作的限制或前置條件;沒有就整段省略>
固定骨架有兩個好處:
上下文、規則、範例和骨架都已經放進 repo 之後,實際丟給 agent 的任務就可以很短。這次開了一個全新的 agent,只給它這一段:
讀 @agent/STYLE.md、@agent/UI-MAP.md、@agent/QUIRKS.md、
@apps/demo-stream-app/TESTID.md、
@apps/demo-stream-app/src/renderer/locales/zh-Hant.json,
以及 @docs/20-live-monitor.md 當範例(模仿結構與語氣,不要複製內容)。
根據 @manifest/50-camera-add.yaml 和 @screenshots/camera-add-*.png,
寫 @docs/50-camera-add.md。寫完跑 npm run validate。
只能新增或修改 @docs/ 底下的檔案,不要動 @manifest/ 和 @screenshots/。
一樣,只要大方向差不多,prompt 怎麼下應該影響不大。
agent 看到的 manifest 是這一段已經跑通的操作路徑:
- { action: click, testid: camera-add }
- { action: waitFor, testid: camera-dialog }
- { action: fill, testid: camera-dialog-name, text: 大門西側 }
- { action: fill, testid: camera-dialog-source, text: 'rtsp://192.0.2.10/live' }
- { action: click, testid: camera-dialog-confirm }
- { action: waitFor, testid: toast }
最後產出的正文是這樣:
# 新增攝影機
這一章說明怎麼在 DemoStreamApp 建立一台攝影機,並填入它的 RTSP 位址。
## 操作步驟
1. 等待左側的「攝影機清單」載入完成。
2. 點擊清單右上角的「新增攝影機」。
{{screenshot:camera-add-01}}
3. 在「{{legend.name}}」輸入「大門西側」。
4. 在「{{legend.source}}」輸入「rtsp://192.0.2.10/live」。
{{screenshot:camera-add-02}}
5. 點擊「{{legend.confirm}}」。
{{screenshot:camera-add-03}}
## 完成後
畫面出現「已新增攝影機『大門西側』」的通知,表示攝影機已經建立。
「{{legend.zone}}」預設為「大門」,「{{legend.enabled}}」預設就是開啟的,這個範例沒有另外變更。
> 注意:「{{legend.name}}」是空的時候,「{{legend.confirm}}」無法點擊。
步驟順序跟 manifest 完全一致,沒有自己補上「測試連線」這類看起來合理的步驟;waitFor: toast 被翻成「畫面出現通知」,而不是「等待 toast」;按鈕一律用 {{legend.*}} 引用,testid 一個都沒有漏進正文。「注意」那一點則是從 QUIRKS.md 來的,截圖裡「建立」也確實是灰的。
過程中如果遇到問題,例如截圖跟 TESTID.md 的規則對不上、編號圓圈蓋到欄位名稱,或是資料不足以寫出某一段,agent 不會自己挑一個答案硬寫,而是停下來回報、跟你討論。尤其是超出 docs/ 範圍的問題,它沒有權限動,就該交給人決定要改 manifest、改 runner,還是重拍截圖。這正是 prompt 最後一句想要的行為。
正文由 AI 產出,不代表人可以跳過審查 ,畢竟責任還是要由人類來扛的。在檢查時建議對照三樣東西:
看截圖
正文提到的按鈕與欄位,畫面上真的找得到嗎?
看 manifest
正文的操作順序,跟實際跑過的步驟一致嗎?
看 App 文案
產品介面上的用字遣詞有沒有被 AI 改寫成其他自創名稱?
雖然上面是寫要人工檢查,但我相信這個部份其實也可以透過另一個 AI Agent 來審查。或者也可以考慮使用最近正夯的 Jev 來幫忙判斷是否有符合要求~
把今天的流程整理起來,大概會是這樣:
人先寫好 STYLE.md 與兩章範例
↓
agent 讀取 agent/ 上下文、STYLE.md 與範例
↓
agent 讀取 manifest 與本章截圖,寫出 docs/{order}-{id}.md 初稿
↓
遇到問題時,agent 回報並跟人討論
↓
人對照截圖、manifest 與產品流程 review
↓
保留審核後版本,作為下一次的範例
這個流程裡,AI 的角色是把結構化資料翻譯成自然語言,不是自己決定產品怎麼操作。越靠近真相來源的部分,越應該由 manifest、i18n 與產品文件提供;越靠近語氣和段落的部分,才交給 AI 發揮。
今天把 AI 的工作範圍從「寫 manifest」延伸到「寫正文」了。要讓這件事可靠,重點不是一句更厲害的 prompt,而是把輸入與品質標準準備好:
agent/STYLE.md 與人工整理的 docs/ 章節固定文章風格,每次的任務 prompt 只需要指定章節與可以動的範圍。{{legend.key}} 引用標號,所以 legend 必須跟畫面上的字完全一致。寫正文這件事,價值不只在於省下打字時間,更重要的是把「品質標準」講清楚。而把操作寫成給人讀的句子,本身也是一次 review。