【MLflow LLMs & Agents 實戰】#03 用 Prompt Registry 管理你的提示詞版本:Vibe Coder 必知

測驗:用 Prompt Registry 管理你的提示詞版本

共 5 題,點選答案後會立即顯示結果

1. 文章把 MLflow Prompt Registry 比喻成什麼?

  • A. 提示詞的資料庫備份工具
  • B. 提示詞的 Git(版本控制)
  • C. 提示詞的翻譯器
  • D. 提示詞的加密保險箱

2. 關於 version 與 alias 的關係,下列敘述何者正確?

  • A. version 可以隨時移動,alias 註冊後固定不變
  • B. version 和 alias 都是不可變的
  • C. version 不可變(固定住),alias 可移動(可改指向別的版本)
  • D. version 和 alias 是同一個東西的兩個名字

3. 下面這個 URI 代表什麼意思?

prompts:/article-summarizer@production
  • A. 載入 article-summarizer 這個 prompt 中 production alias 所指向的版本
  • B. 載入名為 production 的第一個版本
  • C. 把 article-summarizer 部署到 production 環境
  • D. 刪除 article-summarizer 的 production 標籤

4. 為什麼文章建議應用程式用 alias(如 @production)取用,而不是寫死版本號(如 /7)?

  • A. alias 載入速度比較快
  • B. 寫死版本號會讓 prompt 無法被評估
  • C. alias 可以加密 prompt 內容
  • D. 上線新版時只要移動 alias,應用程式不用改 code、不用重新部署

5. 文章描述的健康 prompt 迭代工作流順序是什麼?

  • A. 升 alias → 改 prompt → 評估 → 比較
  • B. 改 prompt(註冊新版)→ 評估 → 比較 → 升 alias
  • C. 評估 → 改 prompt → 升 alias → 比較
  • D. 比較 → 升 alias → 改 prompt → 評估

【MLflow LLMs & Agents 實戰】系列 #03(共 4 篇)|難度:L3-熟練
前置:本系列 #01(Tracing)、#02(評估)+ 基本 Python

一句話說明

Prompt Registry 就是「提示詞的 Git」——把你餵給 LLM 的那段 prompt 從程式碼裡拉出來,變成一個有版本號、有 commit message、有 production / staging 標籤的東西,讓你隨時能回答:「這個爛輸出,到底是哪一版 prompt 產生的?」

如果你的 AI 助手把 prompt 直接用一大坨字串硬塞在程式碼中間(hardcode),那每次改字、比較效果、回滾,全都要靠翻 git log 猜——這正是 Prompt Registry 要解決的痛點。


為什麼 prompt 需要版本控制?

先講清楚問題,你才知道這篇在救什麼。

在 LLM 應用裡,prompt 就是你的核心邏輯。改一句「請用條列式回答」可能讓輸出品質天差地遠。但 prompt 常見的下場是:

# 🚩 典型的「prompt 埋在程式碼裡」寫法
def summarize(article: str) -> str:
    prompt = f"你是專業編輯,請把以下文章縮成三點重點:\n{article}"
    return call_llm(prompt)
Code language: PHP (php)

這樣寫,會遇到三個問題:

  1. 無法回溯:上週輸出品質好,這週變差,是誰改了 prompt?改了什麼?沒人說得準。
  2. 無法比較:想 A/B 測兩個版本的 prompt,得同時維護兩份程式碼。
  3. 無法安全回滾:發現新 prompt 有問題,想退回舊版,只能翻 git 硬找。

Prompt Registry 把 prompt 變成受管控的資產:每次改動都有版本號、可以打標籤、可以搭配 #02 的評估分數一起看,形成「改 → 評估 → 比較 → 上線」的閉環。


四個必懂的名詞(先認得,再看 code)

讀 Prompt Registry 的程式碼前,先把這四個詞對上白話,後面 code 就好懂了:

名詞 白話 類比 Git
template 一段有變數空格的 prompt 範本 一個 repo(檔案)
version 每次註冊自動 +1 的版本號(1, 2, 3…) 一個 commit
alias 貼在某個版本上的標籤,如 production 一個會移動的 tag / 分支指標
commit message 這次改動的說明 git commit 的訊息

必看懂:template(範本)、version(版本號)、alias(別名標籤)——這三個是每天都會碰的。 📌 知道就好:commit message,遇到再填。

