跳到正文
Chandler Nguyen
AI閱讀時間2分鐘

我嘅AI Podcast主持講咗13次「Trời ơi」之後,我終於學識點寫真正會被執行嘅系統提示

我花咗幾日時間為AI podcast主持編寫系統提示。佢哋逐字閱讀咗——然後幾乎全部無視晒。解決方案唔係更好嘅措辭——而係明白LLM處理規則嘅方式,取決於規則喺pipeline中嘅位置。

上星期,我發現咗一件有啲尷尬嘅事。

我個AI podcast pipeline有個精心編寫嘅系統提示——「對話指南」——我花咗幾日時間先寫好。佢話畀兩位主持(兩個AI足球評論員)知,應該點樣同對方講嘢。唔好重複相同嘅開場。唔同段落要有唔同結構。口頭禪要克制使用。絕對唔好老作統計數據。

LLM逐字閱讀咗。然後幾乎全部無視晒。

越南主持一集講咗13次「Trời ơi」(天呀)。日本主持每個段落嘅開頭都係「いやー、健一さん!」(哎吔,健一先生!)。英文主持信心十足咁引用xG 0.35同65%控球率——呢啲數字喺我個database度根本唔存在。

個prompt被禮貌地接收咗。然後被無視咗。

呢個係我喺prompt engineering學到最有用嘅一件事:LLM有兩種閱讀模式,而且佢哋對待呢兩種模式嘅方式完全唔同。


兩種閱讀模式嘅問題

呢個係我最初嘅對話指南嘅樣。因為結構完全一樣,我將越南文版本翻譯成英文嚟展示:

STYLE GUIDELINES:

HOST INTERACTION PATTERN: Emotional Host + Analytical Host.

STRICT RULES FOR EVERY SEGMENT:

0. NEVER REPEAT THE SAME OPENING. Vary which host initiates, 
   which match moment they react to first.

1. EMOTIONAL START (mandatory): Every segment begins with 
   the emotional host's pure reaction.

2. DATA-GROUNDING RULE (mandatory): Every claim must cite 
   specific numbers. Not "they dominated" but "61% possession, 
   3.17 xG to 0.65."

3. CATCHPHRASES:
   Emotional host: "You see that?!" "Wait wait wait..."
   Analytical host: "There's a deeper reason..." "Let me tell you."

睇落好周全啦?我真係以為自己做足晒功課。

但當我睇到實際生成出嚟嘅script,情況係咁:

規則指南寫嘅內容LLM實際做咗嘅
規則0(禁止重複)變化開場方式每個段落都以情緒化主持嘅口頭禪開場
規則2(數據)引用具體數字引用咗完全老作嘅數字,語氣仲極之篤定
規則3(口頭禪)標誌性短語列表每條短語每集用咗5到13次

規則明明喺度。LLM讀過晒。但呢啲規則嘅效力只係相當於建議,而唔係要求。

就喺呢個時候我醒覺:LLM將我嘅規則當作「風格背景資訊」——而唔係「可執行嘅約束條件」。


模式:Context vs. Command

諗下你閱讀唔同類型文本嘅方式。如果我畀張餐廳menu你,你會當佢係行動資訊咁睇。如果我畀篇關於意粉歷史嘅Wikipedia文章你,你會當佢係背景知識咁睇。

LLM對prompt嘅處理都係類似。當規則出現喺標記為「STYLE GUIDELINES」、「HOST INTERACTION PATTERN」或者「RULES FOR SEGMENTS」嘅段落嗰陣,個model會當佢係環境資訊——為回答提供色彩嘅背景,但唔構成約束。

當規則出現喺標記為「CRITICAL IMPROVEMENTS REQUIRED」或者「SPECIFIC PHRASE LIMITS」嘅段落嗰陣,個model會當佢係可執行嘅命令——必須驗證同糾正嘅事項。

呢個洞察嘅關鍵唔係「CRITICAL」或者「REQUIRED」呢啲字。關鍵係規則喺pipeline嘅邊個位置


解決方案:令review step強制執行generation step忽略嘅嘢

我個pipeline有兩個LLM call:

  1. Generation step —— 以對話指南做背景,逐段撰寫script
  2. Review step —— 通讀完整嘅script並加以改進

