tech-prompt-engineering
診斷並強化 production 的 LLM prompt,防 injection 和格式漂移
中文翻譯
---
name: "tech-prompt-engineering"
description: "除錯並強化 production 的 LLM prompt:處理 prompt injection、輸出格式漂移、長 context 裡指令被遺忘,以及跨模型可攜性問題。當使用者已把 LLM 功能上線到 production,需要診斷輸出為什麼不一致、不安全,或在模型更新後退步時使用這個 skill,「不適用」於一般的「幫我把 prompt 寫好一點」這類問題。"
metadata:
category: "WP-11 通用技術"
tags: ["technology", "llm", "production", "debugging", "security"]
---
# Production Prompt Engineering
## 概述
這個 skill 處理的是「只會」在 production LLM 應用裡出現的失敗模式:prompt injection、輸出格式漂移、跨模型版本的無聲退步、長 context 裡的指令衰減,以及壓力下的幻覺。它「不是」few-shot 或 chain-of-thought 的教學,預設 agent 已經懂基本的 prompting 技巧。
## 何時使用
**觸發條件:**
- production 的 LLM 功能行為異常(不一致、不安全、格式漂移)
- 替多租戶應用設計 system prompt
- 強化 prompt,抵禦 injection 或 jailbreak 嘗試
- 診斷模型版本更新後的退步
**何時「不」使用:**
- 基本的「怎麼寫 prompt」,agent 本來就懂 few-shot、CoT、角色扮演
- 一次性的內容生成(直接寫 prompt 就好)
- RAG 架構設計(用 RAG 專用的 skill)
## 框架
```
IRON LAW: Treat User Input as Hostile by Default
(鐵律:預設把使用者輸入當成有敵意)
在 production 裡,使用者輸入「一定」會被拿來嘗試 prompt injection。
唯一可靠的防禦是結構性隔離:
1. System prompt 承載「所有」規則和行為(絕不信任使用者輸入能覆蓋它)
2. 使用者輸入「絕對不」直接串接進指令裡
3. 輸出在被下游使用「之前」,要先對照預期 schema 驗證
一個在 dev 用乾淨輸入跑得好好的 prompt,到了 production 碰上惡意輸入就會失敗。
```
## Production 失敗模式
| 失敗模式 | 可觀察的症狀 | 根本原因 | 解法 |
|--------------|-------------------|-----------|-----|
| **Prompt injection** | 使用者輸入覆蓋了 system 指令 | 指令和不受信任的輸入被串接在一起 | 結構性隔離:用 ChatML role;對 schema 驗證輸出;絕不使用容易被「ignore previous instructions」攻破的範本 |
| **格式漂移** | JSON 回應每 1000 次呼叫會壞 1 次 | 模型 temperature > 0 + 輸出沒有約束 | 約束式解碼(JSON mode、grammar)、schema 驗證 + 重試、調低 temperature |
| **指令衰減** | 規則一開始遵守,過了 N 輪就被忽略 | 長 context 把 system prompt 擠出注意力範圍 | 在「每一則」使用者訊息裡強化關鍵規則;用模型原生的 tool/system role;縮短 context |
| **無聲退步** | 同一個 prompt,模型更新後輸出變差 | 供應商更新了模型權重 | 鎖定模型版本;維護回歸測試集;滾動升級前先 A/B 測試 |
| **壓力下的幻覺** | 模型不確定時就捏造事實 | 沒有明確的「我不知道」退路 | 加上「If uncertain, respond with {null}. Do not guess.」+ 基於事實的約束 |
| **跨模型可攜性** | 在 GPT-4 上能跑,在 Claude/Gemini 上失敗 | 各模型專屬的 prompt 慣例 | 在所有目標模型上測試;避免用特定模型的 jailbreak;採用最大公約數的寫法 |
## 方法論
### 階段 1:重現失敗
收集:確切的輸入、確切的輸出、預期的輸出、模型 + 版本、temperature。在隔離環境(app 之外)重現,排除應用程式本身的 bug。
**關卡:** 失敗能在最小測試案例裡穩定重現。
### 階段 2:分類失敗模式
對照上面的表。多數 production 失敗都落在 6 個類別之一。不要用猜的,要找出是哪一種模式。
**關卡:** 失敗模式已分類,且有證據。
### 階段 3:套用針對性的修正
只修「那個特定」的失敗模式。不要整份 prompt 重寫,泛用式的重寫常常會帶出新的失敗模式。
**關卡:** 修正針對根本原因,不是症狀。
### 階段 4:建立回歸測試
把失敗案例加進回歸測試集。每次改 prompt 或更新模型版本前,都先跑一遍測試集。
**關卡:** 測試集能抓到原本的失敗,也能抓到之後的重蹈覆轍。
## 輸出格式
```markdown
# Prompt Debug Report: {Feature Name}
## Failure Reproduction
- Input: {exact input}
- Observed: {what happened}
- Expected: {what should have happened}
- Model: {name + version + temperature}
## Failure Mode
{One of: injection, format drift, instruction decay, silent regression, hallucination, cross-model}
## Root Cause
{Specific mechanism, not generic "prompt was bad"}
## Fix
{Targeted change with before/after prompt diff}
## Regression Test
{Test case added to prevent reintroduction}
```
## 常見陷阱
- **「Ignore previous instructions」只是開始**:現代的 injection 會用角色扮演("Pretend you are DAN...")、切換語言、Unicode 花招和編碼過的 payload。防禦需要輸入驗證「加上」輸出驗證,不是只靠指令的措辭。
- **Temperature 0 在多次呼叫間並不是確定性的**:就算 T=0,因為後端 GPU 的非確定性(batch 效應),不同次 API 呼叫的輸出還是可能不同。測試別依賴字串完全相等,改用語意或 schema 相等。
- **Few-shot 範例會蓋過你的指令**:如果範例給的是 500 字的回應,你卻說「要簡潔」,模型會照範例走。範例比指令「更強」。
- **System prompt 不是絕對的**:即使有 system prompt,夠惡意的使用者輸入還是能覆蓋行為。System prompt 是強烈的提示,不是安全邊界。要真正的安全,得靠輸出驗證和 sandbox。
- **供應商的模型更新是無聲的**:OpenAI 的 "gpt-4" 別名會在沒通知的情況下換權重。要鎖定有日期的版本(gpt-4-0613)才穩定,每次更新後都要重跑回歸測試。
- **Context window 大小 ≠ 有效 context**:128K context 的模型可能只對前 32K 和最後 4K 注意得好。關鍵指令要放在「開頭」和「結尾」,不要放中間("lost in the middle" 效應)。
## 參考資料
- Prompt injection 攻擊模式,見 `references/injection-patterns.md`
- 回歸測試框架,見 `references/regression-testing.md`
- 跨模型的 prompt 可攜性,見 `references/cross-model-testing.md`英文原文
---
name: "tech-prompt-engineering"
description: "Debug and harden production LLM prompts — handle prompt injection, output format drift, instruction forgetting in long contexts, and cross-model portability issues. Use this skill when the user ships an LLM-powered feature to production and needs to diagnose why outputs are inconsistent, unsafe, or regressed after model updates — NOT for basic 'write a better prompt' questions."
metadata:
category: "WP-11 通用技術"
tags: ["technology", "llm", "production", "debugging", "security"]
---
# Production Prompt Engineering
## Overview
This skill addresses the failure modes that appear ONLY in production LLM applications: prompt injection, output format drift, silent regression across model versions, instruction decay in long contexts, and hallucination under pressure. It is NOT a tutorial on few-shot or chain-of-thought — assume the agent already knows basic prompting techniques.
## When to Use
**Trigger conditions:**
- A production LLM feature is misbehaving (inconsistent, unsafe, format-drifting)
- Designing a system prompt for a multi-tenant application
- Hardening prompts against injection or jailbreak attempts
- Diagnosing regression after a model version update
**When NOT to use:**
- Basic "how do I write a prompt" — the agent already knows few-shot, CoT, role-play
- One-off content generation (just write the prompt directly)
- RAG architecture design (use a RAG-specific skill)
## Framework
```
IRON LAW: Treat User Input as Hostile by Default
In production, user input WILL be used to attempt prompt injection.
The only reliable defense is structural separation:
1. System prompt carries ALL rules and behavior (never trust user input to override)
2. User input is NEVER concatenated directly into instructions
3. Output is validated against an expected schema BEFORE being used downstream
A prompt that works in dev with clean input will fail in production with adversarial input.
```
## Production Failure Modes
| Failure Mode | Observable Symptom | Root Cause | Fix |
|--------------|-------------------|-----------|-----|
| **Prompt injection** | User input overrides system instructions | Instructions concatenated with untrusted input | Structural separation: use ChatML roles; validate outputs against schema; never use "ignore previous instructions" susceptible templates |
| **Format drift** | JSON response breaks 1/1000 calls | Model temperature > 0 + unconstrained output | Constrained decoding (JSON mode, grammar), schema validation + retry, lower temperature |
| **Instruction decay** | Rules followed early, ignored after N turns | Long context pushes system prompt out of attention | Reinforce critical rules in EACH user message; use model's native tool/system role; shorter contexts |
| **Silent regression** | Same prompt, worse output after model update | Provider updated model weights | Pin model version; maintain regression test suite; A/B test before rolling upgrades |
| **Hallucination under pressure** | Model invents facts when uncertain | No explicit "I don't know" escape hatch | Add "If uncertain, respond with {null}. Do not guess." + grounding constraint |
| **Cross-model portability** | Works on GPT-4, fails on Claude/Gemini | Model-specific prompt conventions | Test on all target models; avoid model-specific jailbreaks; use common-denominator patterns |
## Methodology
### Phase 1: Reproduce the Failure
Collect: exact input, exact output, expected output, model + version, temperature. Reproduce in isolation (outside the app) to rule out application bugs.
**Gate:** Failure reproduces consistently in a minimal test case.
### Phase 2: Classify the Failure Mode
Match against the table above. Most production failures fall into one of 6 categories. Don't guess — identify which mode applies.
**Gate:** Failure mode classified with evidence.
### Phase 3: Apply the Targeted Fix
Fix the SPECIFIC failure mode. Don't rewrite the whole prompt. Generic rewrites often introduce new failure modes.
**Gate:** Fix addresses root cause, not symptom.
### Phase 4: Build a Regression Test
Add the failing case to a regression test suite. Run the suite before every prompt change or model version update.
**Gate:** Test suite catches the original failure AND any reintroduction.
## Output Format
```markdown
# Prompt Debug Report: {Feature Name}
## Failure Reproduction
- Input: {exact input}
- Observed: {what happened}
- Expected: {what should have happened}
- Model: {name + version + temperature}
## Failure Mode
{One of: injection, format drift, instruction decay, silent regression, hallucination, cross-model}
## Root Cause
{Specific mechanism, not generic "prompt was bad"}
## Fix
{Targeted change with before/after prompt diff}
## Regression Test
{Test case added to prevent reintroduction}
```
## Gotchas
- **"Ignore previous instructions" is only the beginning**: Modern injection uses role-play ("Pretend you are DAN..."), language switching, Unicode tricks, and encoded payloads. Defense requires input validation AND output validation, not just instruction phrasing.
- **Temperature 0 is not deterministic across calls**: Even at T=0, outputs can vary across API calls due to backend GPU non-determinism (batch effects). Don't rely on exact string equality in tests; use semantic or schema equality.
- **Few-shot examples override your instructions**: If your examples show 500-word responses and you say "be concise", the model follows the examples. Examples are STRONGER than instructions.
- **System prompts are NOT absolute**: Even with a system prompt, sufficiently adversarial user input can override behavior. System prompts are a strong hint, not a security boundary. For real security, use output validation and sandboxing.
- **Provider model updates are silent**: OpenAI's "gpt-4" alias changes weights without notice. Pin to dated versions (gpt-4-0613) for stability. Rerun regression tests after every update.
- **Context window size ≠ effective context**: A 128K context model may only attend well to the first 32K and last 4K. Put critical instructions at START and END, not in the middle ("lost in the middle" effect).
## References
- For prompt injection attack patterns, see `references/injection-patterns.md`
- For regression testing frameworks, see `references/regression-testing.md`
- For cross-model prompt portability, see `references/cross-model-testing.md`