關鍵直覺:version 是不可變的(註冊了就固定住),alias 是可移動的(今天指向 v3,明天可以改指 v5)。程式碼裡「用哪一版」通常是透過 alias 取用,而不是寫死版本號。


最小範例:註冊一個 prompt

import mlflow

prompt = mlflow.genai.register_prompt(
    name="article-summarizer",
    template="你是專業編輯,請把以下文章縮成三點重點:\n\n{{ article }}",
    commit_message="初版:三點重點摘要",
)

print(prompt.name)     # article-summarizer
print(prompt.version)  # 1
Code language: PHP (php)

這在幹嘛:把一段 prompt 範本存進 MLflow,取名叫 article-summarizer。MLflow 自動給它版本號 1

逐行翻譯:

prompt = mlflow.genai.register_prompt(   # 註冊一個 prompt 到 registry
    name="article-summarizer",           # 這個 prompt 的名字(像檔名)
    template="...{{ article }}",          # 範本本體,{{ article }} 是待填變數
    commit_message="初版:三點重點摘要",   # 這次改動的說明(像 git commit)
)
Code language: PHP (php)

注意 template 裡的 {{ article }}——雙大括號包起來的是「變數插槽」,代表「這裡之後會填東西進去」。這是 MLflow prompt 用的變數語法(跟 Python f-string 的單大括號 {article} 不一樣,別搞混)。


載入並填入變數

註冊只是存起來,真正用的時候要載入 + 填變數

# 載入最新版
prompt = mlflow.genai.load_prompt("prompts:/article-summarizer/1")

# 把變數填進去,變成真正要送給 LLM 的字串
final_prompt = prompt.format(article="MLflow 是一個開源的 ML 生命週期平台……")

print(final_prompt)
# 你是專業編輯,請把以下文章縮成三點重點:
#
# MLflow 是一個開源的 ML 生命週期平台……
Code language: PHP (php)

這在幹嘛load_prompt 把第 1 版拉出來,.format(...){{ article }} 換成真實內容,產出最終要餵給 LLM 的完整字串。

那串 "prompts:/article-summarizer/1" 是 MLflow 的 URI(統一資源位址),拆開看:

prompts:/article-summarizer/1
   │            │           │
   協定        prompt 名    版本 or alias
Code language: JavaScript (javascript)

必看懂prompts:/名字/版本 這個格式。最後那格可以是版本號(/1),也可以是 alias(/production)——這是重點,下一段講。


用 alias 取用版本(重點!)

直接在程式碼寫死 /1/2 很脆弱——每次上線新版都得改 code 再部署。正解是用 alias

# 把 production 這個標籤貼到第 3 版
mlflow.genai.set_prompt_alias(
    name="article-summarizer",
    alias="production",
    version=3,
)

# 應用程式裡永遠這樣載入,不寫死版本號
prompt = mlflow.genai.load_prompt("prompts:/article-summarizer@production")
Code language: PHP (php)

這在幹嘛:先把 production 標籤貼到第 3 版;之後應用程式只認 @production,完全不知道底下是第幾版。

