1. 為什麼 App 需要閉環式改進循環
任何 LLM‑App 都活在瞬息萬變的世界。你會有新用戶與新情境,OpenAI 會推出新模型與防護機制,你自己也會更新 MCP‑伺服器、Agents SDK、UI 小元件…… 即便所有程式碼都寫得完美(是的,是的,我知道你們幾乎就這樣做),只要換了模型或 prompt,就可能在不知不覺間把一半情境弄壞。
沒有改進循環的生活大概是這樣:用戶寫信客服:「GiftGenius 開始推薦超出預算的禮物」或「卡住想了 15 秒」。你打開日誌,去改一下 system‑prompt,換個模型就上線。一週後同樣的事又在別處重演。最後的結果——慢性救火外加一堆誰也說不清的「魔法改動」。
有了循環就不一樣了。你會有:
- 對技術、金錢、產品與品質清楚且可理解的一組訊號;
- 固定的節奏:定期查看並挑選要驗證的假設;
- 在 code/config 中可控的改動;
- 自動化檢查:golden cases + LLM‑evals + 實驗。
如此一來,App 會從「凍結的 prompt」轉為一個有生命的系統,它會:
- 指出哪裡在痛、為什麼在痛;
- 提示具體可以改進什麼;
- 在「看似無害」的 prompt 變更後,避免品質悄悄下滑。
額外的好處:這樣的循環非常容易和你在前面模組已完成的內容銜接。來自 M17 的日誌與 SLO 提供技術訊號,M19 的 cost 儀表化與 AARRR 提供經濟與產品訊號,M20.1–2 的 golden cases 與 LLM‑evals 則提供品質訊號。剩下的就是把它們串成清晰的營運循環。
2. 改進所需的訊號地圖
要讓 App 自己提示該從哪裡改進,你需要清楚了解,你手上到底有哪些訊號,以及它們從哪裡來。可以分成四組來思考。
技術訊號來自你的 observability 堆疊:日誌 tool_invocation、latency 與 error‑rate 指標、MCP/ACP 的 health check、OAuth 失敗等。它們回答「服務是否存活、穩定性如何」。
經濟訊號產生於 cost 儀表化與計費:cost_per_tool_call、cost_per_task、cost_per_user,以及特定工具或情境的成本異常飆升。它們會說:「我們在燃燒比預期更多的 tokens 與金錢」,或相反地,「還有空間,可以提升品質」。
產品訊號則來自事件,例如 app_opened、workflow_started、workflow_completed、checkout_*。這包括 activation‑rate、漏斗各步驟間的轉換、分群的留存。它們反映了真實的人類行為正在發生什麼。
品質與行為訊號則包含對 golden cases 的 LLM‑evals 結果(correctness/helpfulness/style/safety 的分數)、抽樣的人工對話審查、thumbs up/down、商店中的投訴與評論。這些最接近「App 變聰明/變笨」的直觀感受。
把這些整理成表格會很方便:
| 訊號類型 | 範例 | 來源 |
|---|---|---|
| 技術 | error-rate、p95 latency、MCP/ACP 的 timeouts | 日誌/指標 (M17) |
| 經濟 | cost_per_tool_call、cost_per_task、cost_per_user | cost 儀表化 (M19.1) |
| 產品 | activation、轉換、retention | 產品事件 (M19.3) |
| 品質/行為 | LLM-eval score、safety 標記、回饋 | golden cases + LLM‑evals + 評論 (M20) |
關鍵點:所有這些訊號都需要和特定情境與 App 版本關聯後再記錄。也就是說,在事件中至少要包含 scenario、appVersion 與 experimentId。這樣一來,當你看到 golden cases 的 helpfulness 從 8.5 掉到 6.2,你不僅能說「變差了」,還能說是「在情境 "gift_selection",於版本 "1.3.0" 發版後,在實驗變體 "B" 中變差」。
在程式碼裡甚至可以為訊號設計一個簡單的結構:
// lib/improvement/signals.ts
export type SignalKind = "slo" | "cost" | "product" | "quality";
export type ImprovementSignal = {
kind: SignalKind;
scenario: string; // e.g. "gift_selection"
metric: string; // e.g. "p95_latency_ms", "cost_per_task"
value: number;
previous?: number; // 「之前」的值
};
這樣的物件既方便餵給儀表板,也方便餵給你未來的改進助理。
3. 經典的 feedback‑loop:4 個步驟
現在我們把一個每次都能依循的改進循環拼起來。它非常務實:四個步驟。
flowchart TD A[訊號:哪裡疼
或有成長機會] --> B[假設:
要改什麼、怎麼改] B --> C[受控的變更
在 code/config 中] C --> D[驗證:
offline + online] D --> A
步驟 1. 發現問題或機會
這一步你要回答「該往哪裡看」。例如:
- 有預算限制的 golden cases 的 LLM‑eval 顯示 helpfulness 下滑。
- p95 latency 在工具 "suggest_gifts" 上從 1.2 秒升到 3.8 秒。
- 情境 "gift_selection" 的 cost_per_task 在切換到 reasoning 模型後增加了 40%。
- workflow_completed → checkout_success 的轉換在更動 UX 精靈後下降了 5 個百分點。
- Store 一週內出現了 10 則投訴「禮物比指定上限更貴」。
重要細節:有時訊號不是在說「不好」,而是「可以更好」。例如你看到 cost_per_task 明顯低於允許門檻,而 quality‑score 已經 9/10。那就可以試試更昂貴的模型或更「聰明」的流程——或許轉換會上升。
步驟 2. 形成假設
假設不是「我們要重寫 prompt」,而是「我們認為在元件 Y 中做出具體改動 X,會改善指標 Z,因為……」。沒有「因為」就不是假設,只是願望。
例如:
- 「如果我們在 system‑prompt 中加入嚴格遵守預算的規則,並要求永遠解釋預算怎麼被利用,那麼在有預算的案例中,helpfulness 至少會提高 2 分。」
- 「如果我們將 rerank 這步的昂貴模型替換成 "gpt-mini",cost_per_task 會下降 30%,而轉換不會下滑超過 1 個百分點。」
- 「如果我們簡化 wizard(把兩步合併為一步)並重寫 CTA,activation‑rate 會提高 5 個百分點。」
在程式碼中,這樣的假設可以明確地描述為一個物件:
// lib/improvement/hypothesis.ts
export type ImprovementHypothesis = {
id: string;
scenario: string;
description: string; // 「要改什麼以及為什麼」
targetMetric: string; // 例如 "quality.helpfulness" 或 "conversion.checkout"
successCriteria: string;
};
是的,這幾乎就像一個 Jira 票,但至少是型別化的。
步驟 3. 做一個受控的改動
這裡有兩個關鍵詞:受控與分離。
受控代表改動以 PR/commit 的形式提交,關聯到某個假設,帶有變更日誌,並且最好有 feature flag 或版本。你不是「在生產上直接改了 prompt」,而是能指出是哪個版本釋出帶來了這個改動。
分離代表你盡量不要在同一個釋出中混入三個不同的假設。如果你同時:
- 更換模型,
- 重寫一半的 system‑prompt,
- 並在 UX 中加入新的一步,
那麼即便指標提升,也很難知道到底是什麼起了作用。更誠實的做法是用小步快跑。
從技術角度,改動可能出現在任何地方:
- 代理的 system‑prompt(lib/prompt/systemPrompt.ts);
- MCP‑tools 的描述(description、inputSchema、annotations);
- 代理的設定檔(reasoning 步數限制、特定 tool 的模型選擇);
- 小元件的程式碼(CTA、步驟順序、錯誤文字)。
步驟 4. 驗證是否變得更好
驗證分為離線(offline)與線上(online)。
離線驗證是用新的 App 版本在沒有真實用戶的情況下跑 golden cases。這裡你已經有:
- LLM‑evals(模組 20.1);
- threshold/baseline 邏輯(模組 20.2)。
你要看目標情境的 quality‑score 怎麼變化:上升、下降或持平。同時檢查 safety cases:任何 prompt 修改都應先通過 safety 集。
線上驗證是在真實流量上做實驗。最簡單的做法是,讓 N% 的用戶使用新版本,並比較:
- 目標行為的轉換(checkout、再次啟動情境);
- cost_per_task;
- 投訴/回饋。
之後要嘛關閉循環(假設被證實/否證並完成紀錄),要嘛產生新的假設。
4. 作為獨立代理的內部「改進助理」
現在來說重點:讓 LLM 模型再多一個角色——不僅回答用戶,也幫助你改進 App。這是一個獨立於使用者端 GiftGenius 的內部代理。
它是什麼
這個助理運行在你的內部環境(在同一個 repo、Dev Mode、獨立的 ChatGPT App)。它會:
- 閱讀日誌與對話樣本;
- 查看指標;
- 分析 system‑prompt 與工具描述;
- 協助提出問題與改動建議。
本質上,你得到了一個「虛擬的產品/分析師」,它:
- 不會累,能讀很多對話;
- 能快速找出重複的模式;
- 會撰寫 prompt 與 changelog 的草稿。
它接收什麼輸入
把輸入格式化,能讓代理更容易工作。例如,定義型別:
// lib/improvement/assistant.ts
export type BadDialogExample = {
id: string;
userMessages: string[];
appMessages: string[];
qualityScore?: number;
};
export type ImprovementInput = {
scenario: string;
signals: ImprovementSignal[]; // 來自前一節
examples: BadDialogExample[];
systemPrompt: string;
toolsDescription: string;
};
你可以從日誌匯出情境 "gift_selection" 的 10–20 個不理想對話,並附上目前的 system‑prompt 與工具描述,組成這個物件。
它應該輸出什麼
同樣地,固定預期的回應格式會很有幫助:
export type ImprovementSuggestion = {
patterns: string[]; // 重複出現的問題
promptPatches: string[]; // 對 system-prompt 的片段建議
toolsPatches: string[]; // 對工具描述的想法
uxCopyIdeas: string[]; // UX 文字的候選
changelog: string[]; // 簡短的「要改什麼」清單
};
用於此代理的 meta‑prompt 大致會是:
- 「分析這些範例與訊號」;
- 「描述 2–3 個問題模式」;
- 「在 prompt、tools 描述與 UX 文字各提出 1–2 項改動」;
- 「全部以嚴格定義的 JSON 格式回傳」。
接下來你再手動拿這些片段與團隊討論,整合進程式碼,並透過 eval 與實驗來驗證。一個重要原則:這個助理不會自行在生產上做任何改動。它只產生想法與文字,而不是 commit。
5. 改動的類型:到底可以「調」什麼
當有了這樣的助理與清晰的循環,很容易把所有事都簡化成「給我一個新的 system‑prompt 版本」。但實際上,可改進的範圍廣得多。
Prompt 與指令
System‑prompt 定義角色、語氣、優先級與硬性規則(例如預算、安全性、步驟順序)。它可以:
- 簡化,移除矛盾或重複的指令;
- 加強,補上缺少的規則(如預算的例子);
- 針對不同情境調整(為 "gift_selection"、"post_purchase_help" 等設置子 prompt)。
工具描述能幫助模型理解何時呼叫特定工具、以及它在做什麼。這裡的改進通常包括:
- 更明確的「Use this when… / Do not use when…」;
- 澄清措辭(降低與其他工具的重疊);
- 加入結果資訊(destructiveHint、isConsequential)。
Safety 規則屬於 prompt/描述的一部分,用於在複雜領域中的行為。最好在有充分的 safety‑eval 之後再調整。
行為架構(behavior)
有時光靠 prompt 解不了問題:你需要改變行動順序。
例如:
- 在呼叫昂貴工具前,加入必須的參數澄清步驟;
- 把部分運算移到獨立且更便宜的一步(例如先在後端做預篩);
- 限制某情境中連續的 tool 呼叫次數。
這些改動通常描述在代理或 MCP 層的設定中,而不只是在 prompt 裡。
UX 與文案(copywriting)
沒錯,按鈕與錯誤訊息的文字也是品質的一部分。當 GiftGenius 顯示:
「錯誤 500。請聯絡管理員」,
所帶來的感受,和下面這樣是完全不同的:
「無法從商店取得回應。你已挑選的點子不會遺失,請稍後再試著完成購買」。
中介畫面、提示、精靈結構——這些都會影響你所追蹤的 activation‑rate 與轉換。
經濟
這裡我們玩的是熟悉的「品質 ↔ 成本」:
- 模型選擇(昂貴的 reasoning、或快速/便宜的);
- reasoning/代理步數深度(允許多少次迭代);
- 對話限制(例如單次工作階段中最多 N 次重算推薦);
- 「便宜的」fallback 模式,當 token/配額預算用罄時啟用。
這裡的訊號會匯入 cost_per_task、cost_per_user、毛利,並與 quality‑score 一起觀察。
6. Guardrails:哪些不能交給 LLM 決定
當系統有了「改進助理」與便利的循環,很容易想按下「自動最佳化」按鈕去喝咖啡。讓我們先說好,哪些地方絕不能有這個按鈕。
權限變更(OAuth scopes、MCP 工具、資料存取)永遠是human‑in‑the‑loop 的範疇。任何模型都不該自行決定 App 現在可以讀取訂單、動到支付或寄信給用戶。同樣地,與 commerce 流程相關的一切:ACP/Stripe、限額、付款型態與退款等,都必須有人審查與測試。
App 的安全性側寫(在哪些領域可以提供建議、在哪些領域必須拒絕)也不該交給 LLM。模型可以幫忙撰寫規則文字,但決定你信任 App 涵蓋哪些主題仍由你來做。
資料與日誌政策(記什麼、存多久、如何回應刪除請求)也在此列。LLM 可以建議 Privacy Policy 的結構,但不該在沒有你參與的情況下更改程式碼裡的保留期。
那什麼可以半自動化?prompt 的措辭、工具描述與 UX 文字、工具的優先順序(在合理範圍內)、額外的澄清問題。這些可以交由助理提供點子,但最後的決定與驗證仍由人與 eval 腳本負責。
7. 端到端的改進循環範例(GiftGenius)
回到我們的主角。
問題
用戶設定了預算,但 GiftGenius 常常推薦超過上限的禮物。日誌裡能看到很多對話延續如「不行,太貴了」與「做便宜一點」。
訊號
首先你看到品質:對於「在 50$ 內挑禮物」這類 golden cases 的 LLM‑eval,helpfulness 大約是 6/10。評審經常在 reason 中寫道「禮物超出預算」或「沒有解釋如何考慮預算」。
同時也出現產品與經濟訊號:
- 有設定上限的情境,其 checkout_success 轉換低於沒有上限的情境;
- 部分用戶在看到太貴的選項後中止流程;
- 這類情境的 cost_per_task 較高,因為 App 會依照「便宜一點」的請求做多次重算。
用改進助理進行分析
你收集了 20 個用戶抱怨價格的對話,並組成 ImprovementInput:
- scenario = "gift_selection_with_budget";
- 帶有 helpfulness 與轉換下滑的 signals;
- 包含對話的 examples;
- 目前的 system‑prompt 與工具描述。
把這些餵給內部的改進助理。它可能回覆:
- 模式:
- 像「大約 50$ 以內」這樣表述的預算,被解讀得太寬鬆;
- system‑prompt 沒有明確要求「絕對不要推薦超過上限的禮物」;
- 回覆沒有向用戶解釋預算是如何被考量的。
- 建議:
- 在 system‑prompt 中加入嚴格遵守上限的指令;
- 要求模型總是明說「所有選項 ≤ X」;
- 若預算表述模糊(「大概」「差不多」),先加一個澄清問題。
假設與改動
整理假設:
「如果我們明確要求嚴格遵守上限,並請模型解釋預算的使用方式,則在有預算的案例中,helpfulness 至少會到 8/10,而購買轉換會提高 3 個百分點。」
把以下片段加入 system‑prompt:
export const budgetRule = `
如果使用者指定預算(例如:「最多 50$」或「大約 30€」),
將此金額視為嚴格的上限。
絕不要提出超過此上限的選項。
在每個回覆中明確說明所有選項都在預算內,
以及具體如何(例如:"所有禮物都不超過 45$")。
`.trim();
然後把 budgetRule 納入 GiftGenius 的整體 system‑prompt。
離線驗證
用新版本跑「有預算的禮物」這組 golden cases:
- LLM‑eval helpfulness 從 6.0 升到 8.5;
- correctness 也提升:預算得到遵守;
- safety 未變差(至少沒有更糟)。
若反過來——helpfulness 沒上升或 safety 下降——則改動不通過,需重新檢視假設。
線上測試
接著啟動實驗:
- 10% 的用戶拿到新的 prompt 版本(variant B);
- 其餘 90% 使用舊版(variant A)。
一週後查看:
- B 的 workflow_completed → checkout_success 轉換,例如變成 13%,而 A 是 10%;
- cost_per_task 幾乎不變;
- 抱怨「太貴」的對話比例下降。
實驗被判定為成功。
固定成果
之後:
- 把新 prompt 推到 100% 流量;
- 在回歸集加入新的 golden case「寬鬆的 50$ 預算」;
- 把結果寫入 changelog,並可能加到技術筆記:讓半年後也能清楚為何 prompt 中會有這麼嚴格的預算表述。
此循環結束。下一輪可以著眼於,例如對非常冷門興趣用戶的推薦,或是優化挑選成本。
8. 自我改進型 App 的小型路線圖
為了不讓這看起來像「又多出一大堆任務」,先看看最低需求是什麼,讓 App 就能算是自我改進;然後再看之後可以加什麼。
版本 1.0:最小的 improvement‑loop
第一步只需要三件事。
第一,結構化日誌與基本 SLO。你已會記錄 tool_invocation、workflow_completed、checkout_*,並帶上 requestId、userId、scenario、appVersion、costEstimateUsd。在此之上建立 SLO:latency、error‑rate、checkout 成功率。
第二,10–20 個 golden cases 與一個 LLM‑eval 腳本。小而精選的關鍵情境範例集 + safety cases。一個 CLI 腳本,能把它們丟進 App 與評審,並輸出 JSON 評分。
第三,每 2 週一次的簡單儀式。坐下來(單獨或和團隊),打開:
- 2–3 個 SLO、cost、產品指標的儀表板;
- golden cases 的 LLM‑eval 報告;
然後挑出1–2 個假設作為下一輪循環。把它們寫下、文件化,做小改版並驗證。
版本 2.0:「聰明的」 improvement‑loop
下一個層級會有:
內部改進助理。 這是一個獨立描述的代理(或 ChatGPT App),接收 ImprovementInput,輸出 ImprovementSuggestion。它幫你省下反覆手動篩對話的時間。
自動化報告。 根據日誌與 eval,可以產生:
- 問題案例叢集(例如所有「用戶重寫預算」的情況);
- 可直接使用的 prompt 與工具描述修改草稿;
- 簡短的 changelog。
CI hooks。 任何對 prompt、代理設定、工具描述的改動都會自動觸發:
- 功能性 golden suite;
- safety suite。
若 safety cases 失敗,或關鍵情境的品質未達門檻——build 會變紅,無法釋出。
9. 實作
練習 1:為自己的 App 做一個迷你 feedback‑loop
挑一個你應用的關鍵情境。對 GiftGenius 我們選的是「挑選與購買禮物」,你可以選相似或自己的情境。
用自由格式描述(或新建一個小小的 improvement-plan.md):
你要追蹤哪些訊號。 各取一個:
- 技術:例如對執行主要工作的工具追 p95 latency;
- 經濟:該情境的 cost_per_task;
- 產品:workflow_started → workflow_completed 的轉換,或到目標行為的轉換;
- 品質:此情境幾個 golden cases 的平均 quality_score。
接著固定下來,你認為的退化門檻。不要「哪天再看」,而是明確具體地寫下來:
- p95 > 5 秒——不行;
- cost_per_task 若增加超過 30% 且營收未成長——警訊;
- quality_score 掉到 7 以下——需要調查。
然後提出你的第一個假設。例如:
「我懷疑我們問了太多澄清問題。如果把 wizard 減少一個步驟,並把問題變得稍微寬泛一點,activation‑rate 會提升,而 helpfulness 幾乎不受影響。我會透過小幅 UX 改動與 A/B 測試來驗證。」
這就不只是「改善 UX」,而是循環中的一個具體步驟了。
練習 2:為改進助理撰寫 meta‑prompt
試著為你的 App 撰寫一段內部改進代理的 prompt。可以從簡單開始:
- 描述它是誰:「你是 App N 的品質分析師,會……」。
- 列出它會收到什麼輸入:對話、訊號、system‑prompt、描述等。
- 規劃任務:
- 找出 2–3 個問題模式;
- 在 prompt、tools、UX 文字各提出 1–2 項改動;
- 整理一份簡短的 changelog。
- 描述回應格式:帶有 patterns、suggestions、changelog 欄位的結構化 JSON。
即便你還不會從程式中呼叫這個代理,這段 prompt 也能幫助你更有條理地思考 App 的改進方式。
10. 構建改進循環的常見錯誤
錯誤 №1:只針對單一指標最佳化。
只專注一件事很誘人。你可能只盯著 cost 看,看到給 OpenAI 的帳單下降就開心——卻沒注意 quality‑score、轉換與留存一路下滑。也可能反過來,把品質在 reasoning 模型上拚到 10/10,卻忘了每個情境都要花上一美元。改進循環必須同時關注指標組合:品質 ↔ 金錢 ↔ 用戶行為。
錯誤 №2:「魔法般」的 prompt 改動卻沒有量化。
「我重寫了 system‑prompt,現在應該更好了」——沒有 golden cases 與 eval,兩週後就等著驚喜吧。任何 prompt 改動——尤其是在生產——都該通過清晰的流程:案例集、改前/改後的 LLM‑eval,必要時再做線上實驗。否則你不是在改進 App,而是在隨機擾動品質。
錯誤 №3:自動部署來自 LLM 助理的改動。
即便改進助理產出的 prompt 片段與工具描述再美,再有說服力,也不能不經審查就推到生產。模型看不到所有商務限制、安全風險、與你指標的脈絡。它的角色是顧問,而不是有釋出權的 DevOps。
錯誤 №4:改動與假設/訊號之間沒有關聯。
有時團隊憑「感覺」做修補,卻沒記下是什麼訊號導致改動、想驗證哪個假設。結果一個月後沒人記得為什麼 prompt 裡會有奇怪的一段文字,或它當初到底為了什麼。好的品質 PR 至少要回答三個問題:「哪裡在痛?」「我們改什麼?」「靠哪個指標判斷是否變好?」。
錯誤 №5:改進時忘了 safety。
在追求有用性的過程中,很容易放鬆 safety 限制、移除 prompt 中「看似多餘的拒絕」、或忘了跑 safety cases。任何對 system‑prompt、工具描述與代理行為的改動,都應先通過 safety‑eval。只要有一個原本通過的案例現在失敗了——無論其他指標多漂亮,這都是停車燈。
錯誤 №6:想要「一次優化所有東西」。
一次重寫半個 prompt、換模型、加一個 MCP‑tool、再上新 wizard——都放在同一個釋出裡——聽起來很有效率,但會讓你完全無法判斷是什麼改動起了作用。改進循環只有在迭代且聚焦時才有效:一到兩個假設、一小組改動、清楚的回滾計畫。
錯誤 №7:把改進循環變成偶發的「大掃除日」。
如果你每半年搞一次盛大的「品質日」,其餘時間都不看 eval 與指標,App 大部分時間都會在「隨波逐流」。更好的做法是小而規律的儀式:每週/兩週看訊號、更新假設、做小步驟。你的 ChatGPT App 才會不再靜止,並且真正自我改進。
GO TO FULL VERSION