最初,所有規則都喺generation step度。Review step只有通用嘅反重複規則(「唔好講兩次'That's fascinating'」),完全以英文為中心,對我啲主持特有嘅口頭禪或者結構要求一無所知。

個fix係結構性嘅,唔係詞彙性嘅。我將enforcement轉移咗去review step——因為嗰度可以同時睇到完整script。

改變如下:

Before:規則喺generation prompt度(被無視)

STYLE GUIDELINES:
0. NEVER REPEAT THE SAME OPENING...
1. EMOTIONAL START...
2. DATA-GROUNDING...
3. CATCHPHRASES: "You see that?!" ...

After:規則被提取並注入review prompt(強制執行)

CRITICAL IMPROVEMENTS REQUIRED ACROSS THE ENTIRE SCRIPT:

2a. ENFORCE STYLE GUIDELINES' STRUCTURAL RULES:
     The STYLE GUIDELINES above contain specific requirements 
     about segment structure. These are REQUIREMENTS, not suggestions.
     - If the guidelines say "X of Y segments must vary," CHANGE 
       segments that violate this.
     - Check how EACH segment opens. If 4+ out of 5 open identically, 
       VARY at least 2.

3b. LOCALE-SPECIFIC PHRASE LIMITS (extracted from host profiles — 
    MAXIMUM 2 TIMES each across entire script):
    - "Trời ơi" / "Trời má" — max 4x combined
    - "Có một lý do sâu hơn" — max 2x
    - "Mày thấy chưa?!" — max 2x
    ...

呢度發生咗兩件事:

  1. 結構規則從context升級為command——被重新表述為「強制執行」同「修改違反此規則嘅段落」,而唔係「呢個係推薦模式」

  2. 口頭禪從主持profile中提取出嚟,以明確嘅限制而非建議列表嘅形式呈現。"Catchphrases: here are some"變成咗"These phrases: MAXIMUM 2 TIMES each。"

兩處修改都喺review prompt度,而唔係generation prompt度。呢個係關鍵嘅architecture決策。Generation step將style guide作為context接收——佢需要個性色彩。Review step將規則作為enforcement command接收——佢需要compliance權限。


提取細節(點解呢個喺7種語言都work)

我唔想手動maintain每種語言嘅phrase list。每次調整主持profile,我都要同時update review prompt。呢種drift足以毁咗一個solo developer嘅產品。

於是我寫咗一個細extraction function,喺review時parse主持profile。每種語言嘅profile都有一個帶標準label嘅口頭禪section:

  • 越南文:Câu cửa miệng:
  • 日文:口癖:
  • 西班牙文:Latiguillos:
  • 法文:Phrases fétiches:
  • 韓文:입버릇:
  • 中文:口头禅:

個function搵到對應嘅label,提取其後所有嘅引用string,並format為可執行嘅限制:

@staticmethod
def _extract_catchphrase_limits(host_profiles: str) -> str:
    patterns = [
        (r'Câu cửa miệng:?', r'"([^"]+)"'),       # Vietnamese
        (r'口癖:?',             r'「([^」]+)」'),    # Japanese
        (r'Latiguillos:?',      r'"([^"]+)"'),       # Spanish
        # ... etc for all 7 languages
    ]
    limits = []
    for marker_pattern, quote_pattern in patterns:
        match = re.search(marker_pattern, host_profiles)
        if match:
            phrases = re.findall(quote_pattern, host_profiles[match.end():])
            for phrase in phrases:
                limits.append(f'   - "{phrase}" — max 2x')
    return "\n".join(limits)

而家,當我edit主持profile、修改佢哋嘅口頭禪時,review prompt會自動update。冇drift。冇漏咗嘅語言。


實際fix咗邊啲問題(用數據說話)

以下係fix前同fix後生成嘅episode之間嘅變化:

指標Fix前Fix後
"Trời ơi"次數(quota:最多4次)13次越南文未測試,但日文中所有4個口頭禪均在quota內
"Có một lý do sâu hơn"(quota:最多2次)5次喺對應嘅日文測試中喺quota內
老作統計數據(xG、控球率、陣型闊度)4個老作嘅數字零個老作嘅數字
相同模式嘅段落開頭6/6完全一樣日文中仍然係5/5——見下文
越南/日本關聯保留1/4存活(review刪除咗3個)11/11存活
主持口吻cross-contamination雙方互相使用對方嘅phrase清晰分離

口頭禪quota、反老作規則同localization保留都已經奏效。主持profile而家能夠足夠清晰咁表達每位主持嘅個性,LLM唔再混淆邊個該講咩。


仲有邊啲問題

有一條規則仍然fail:結構多樣性。對話指南話「5個段落中至少有2個必須使用唔同嘅結構入口。」Fix後,日文episode仍然以完全一樣嘅方式打開每一個段落:「いやー、健一さん!」——一集裏面出現咗五次。

呢個唔係prompt enforcement嘅問題。呢個係architecture嘅問題

Generation step獨立生成每個segment。Segment 3唔知道segment 1同2係以情緒化主持嘅口頭禪開頭嘅。每個segment都用同一個對話指南獨立生成,所以每個segment都做出同樣嘅「用情緒化主持開場」嘅決定。

Review step理應能夠發現呢一點——佢可以同時睇到完整script。而且我都加咗明確嘅enforcement language,要求佢變化開場方式。但係run review嘅Gemini 3.5 Flash顯然覺得重組segment開場比削減口頭禪或者soften老作聲明更困難。開場嘅多樣性需要regenerate部分內容,而唔係單單trim或者remove。呢個對model嚟講係更heavy嘅task。

我仲喺度處理緊呢個問題——可能需要更強嘅review model,或者重新設計pipeline structure,令segment之間share開場狀態。更廣泛嘅啟示係:**prompt enforcement冇辦法fix architecture問題。**如果pipeline structure本身令規則無法被遵守,喺prompt度寫再多「CRITICAL」或者「MANDATORY」都救唔到你。


Framework:每條規則問自己三個問題

經過今次經驗,我而家對每一個system prompt都用三個問題做audit:

1. 呢條規則放喺邊度——generation定係review? 關於個性同tone嘅規則放喺generation。關於compliance、consistency同structure嘅規則放喺review。如果一條規則同時涉及兩者(例如口頭禪——佢係個性嘅體現但需要限制),就兩邊都放。

2. 呢條規則嘅措辭係context定係command? 「呢啲係口頭禪」係context。「每條最多2次」係command。同一條規則需要兩種形式——generation step需要知道口頭禪係咩,review step需要強制執行佢哋出現嘅frequency。

3. 個pipeline真係能夠執行呢條規則嗎? 逐segment生成冇辦法強制執行跨segment嘅多樣性。任何prompt都無法解決呢個問題。你需要將規則移到review step(能夠睇到完整script),或者重新設計pipeline,令segment之間share狀態。

呢個framework唔單止適用於podcast generation。佢適用於任何multi-step LLM pipeline——content generation、code review、document summarization,任何有單獨嘅generation同quality control pass嘅場景。


我仲喺度持續iterate緊,但如果你正在build你嘅第一個multi-step LLM pipeline:至少分成兩個step。第一個step帶着個性同自由度生成——畀佢context、example、tone guidance。第二個step帶着精確性同enforcement review——畀佢明確嘅limit、compliance check同修改嘅authority。

Generation step應該好似同creative collaborator做briefing咁。Review step應該好似將checklist交畀editor咁。

而當你兩樣都做咗之後,規則仍然被無視,先問architecture嘅問題。係prompt嘅問題,定係pipeline嘅問題?


常見問題

呢個對單一prompt setup(冇pipeline)適用嗎?

適用,但作用有限。喺單一prompt度,你要求同一個model同時具有創造性同compliance——兩者衝突時,創造性永遠贏compliance。即使喺單一prompt度,將instruction分成「context」section同明確嘅「constraint」section都有幫助。但係天花板係存在嘅。兩個帶住唔同instruction嘅獨立call幾乎總是優於一次。

你點解唔直接將generation prompt嘅規則寫得更強硬?

我試過。我加咗「MANDATORY」、「CRITICAL」、「NEVER」,全大寫寫滿晒。Generation step有太多互相競爭嘅demand——佢要同時做到engaging、聽落natural、diverse、locally authentic,仲要compliant。當個model必須喺「聽落似一個興奮嘅越南football fan」同「只講兩次'Trời ơi'」之間做選擇嗰陣,個性永遠贏。Review step冇呢種衝突——佢唯一嘅job就係enforce。

Review step用緊咩model?

Gemini 3.5 Flash(出於cost考慮——review喺7種語言所有episode上行)。佢能夠好好處理簡單嘅enforcement(削減口頭禪、soften老作stat)。但佢喺需要content regeneration嘅task上吃力,例如重組segment開場。更強嘅model會有幫助,但我仲未能夠justify個cost。


我利用夜晚同weekend solo開發DIALØGUE(對話)——一個AI podcast平台。口頭禪extraction同review prompt修改嘅code係open source嘅——你可以喺我嘅Podcast Engine repo度睇到完整嘅system prompt同enforcement logic。我喺度記錄一路上學到嘅嘢。

如果你遇過類似嘅問題——規則被讀取但冇被執行——我好有興趣想知:嗰條規則係咩,佢喺你個pipeline嘅邊個位置?

就係咁多啦。

祝好,Chandler