May na-discover akong nakakahiya last week.
Ang AI podcast pipeline ko may elaborate na system prompt — isang "dialogue guide" — na ilang araw kong ginawa. Sinasabi nito sa hosts (dalawang AI-generated football commentators) kung paano mag-usap sa isa't isa. Huwag ulitin ang opening. Iba-ibahin ang structure sa bawat segment. Gumamit ng catchphrases nang matipid. Huwag mag-imbento ng statistics.
Binasa ng LLM ang bawat salita. Tapos hindi sinunod halos lahat.
Ang Vietnamese host nagsabi ng "Trời ơi" (Oh my god) ng 13 beses sa isang episode. Ang Japanese host nagbukas ng bawat segment gamit ang "いやー、健一さん!" (Well, Kenichi-san!). Ang English host confident na nag-cite ng xG 0.35 at 65% possession — mga numerong wala sa database ko.
Ang prompt ay magalang na kinilala. At pagkatapos, binalewala.
Ito ang pinaka-useful na natutunan ko tungkol sa prompt engineering: May dalawang reading mode ang LLMs, at ibang-iba ang treatment nila sa bawat isa.
Ang Problema ng Dalawang Reading Mode
Ganito ang itsura ng original dialogue guide ko. Na-translate ko ang Vietnamese version sa English dahil pareho lang ang structure:
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."
Mukhang thorough, 'di ba? Akala ko talaga nagawa ko na ang dapat gawin.
Pero nung binasa ko ang actual generated scripts, ito ang nangyari:
| Rule | Ang sabi ng guide | Ang ginawa ng LLM |
|---|---|---|
| Rule 0 (never repeat) | Iba-ibahin ang opening | Bawat segment nagbukas gamit catchphrase ng emotional host |
| Rule 2 (data) | Mag-cite ng specific numbers | Nag-cite ng imbentong numbers na may total authority |
| Rule 3 (catchphrases) | Listahan ng signature phrases | Ginamit bawat phrase ng 5–13 beses per episode |
Nandiyan ang rules. Binasa ng LLM. Pero parang suggestion lang ang bigat nila, hindi requirement.
Dito ko na-realize: nire-process ng LLM ang rules ko bilang "style context" — hindi bilang "enforceable constraints."
Ang Pattern: Context vs. Command
Isipin mo kung paano ka magbasa ng iba't ibang uri ng text. Kung bibigyan kita ng restaurant menu, binabasa mo ito bilang impormasyong gagamitin. Kung bibigyan kita ng Wikipedia article tungkol sa history ng pasta, binabasa mo ito bilang background knowledge.
Ganyan din ang ginagawa ng LLMs sa prompts. Kapag lumabas ang rules sa section na may label na "STYLE GUIDELINES" o "HOST INTERACTION PATTERN" o "RULES FOR SEGMENTS," tinuturing ng model ang mga ito bilang ambient information — context na nagkukulay sa response pero hindi ito kinokontrol.
Kapag lumabas ang rules sa section na may label na "CRITICAL IMPROVEMENTS REQUIRED" o "SPECIFIC PHRASE LIMITS," tinuturing ng model ang mga ito bilang enforceable commands — mga bagay na dapat i-verify at i-correct.
Ang insight hindi tungkol sa mga salitang "critical" o "required." Ito ay tungkol sa kung saan sa pipeline nakatira ang rule.
Ang Fix: Hayaan ang Review Step na Mag-enforce ng Kung Ano ang Ini-ignore ng Generation Step
Ang pipeline ko may dalawang LLM calls:
- Generation step — sinusulat ang script segment by segment, gamit ang dialogue guide bilang context
- Review step — binabasa ang buong assembled script at pinapaganda ito
Sa generation step nakalagay lahat ng rules ko. Ang review step may generic anti-repetition rules ("huwag sabihin ang 'That's fascinating' nang dalawang beses") na English-centric lang at walang alam tungkol sa host catchphrases o structural requirements.
Structural ang fix, hindi lexical. Nilipat ko ang enforcement sa review step, kung saan nakikita ang buong script nang sabay-sabay.
Ito ang nagbago:
Bago: Rules sa generation prompt (hindi sinusunod)
STYLE GUIDELINES:
0. NEVER REPEAT THE SAME OPENING...
1. EMOTIONAL START...
2. DATA-GROUNDING...
3. CATCHPHRASES: "You see that?!" ...
Pagkatapos: Rules na-extract at in-inject sa review prompt (sinusunod)
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
...
Dalawang bagay ang nangyari dito:
-
Ang structural rules ay na-promote mula context papuntang command — ni-rephrase bilang "ENFORCE this" at "CHANGE segments that violate this" imbes na "ito ang preferred pattern"
-
Ang catchphrases ay na-extract mula sa host profiles at ipinakita bilang explicit limits, hindi bilang listahan ng suggestions. "Catchphrases: ito ang ilan" naging "Ang mga phrases na ito: MAXIMUM 2 TIMES bawat isa."
Parehong pagbabago nasa review prompt, hindi sa generation prompt. Iyon ang key architectural decision. Ang generation step nakukuha ang style guide bilang context — kailangan nito ang personality flavor. Ang review step nakukuha ang rules bilang enforcement — kailangan nito ang compliance mandate.
Ang Extraction Detail (Bakit Ito Gumagana Sa 7 Languages)
Hindi ko gustong i-maintain ang per-language phrase lists manually. Tuwing ginagalaw ko ang host profile, kailangan ko ring i-update ang review prompt. Iyong klaseng drift na pumapatay sa produkto ng solo developer.
Kaya nagsulat ako ng maliit na extraction function na nagpa-parse ng host profiles sa review time. Ang profile ng bawat locale may catchphrase section na may standard label:
- Vietnamese:
Câu cửa miệng: - Japanese:
口癖: - Spanish:
Latiguillos: - French:
Phrases fétiches: - Korean:
입버릇: - Chinese:
口头禅:
Hinahanap ng function ang label na iyon, ine-extract ang anumang quoted strings na sumusunod, at pino-format bilang enforceable limits:
@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)
Ngayon kapag nag-edit ako ng host profile at binago ang catchphrases, awtomatikong nag-a-update ang review prompt. Walang drift. Walang nakakalimutang language.
Kung Ano Talaga Ang Na-fix Nito (May Numbers)
Ito ang nagbago sa pagitan ng episode na na-generate bago ang mga fix na ito at ng na-generate pagkatapos:
| Metric | Bago | Pagkatapos |
|---|---|---|
| "Trời ơi" count (quota: max 4) | 13 | Hindi pa na-test sa vi, pero sa ja: lahat ng 4 catchphrases pasok sa quotas |
| "Có một lý do sâu hơn" (quota: max 2) | 5 | Pasok sa quota sa equivalent ja test |
| Imbentong statistics (xG, possession %, formation width) | 4 imbentong numbers | Walang imbentong numbers |
| Segment openings na pare-pareho ang pattern | 6/6 pare-pareho | 5/5 pa rin sa ja — tingnan sa baba |
| Vietnam/Japan connections na-preserve | 1/4 nakaligtas (na-strip ng review ang 3) | 11/11 nakaligtas |
| Host voice cross-contamination | Parehong ginamit ang phrases ng isa't isa | Malinaw na separation |
Ang catchphrase quotas, anti-fabrication rules, at localization preservation lahat gumana. Ang host profiles ngayon nagdi-dictate ng personalities ng hosts nang malinaw enough para hindi na malito ang LLM kung sino ang nagsasabi ng ano.
Kung Ano Pa Ang Hindi Ayos
Isang rule pa rin ang bagsak: structural variety. Ang dialogue guide nagsasabi na "at least 2 of 5 segments must use different structural entries." Pagkatapos ng mga fix, ang Japanese episode nagbukas pa rin ng bawat segment nang pare-pareho: "いやー、健一さん!" — limang beses sa isang episode.
Hindi ito prompt enforcement problem. Ito ay architecture problem.
Ang generation step nagpo-produce ng bawat segment nang independent. Walang kaalam-alam ang Segment 3 na ang segments 1 at 2 nagbukas gamit catchphrase ng emotional host. Bawat segment ay na-ge-generate in isolation gamit ang parehong dialogue guide, kaya bawat isa dumadating sa parehong desisyon na "buksan natin gamit ang emotional host."
Dapat mahuli ito ng review step — nakikita nito ang buong script nang sabay-sabay. At nagdagdag ako ng explicit enforcement language na nagsasabing i-iba ang openings. Pero ang Gemini 3.5 Flash, ang model na nagpapatakbo ng review, tila mas nahihirapang i-restructure ang segment openings kaysa mag-trim ng catchphrases o palambutin ang fabricated claims. Ang opening variety nangangailangan ng pag-regenerate ng parts ng content, hindi lang pag-tighten o pag-remove. Mas mabigat na trabaho iyon para sa model.
Pinagtatrabahuhan ko pa ito — malamang mas capable na review model o pipeline restructure kung saan nagse-share ng opening state ang segments. Ang mas malawak na punto: hindi kayang ayusin ng prompt enforcement ang architecture problems. Kung ang structure ng pipeline mo ginagawang imposibleng sundin ang isang rule, walang dami ng "CRITICAL" o "MANDATORY" sa prompts mo ang magliligtas sa'yo.
Ang Framework: Tatlong Tanong Para sa Bawat Rule
Pagkatapos ng experience na ito, ina-audit ko na ngayon ang bawat system prompt na sinusulat ko gamit ang tatlong tanong:
1. Saan nakatira ang rule na ito — generation o review? Rules tungkol sa personality at tone nasa generation. Rules tungkol sa compliance, consistency, at structure nasa review. Kung ang isang rule tumatawid sa pareho (tulad ng catchphrases — personality sila pero kailangan ng limits), ilagay sa pareho.
2. Naka-phrase ba ang rule na ito bilang context o command? "Ito ang mga catchphrases" ay context. "Maximum 2 times each" ay command. Pareho ang kailangan para sa iisang rule — kailangan malaman ng generation step kung ANO ang catchphrases, at kailangan i-enforce ng review step kung GAANO KADALAS lumabas ang mga ito.
3. Kaya ba talagang sundin ng pipeline ang rule na ito? Ang per-segment generation hindi kayang mag-enforce ng cross-segment variety. Walang prompt ang mag-aayos nito. Kailangan mong ilipat ang rule sa review step (na nakakakita ng buong script) o i-restructure ang pipeline para mag-share ng state ang segments.
Ang framework na ito hindi lang para sa podcast generation. Puwede ito sa kahit anong multi-step LLM pipeline — content generation, code review, document summarization, kahit anong may separate generation at quality-control passes.
Nag-i-iterate pa rin ako dito, pero kung binubuo mo ang first multi-step LLM pipeline mo: hatiin mo sa at least dalawang steps. Ang first step nag-ge-generate nang may personality at freedom — bigyan ito ng context, examples, tone guidance. Ang second step nagre-review nang may precision at enforcement — bigyan ito ng explicit limits, compliance checks, at awtoridad na baguhin ang mga bagay.
Ang generation step dapat parang nagbi-brief ka ng creative collaborator. Ang review step dapat parang nag-aabot ka ng checklist sa editor.
At kapag hindi pa rin sinusunod ang rules mo pagkatapos mong gawin ang pareho, unahin mong tanungin ang architecture question. Prompt ba ito, o pipeline?
Frequently Asked Questions
Puwede ba ito sa single-prompt setup (walang pipeline)?
Oo, pero limited. Sa iisang prompt, pinapagawa mo sa parehong model na maging creative at compliant nang sabay — palaging pipiliin ng model ang creativity over compliance kapag nagka-conflict ang dalawa. Kahit sa iisang prompt, nakakatulong kung paghiwalayin mo ang instructions mo sa "context" section at explicit "constraints" section. Pero may ceiling ka. Dalawang separate calls na may magkaibang instructions halos palaging mas maganda kaysa isa.
Bakit hindi mo na lang ginawang mas forceful ang rules sa generation prompt?
Sinubukan ko. Nagdagdag ako ng "MANDATORY," "CRITICAL," "NEVER," at all-caps lahat. Masyadong maraming competing demands ang generation step — sinusubukan nitong maging engaging, natural-sounding, varied, locally authentic, at compliant sabay-sabay. Kapag kailangang pumili ng model sa pagitan ng "tunog excited na Vietnamese football fan" at "'Trời ơi' dalawang beses lang," laging panalo ang personality. Walang ganoong conflict ang review step — ang tanging trabaho nito ay mag-enforce.
Anong model ang gamit mo para sa review step?
Gemini 3.5 Flash (para sa cost — tumatakbo ang review sa bawat episode sa 7 languages). Mahusay ito sa simpleng enforcement (pag-trim ng catchphrases, paglambot ng fabricated stats). Nahihirapan ito sa tasks na nangangailangan ng content regeneration, tulad ng pag-restructure ng segment openings. Makakatulong ang mas malakas na model doon, pero hindi ko pa na-justify ang gastos.
Binubuo ko ang DIALOGUE, isang AI podcast platform, mag-isa tuwing gabi at weekends. Ang code para sa catchphrase extraction at review prompt changes ay open — puwede mong basahin ang buong system prompt at enforcement logic sa podcast-engine repository ko. Sinusulat ko ang mga natututunan ko habang nasa journey.
Kung naka-encounter ka na ng similar problem — rules na binabasa pero hindi sinusunod — curious ako: ano ang rule, at saan ito nakatira sa pipeline mo?
Iyon lang muna mula sa akin.
Maraming salamat, Chandler