CodeGym /課程 /ChatGPT Apps /自我改進的 App:閉環式改進循環

自我改進的 App:閉環式改進循環

ChatGPT Apps
等級 20 , 課堂 3
開放

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_callcost_per_taskcost_per_user,以及特定工具或情境的成本異常飆升。它們會說:「我們在燃燒比預期更多的 tokens 與金錢」,或相反地,「還有空間,可以提升品質」。

產品訊號則來自事件,例如 app_openedworkflow_startedworkflow_completedcheckout_*。這包括 activation‑rate、漏斗各步驟間的轉換、分群的留存。它們反映了真實的人類行為正在發生什麼。

品質與行為訊號則包含對 golden cases 的 LLM‑evals 結果(correctness/helpfulness/style/safety 的分數)、抽樣的人工對話審查、thumbs up/down、商店中的投訴與評論。這些最接近「App 變聰明/變笨」的直觀感受。

把這些整理成表格會很方便:

訊號類型 範例 來源
技術 error-ratep95 latency、MCP/ACP 的 timeouts 日誌/指標 (M17)
經濟 cost_per_tool_callcost_per_taskcost_per_user cost 儀表化 (M19.1)
產品 activation、轉換、retention 產品事件 (M19.3)
品質/行為 LLM-eval score、safety 標記、回饋 golden cases + LLM‑evals + 評論 (M20)

關鍵點:所有這些訊號都需要和特定情境與 App 版本關聯後再記錄。也就是說,在事件中至少要包含 scenarioappVersionexperimentId。這樣一來,當你看到 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…」;
  • 澄清措辭(降低與其他工具的重疊);
  • 加入結果資訊(destructiveHintisConsequential)。

Safety 規則屬於 prompt/描述的一部分,用於在複雜領域中的行為。最好在有充分的 safety‑eval 之後再調整。

行為架構(behavior)

有時光靠 prompt 解不了問題:你需要改變行動順序

例如:

  • 在呼叫昂貴工具前,加入必須的參數澄清步驟;
  • 把部分運算移到獨立且更便宜的一步(例如先在後端做預篩);
  • 限制某情境中連續的 tool 呼叫次數。

這些改動通常描述在代理或 MCP 層的設定中,而不只是在 prompt 裡。

UX 與文案(copywriting)

沒錯,按鈕與錯誤訊息的文字也是品質的一部分。當 GiftGenius 顯示:

「錯誤 500。請聯絡管理員」

所帶來的感受,和下面這樣是完全不同的:

「無法從商店取得回應。你已挑選的點子不會遺失,請稍後再試著完成購買」

中介畫面、提示、精靈結構——這些都會影響你所追蹤的 activation‑rate 與轉換。

經濟

這裡我們玩的是熟悉的「品質 ↔ 成本」:

  • 模型選擇(昂貴的 reasoning、或快速/便宜的);
  • reasoning/代理步數深度(允許多少次迭代);
  • 對話限制(例如單次工作階段中最多 N 次重算推薦);
  • 「便宜的」fallback 模式,當 token/配額預算用罄時啟用。

這裡的訊號會匯入 cost_per_taskcost_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_invocationworkflow_completedcheckout_*,並帶上 requestIduserIdscenarioappVersioncostEstimateUsd。在此之上建立 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。
  • 描述回應格式:帶有 patternssuggestionschangelog 欄位的結構化 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 才會不再靜止,並且真正自我改進

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION