Production Prompt Engineering: Systematic Design and Version Control
Hardcoding prompts into your code is like baking environment variables directly into source. It’s convenient at first, but it will inevitably cause problems in production.
Advanced Prompting Techniques
Chain-of-Thought (CoT)
For complex problems, “show your reasoning” is far more accurate than “just give the answer.”
# Basic prompt (low accuracy)
basic = "Classify the risk clauses in the following contract as HIGH/MEDIUM/LOW."
# CoT prompt (high accuracy)
cot = """Analyze the following contract.
Analysis procedure:
1. Break the contract down clause by clause
2. List potential risk factors in each clause
3. Assess likelihood and impact
4. Finally classify as HIGH/MEDIUM/LOW and explain your reasoning
[Contract content]
{contract_text}
Follow the procedure above and analyze step by step:"""Few-shot Prompting
few_shot = """Classify the customer inquiry.
Examples:
Input: "I can't make a payment"
Output: {{"category": "billing", "priority": "high", "sentiment": "frustrated"}}
Input: "I'd like to know how to use this"
Output: {{"category": "inquiry", "priority": "low", "sentiment": "neutral"}}
Now classify:
Input: "{user_message}"
Output:"""Few-shot example principles: include edge cases, 3–5 examples is about right, and extract them from real failure cases.
XML Structuring (Claude-specific)
structured = """<system>
You are a code review expert.
Review criteria: security vulnerabilities, performance issues, readability
</system>
<context>
Language: Python, PEP 8 compliance, type hints required
</context>
<code_to_review>
{code}
</code_to_review>
<output_format>
Return JSON only:
{{"issues": [{{"type": "security|performance|readability", "line": number, "description": "description", "suggestion": "fix"}}],
"overall_score": 1-10}}
</output_format>"""Prompt Version Control
prompts/
├── customer_support/
│ ├── classify_v1.txt # keep old version
│ ├── classify_v2.txt # current production
│ └── classify_v3_test.txt # experiment in progress
└── manifest.yaml# manifest.yaml
prompts:
customer_support_classify:
production: v2
canary: v3_test
canary_percent: 5import yaml, random
from pathlib import Path
class PromptRegistry:
def __init__(self, prompts_dir="prompts"):
self.base = Path(prompts_dir)
with open(self.base / "manifest.yaml") as f:
self.manifest = yaml.safe_load(f)
def get(self, name, use_canary=False):
config = self.manifest["prompts"][name]
if use_canary and "canary" in config:
version = (config["canary"]
if random.random() < config.get("canary_percent", 0) / 100
else config["production"])
else:
version = config["production"]
category = name.rsplit("_", 1)[0].replace("_", "/")
return (self.base / f"{category}_{version}.txt").read_text(encoding="utf-8")Prompt A/B Testing
import hashlib
from dataclasses import dataclass
@dataclass
class PromptExperiment:
name: str
control_prompt: str
variant_prompt: str
traffic_split: float = 0.5
class PromptABTester:
def __init__(self, experiment):
self.exp = experiment
def get_prompt(self, user_id):
hash_val = int(hashlib.md5(f"{self.exp.name}:{user_id}".encode()).hexdigest(), 16)
bucket = (hash_val % 100) / 100
if bucket < self.exp.traffic_split:
return self.exp.control_prompt, "control"
return self.exp.variant_prompt, "variant"
def log_result(self, user_id, variant, metric):
print(f"exp={self.exp.name} user={user_id} variant={variant} metric={metric}")Defending Against Prompt Injection
def sanitize_user_input(user_input):
dangerous = [
"ignore previous instructions", "이전 지시를 무시",
"system prompt", "</system>", "<system>"
]
cleaned = user_input
for pattern in dangerous:
cleaned = cleaned.replace(pattern, "[FILTERED]")
return cleaned[:2000]Managing prompts like code makes change tracking, rollbacks, A/B testing, and team collaboration possible. This single practice significantly improves the stability of an LLM service.
Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
Comments
Be the first to comment.