Prompt Engineering Advanced: From "Writing Instructions" to "Designing Iteratable Prompt Systems"
In the previous article "An Impressive AI Product Manager Interview," we shared a candidate's story — he didn't write instructions directly, but used a layered framework, Few-shot design, and feedback loop to design Prompts, impressing the interviewer.
This article systematically explains the 5 key insights he demonstrated, each with practical cases and code examples, helping you level up from "writing instructions" to "designing prompt systems."
Insight 1: Deconstruction Ability — First Define "What Is Good"
Core Idea
Most people write Prompts by directly saying "Help me write an email." Excellent designers first ask: "What is a 'good email'?"
Deconstruction ability is breaking down the vague "good" into specific, executable dimensions.
Practical Case: Interview Invitation Email
Poor Prompt:
Help me write an interview invitation email.
Good Prompt (after deconstruction):
Please help me write an interview invitation email with the following requirements:
1. Tone: Professional but not cold, showing respect for the candidate
2. Structure:
- Opening: Thank the candidate for their time + brief company intro (1-2 sentences)
- Middle: Position highlights + candidate matching (why them)
- Closing: Interview arrangements + looking forward to reply
3. Length: 200-300 words
4. Avoid: "Salary negotiable," "Urgent hiring," excessive company hype
Deconstruction Checklist
For any Prompt, you can use this checklist to deconstruct:
| Dimension | Question | Example |
|---|---|---|
| Goal | What purpose should this generation achieve? | Persuade the candidate to accept the interview |
| Audience | Who is it for? What do they care about? | Candidates care about growth space and team atmosphere |
| Style | Formal/technical/concise? | Professional but not cold |
| Structure | What parts must be included? | Opening thanks + position highlights + interview arrangements |
| Constraints | What must not appear? | No "salary negotiable," no over-promising |
| Success Criteria | How to judge if the output is good? | Candidate response rate, interview attendance rate |
Insight 2: Framework Thinking — Four-Layer Structure for Quality Management
Core Idea
Divide Prompt into four layers, each responsible for one thing:
Layer 1: Role Setting → Who is AI, what capabilities does it have
Layer 2: Task Description → What goes in, what comes out
Layer 3: Format Specification → How to write, how long
Layer 4: Constraints → What not to write
Code Implementation: Four-Layer Prompt Template
class PromptTemplate:
"""Four-layer prompt template"""
def __init__(self, role, task, format_rules, constraints):
self.role = role # Layer 1: Role
self.task = task # Layer 2: Task
self.format = format_rules # Layer 3: Format
self.constraints = constraints # Layer 4: Constraints
def build(self, variables=None):
"""Build the final Prompt"""
prompt = f"""# Role
{self.role}
# Task
{self.task}
# Format Requirements
{self.format}
# Constraints
{self.constraints}
"""
if variables:
prompt = prompt.format(**variables)
return prompt
# Usage example: Interview invitation email generator
prompt = PromptTemplate(
role="""You are a senior HRBP with 8 years of recruiting experience in the internet industry.
You understand company culture and position requirements, and excel at writing professional yet warm recruiting copy.
Your goal is to make candidates feel valued while clearly conveying interview information.""",
task="""Please generate an interview invitation email for the following candidate:
- Candidate Name: {name}
- Position: {position}
- Interview Time: {interview_time}
- Location: {location}
- Position Highlights: {highlights}
- Candidate Match: {match_reason}""",
format="""Email structure:
1. Opening: Thank the candidate + one-line company introduction
2. Middle: Position highlights (why this role is worth joining) + candidate match (why them)
3. Closing: Interview time and location + looking forward to reply
Word count: 200-300 words
Tone: Professional but not cold, showing respect for the candidate""",
constraints="""Prohibited:
- "Salary negotiable" (see position details for salary info)
- "Urgent hiring" (avoid pressuring candidates)
- Excessive company hype (stay authentic and credible)
- Exceeding 300 words (avoid being verbose)"""
)
# Generate
final_prompt = prompt.build({
"name": "John Smith",
"position": "AI Product Manager",
"interview_time": "June 15, 2024, 2:00 PM",
"location": "Building Haidian District, Beijing",
"highlights": "Team from top tech companies, product has 10M+ users",
"match_reason": "3 years AI product experience with successful launch cases"
})
print(final_prompt)
Benefits of Four-Layer Structure
| Layer | Function | Benefit |
|---|---|---|
| Role | Set AI's identity and capabilities | More consistent output style |
| Task | Clarify input and output | Reduce ambiguity |
| Format | Specify structure and length | Unified output format |
| Constraints | Explicitly prohibit certain content | Avoid basic errors |
Insight 3: Example-Driven — The Decisive Role of Few-shot
Core Idea
Instead of using words to describe "please write warmly," give a real warm example for the model to imitate.
Few-shot = Show AI 1-3 real examples, let it learn "what is good."
Practical Comparison
Without Few-shot:
Please write a warm interview invitation email.
→ AI might generate overly enthusiastic, unprofessional content.
With Few-shot:
Please refer to the following high-conversion email examples for tone and structure, then generate a new invitation email:
【Example】
Hi Xiaoming,
Thank you for taking the time to learn about our Product Director position! Our team has been working in AI for 3 years, and our product just crossed 1M daily active users. We need someone with your growth experience.
Would you be available next Wednesday at 2 PM to chat? We'd love to hear your thoughts on AI product growth.
Looking forward to meeting!
Li Hua
Please generate an email for the following candidate: {candidate_info}
→ AI will mimic the example's tone: concise, sincere, attractive.
Code Implementation: Few-shot Management
class FewShotManager:
"""Few-shot example library management"""
def __init__(self):
self.examples = []
def add_example(self, input_text, output_text, score=1.0):
"""Add example, score represents conversion rate/satisfaction"""
self.examples.append({
"input": input_text,
"output": output_text,
"score": score
})
def get_top_k(self, k=2):
"""Get the top K highest-scoring examples"""
sorted_examples = sorted(self.examples, key=lambda x: x["score"], reverse=True)
return sorted_examples[:k]
def build_few_shot_prefix(self, k=2):
"""Build Few-shot prefix"""
top_examples = self.get_top_k(k)
prefix = "Here are some high-conversion email examples. Please reference their tone and structure:\n\n"
for i, ex in enumerate(top_examples, 1):
prefix += f"[Example {i}]\n{ex['output']}\n\n"
prefix += "Please refer to the above examples and generate an email for the following candidate:\n"
return prefix
# Usage
manager = FewShotManager()
manager.add_example("Candidate A", "Hi Xiaoming, thanks for taking the time...", score=0.85)
manager.add_example("Candidate B", "Hi Xiaohong, congratulations on passing the resume screening...", score=0.78)
manager.add_example("Candidate C", "Hi Xiaoli, loved your portfolio...", score=0.92)
prefix = manager.build_few_shot_prefix(k=2)
# Result: The 2 highest-scoring examples are selected
3 Key Principles of Few-shot
- Quality over quantity: 1 high-quality example > 5 average examples
- Diversity coverage: Examples should cover different scenarios (different positions, different candidate backgrounds)
- Continuous updates: Regularly replace low-scoring examples with new data
Insight 4: Feedback Loop — Turning "Dissatisfaction" into Optimization Signals
Core Idea
When users click "generate another version," this is not failure — it's data.
Feedback loop = Record user behavior → Analyze rejection reasons → Automatically optimize Prompt
Feedback Loop Design
User clicks "generate another version"
↓
Record rejected version characteristics (too wordy / too formal / not attractive)
↓
Update Prompt constraints
↓
Automatically avoid known issues when generating new version
Code Implementation: Feedback Loop System
class FeedbackLoop:
"""Prompt feedback loop"""
def __init__(self):
self.rejection_reasons = {
"too_long": 0,
"too_formal": 0,
"too_casual": 0,
"not_attractive": 0,
"too_short": 0
}
self.constraint_adjustments = {
"too_long": "Strictly control word count within 200 words",
"too_formal": "Warm tone, like talking to a friend",
"too_casual": "Maintain professionalism, avoid excessive colloquialism",
"not_attractive": "First 3 lines must highlight position highlights",
"too_short": "Include at least 3 paragraphs"
}
def record_rejection(self, reason):
"""Record rejection reason"""
if reason in self.rejection_reasons:
self.rejection_reasons[reason] += 1
def get_adjusted_constraints(self):
"""Adjust constraints based on feedback"""
constraints = []
for reason, count in self.rejection_reasons.items():
if count >= 2: # Same reason rejected 2+ times
constraints.append(self.constraint_adjustments[reason])
return constraints
def build_improved_prompt(self, base_prompt):
"""Build improved Prompt"""
adjustments = self.get_adjusted_constraints()
if not adjustments:
return base_prompt
adjustment_text = "\n\n# Based on user feedback, please pay special attention to:\n"
for adj in adjustments:
adjustment_text += f"- {adj}\n"
return base_prompt + adjustment_text
# Usage
loop = FeedbackLoop()
# Simulate user feedback
loop.record_rejection("too_long") # 1st time: too long
loop.record_rejection("too_formal") # 2nd time: too formal
loop.record_rejection("too_long") # 3rd time: too long again
# Get improved constraints
print(loop.get_adjusted_constraints())
# → ['Strictly control word count within 200 words', 'Warm tone, like talking to a friend']
Data Value of Feedback Loop
| Rejection Reason | Frequency | Optimization Action |
|---|---|---|
| Too verbose | 30% | Add word count limits |
| Too formal | 25% | Adjust role setting to "friend" |
| Not attractive | 20% | Add Few-shot examples |
| Incomplete info | 15% | Add required fields |
| Other | 10% | Manual analysis |
Insight 5: Product Mindset — Treating Prompt as a Product Iteration
Core Idea
Traditional mindset: Prompt is done once and for all.
Product mindset: Prompt is a core asset that needs A/B testing, version management, and continuous optimization.
Prompt Version Management
class PromptVersionManager:
"""Prompt version management"""
def __init__(self):
self.versions = []
def create_version(self, prompt_text, description, metrics=None):
"""Create new version"""
import hashlib
version_id = hashlib.md5(prompt_text.encode()).hexdigest()[:8]
self.versions.append({
"id": version_id,
"prompt": prompt_text,
"description": description,
"metrics": metrics or {},
"created_at": "2026-06-11"
})
return version_id
def get_best_version(self, metric="conversion_rate"):
"""Get the best performing version"""
return max(self.versions, key=lambda v: v["metrics"].get(metric, 0))
def ab_test(self, version_a_id, version_b_id):
"""A/B test two versions"""
version_a = next(v for v in self.versions if v["id"] == version_a_id)
version_b = next(v for v in self.versions if v["id"] == version_b_id)
return {
"version_a": version_a["metrics"],
"version_b": version_b["metrics"],
"winner": "A" if version_a["metrics"].get("conversion_rate", 0) >
version_b["metrics"].get("conversion_rate", 0) else "B"
}
# Usage
manager = PromptVersionManager()
v1 = manager.create_version(prompt_v1, "Basic: Simple instruction", {"conversion_rate": 0.15})
v2 = manager.create_version(prompt_v2, "Advanced: Layered framework", {"conversion_rate": 0.28})
v3 = manager.create_version(prompt_v3, "Complete: Layered + Few-shot + Feedback", {"conversion_rate": 0.42})
best = manager.get_best_version()
print(f"Best version: {best['description']}, Conversion rate: {best['metrics']['conversion_rate']:.0%}")
Prompt Productization Checklist
| Dimension | Check Item | Status |
|---|---|---|
| Version Management | Is there version history? | ☐ |
| A/B Testing | Are different Prompts tested regularly? | ☐ |
| Data Tracking | Is user feedback recorded? | ☐ |
| Iteration Mechanism | Is there an auto-optimization process? | ☐ |
| Quality Monitoring | Is output quality monitored? | ☐ |
| Documentation | Is Prompt design rationale documented? | ☐ |
Learning Path Recommendations
Beginner
- Course: DeepLearning.AI "ChatGPT Prompt Engineering" (Andrew Ng)
- Tools: OpenAI Playground, PromptPerfect
- Community: Prompt Engineering Guide, r/PromptEngineering
Intermediate
- Tutorials: LangChain official docs, LlamaIndex tutorials
- Tools: Coze, Dify's Prompt debugging features
- Books: "AI Product Manager's Prompt Practice Handbook," "Minimalist Guide to LLM Application Development"
Practice
- Start with simple tasks (summarization, classification, generation)
- Gradually increase complexity (multi-turn dialogue, Agent, tool calls)
- Build your own Prompt template library and example library
Summary
| Insight | Core | Action |
|---|---|---|
| Deconstruction Ability | First define "what is good" | Use checklist to break down fuzzy requirements |
| Framework Thinking | Four-layer structure for quality management | Role + Task + Format + Constraints |
| Example-Driven | Few-shot stabilizes output | Build high-quality example library |
| Feedback Loop | Turn dissatisfaction into data | Record rejection reasons, auto-optimize |
| Product Mindset | Prompt is core asset | Version management, A/B testing, continuous iteration |
One-sentence summary: Prompt Engineering is not "writing instructions" but "designing systems." Treat Prompt as a product, drive iteration with data, and you can truly unlock AI's potential.
📌 Related Reading:
- Interview case: An Impressive AI Product Manager Interview: I Knew He Understood Prompts the Moment He Spoke
- Vibe Coding series: 2026 Vibe Coding Tech Stack Selection Guide