注意 URI 的差別:

  • prompts:/名字/3 → 用版本號(斜線 /
  • prompts:/名字@production → 用alias(小老鼠 @

好處:想上線新版 prompt,只要把 production alias 移到新版本,應用程式一行 code 都不用改、不用重新部署。想回滾?把 alias 移回舊版就好。這就是為什麼「用 alias 取用」是最佳實務。

常見 alias 慣例:production(正式上線)、staging(測試中)、champion / challenger(A/B 對照)。


把 prompt 版本綁到 trace / run

這是 Prompt Registry 真正發威的地方,也是接續 #01 Tracing 的關鍵:當你載入的 prompt 被用來呼叫 LLM,MLflow 會自動把「用了哪一版 prompt」記進 trace

import mlflow

mlflow.openai.autolog()  # 開啟自動追蹤(見 #01)

prompt = mlflow.genai.load_prompt("prompts:/article-summarizer@production")

# 這次呼叫的 trace 會自動關聯到 production 指向的那個版本
response = call_llm(prompt.format(article="……"))
Code language: PHP (php)

這在幹嘛:因為 prompt 是從 registry 載入的,MLflow 知道它的身分,會在這次呼叫的 trace 上標記「本次使用 article-summarizer v3」。

於是你就能回答那個致命問題:「這個奇怪的輸出,是哪一版 prompt 產生的?」 打開 MLflow UI 的那條 trace,版本號寫在上面。不用再猜。


完整迭代工作流:改 → 評估 → 比較 → 升 alias

把 #02(評估)和本篇串起來,一個健康的 prompt 迭代長這樣:

# 1. 改 prompt,註冊成新版本(不覆蓋舊的,version 自動變 4)
new_prompt = mlflow.genai.register_prompt(
    name="article-summarizer",
    template="你是專業編輯,請用繁體中文把文章縮成三點,每點不超過 20 字:\n\n{{ article }}",
    commit_message="限制每點字數,避免冗長",
)

# 2. 對新版本跑評估(見 #02),拿到分數
results = mlflow.genai.evaluate(
    data=eval_dataset,
    predict_fn=lambda article: call_llm(new_prompt.format(article=article)),
    scorers=[relevance_scorer, conciseness_scorer],
)

# 3. 比較 v3(現任 production)vs v4 的評估分數
#    → 在 MLflow UI 並排看兩個 run 的指標

# 4. 新版更好,才把 production alias 升上去
mlflow.genai.set_prompt_alias(
    name="article-summarizer",
    alias="production",
    version=4,
)
Code language: PHP (php)

整個流程的價值:每一版 prompt 都有版本號、有 commit message、有對應的評估分數,升上 production 是「數據支持的決定」而不是「感覺新的比較好」。要回滾也只是把 alias 移回 v3 的一行事。


🚩 紅旗:看到這些要警覺

AI 幫你寫 LLM 應用時,很容易生出這些「看起來能跑、其實埋雷」的寫法:

紅旗 1:prompt 硬編碼在程式碼裡

prompt = "你是專業編輯,請把文章縮成三點:" + article  # 🚩 沒進 registry
Code language: PHP (php)

沒版本、沒法回溯、沒法評估比較。看到成串 prompt 字串直接埋在函式裡,就該問 AI 能不能改用 Prompt Registry 管理。

紅旗 2:應用程式寫死版本號

prompt = mlflow.genai.load_prompt("prompts:/summarizer/7")  # 🚩 寫死 /7
Code language: PHP (php)

每次上線都要改 code 重部署,還容易忘。正解是用 @production alias。

紅旗 3:改 prompt 直接覆蓋,沒留舊版 如果 AI 的作法是「把 template 字串改掉就好」而沒有 register_prompt 註冊成新版本,那舊版就消失了,出事無法回滾。每次改動都該是新版本,而不是就地覆蓋。

紅旗 4:升 production 前沒跑評估

# 🚩 改完 prompt 直接把 production 指過去,沒經過評估
mlflow.genai.set_prompt_alias(name="summarizer", alias="production", version=9)
Code language: PHP (php)

沒有 #02 的評估數據就升上線,等於用正式流量當白老鼠。升 alias 前應該先有評估分數撐腰。

紅旗 5:搞混 {{ }} 和 f-string 的 { }

template = f"請摘要:{{ article }}"  # 🚩 混用,容易出錯
Code language: PHP (php)

MLflow prompt 變數用雙大括號 {{ article }}不要加 f-string 前綴 f——加了 f 會被 Python 先處理掉。範本就是普通字串,變數留給 .format() 填。


Vibe Coder 驗收檢查點

拿到 AI 寫的 Prompt Registry 程式碼,這樣驗收:

  1. 確認 prompt 有進 registry:搜尋程式碼裡有沒有 register_prompt。如果 prompt 只是普通字串變數,請 AI 改成註冊制。
  2. 確認用 alias 而非寫死版本:載入語句應該長得像 @production,不該是 /7 這種硬版本號。可以問 AI:「這裡為什麼用寫死版本號而不是 alias?上線後要改版怎麼辦?」
  3. 跑一次載入 + format,看輸出對不對
  4. 打開 MLflow UI 確認 trace 有標到版本:跑一次呼叫後,到 UI 找那條 trace,應該能看到關聯的 prompt 版本。看得到,才代表回溯能力真的接上了。
  5. 確認迭代有評估撐腰:升 production alias 的那段程式碼前後,應該找得到 evaluate 的呼叫。沒有評估就升版,是紅旗 4。

看不懂就這樣問 AI

把程式碼貼給你的 AI 助手,直接問:

「這段用了 MLflow Prompt Registry,請一行一行用白話解釋,我是初學者。特別說明 register_promptload_promptset_prompt_alias 各自在幹嘛,還有 prompts:/名字@production 這個 URI 怎麼讀。」

想確認有沒有踩紅旗,問:

「這段 LLM 應用的 prompt 是硬編碼還是有進 Prompt Registry?載入時是用 alias 還是寫死版本號?升上 production 前有沒有先跑評估?有的話幫我指出哪幾行,沒有的話幫我補上。」


小結

  • Prompt Registry = 提示詞的 Git:template(範本)、version(不可變版本號)、alias(可移動標籤)、commit message。
  • 註冊用 register_prompt,載入用 load_prompt,變數用雙大括號 {{ }} 搭配 .format() 填。
  • 應用程式用 alias(@production)取用,別寫死版本號——上線改版不用動 code。
  • prompt 版本會綁進 trace,讓你能回答「這輸出是哪一版 prompt 產的」。
  • 健康的迭代 = 改 → 評估(#02)→ 比較 → 升 alias,每步都有數據可回溯。
  • 看到 prompt 硬編碼、寫死版本號、就地覆蓋、無評估升版——都是紅旗。

下一篇(#04)會把 Tracing、評估、Prompt Registry 這些拼圖組成一個完整的 LLM 應用觀測與迭代流程。

進階測驗:用 Prompt Registry 管理你的提示詞版本

測驗目標:驗證你是否能在實際情境中應用所學。
共 5 題,包含情境題與錯誤診斷題。

1. 你發現正式環境某個 prompt 的輸出品質變差,想立刻退回上一個穩定版本。應用程式是用 prompts:/summarizer@production 載入的,最省事又不用重新部署的做法是什麼? 情境題

  • A. 修改應用程式的載入語句,寫死成舊版本號後重新部署
  • B. 用 register_prompt 把舊 template 再註冊一次成新版
  • C. 用 set_prompt_alias 把 production alias 移回舊的穩定版本
  • D. 刪除有問題的那個版本,讓系統自動用前一版

2. 團隊想比較兩版 prompt 哪個較好再決定上線。依文章建議的迭代流程,「升 production alias」應該在什麼時候做? 情境題

  • A. 一改完 prompt 立刻升,讓正式流量幫忙驗證
  • B. 先對新版本跑評估、比較分數,確認新版更好之後才升
  • C. 註冊新版本的同時就在 register_prompt 裡直接升
  • D. 只要 commit message 寫得清楚就可以直接升

3. 你在 code review 一段 AI 生成的 LLM 應用,想確認它有沒有把「回溯輸出來自哪一版 prompt」做對。下列哪個檢查最能驗證這個能力真的接上了? 情境題

  • A. 確認 prompt 字串裡有沒有錯字
  • B. 確認 template 有沒有超過一定字數
  • C. 確認有沒有用 f-string 拼接變數
  • D. 跑一次呼叫後到 MLflow UI 找那條 trace,確認上面有標到關聯的 prompt 版本

4. 這段程式碼載入 prompt 後,最終字串竟然還殘留 article 變數插槽沒被替換掉。最可能的原因是什麼? 錯誤診斷

p = mlflow.genai.load_prompt( “prompts:/article-summarizer@production”) final = p.format(atricle=”今天的新聞內容……”) print(final) # 你是專業編輯……(變數插槽沒被填)
  • A. load_prompt 的 URI 用了 alias,alias 無法被 format 填變數
  • B. production 這個 alias 尚未指向任何版本
  • C. format 的參數名拼錯成 atricle,跟 template 裡的變數名 article 對不上
  • D. 缺少 mlflow.openai.autolog() 所以變數不會被填

5. AI 幫你寫的摘要功能長這樣,從 Prompt Registry 的角度看,最主要的紅旗是什麼? 錯誤診斷

def summarize(article: str) -> str: prompt = f”你是專業編輯,請把文章縮成三點:{article}” return call_llm(prompt)
  • A. 沒有型別標註,回傳型別不明
  • B. prompt 硬編碼在程式碼裡,沒進 registry,無法版本控制、回溯或評估比較
  • C. 用了 f-string,效能比 .format() 差
  • D. call_llm 沒有處理逾時例外

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *